Open vislee opened 7 years ago
ngx以前的版本代码11个阶段有个tryfile阶段,从1.13.3以后改为了NGX_HTTP_PRECONTENT_PHASE阶段,且新加了个mirror模块。
github master分支已经有该代码,nginx.org文档还没有说明。 1.13.4发布了该模块,同时文档也有了mirror模块的说明
mirror模块是以子请求的形式把原始请求镜像一份或多份。通过mirror来控制镜像的location,mirror_request_body 控制镜像请求是否镜像body。
mirror
mirror_request_body
唯一的问题是原始uri不会镜像,可以通过$request_uri变量取得原始请求的uri。
Syntax: mirror uri; Default: — Context: http, server, location
uri 是server下配置的location的uri,以子请求的形式把当前请求内容镜像到uri下的location。
Syntax: mirror_request_body on|off; Default: on Context: http, server, location
是否镜像body。
mirro模块存储指令的结构体为:
typedef struct { // ngx_str_t 数组 ngx_array_t *mirror; ngx_flag_t request_body; } ngx_http_mirror_loc_conf_t;
在阶段NGX_HTTP_PRECONTENT_PHASE添加了回调函数ngx_http_mirror_handler。
解析完请求行请求头后会调用到ngx_http_process_request 函数中,该函数修改了可读可写事件的回调后调用ngx_http_handler函数执行http的10个阶段。执行完10个阶段后调用ngx_http_run_posted_requests再执行子请求。
该模块首先从注册到precontent阶段的回调函数ngx_http_mirror_handler开始执行,该回调函数调用了ngx_http_subrequest向父请求posted_requests(sr->main->posted_requests)中添加了子请求。
执行完10个阶段后调用ngx_http_run_posted_requests函数执行子请求。子请求其实就是把当前请求的内容复制一份添加到当前请求的posted_requests上,重新执行http的10个阶段。
代码:
void ngx_http_process_request(ngx_http_request_t *r) { ...... c->read->handler = ngx_http_request_handler; c->write->handler = ngx_http_request_handler; r->read_event_handler = ngx_http_block_reading; ngx_http_handler(r); ngx_http_run_posted_requests(c); } void ngx_http_handler(ngx_http_request_t *r) { ...... // http可写事件回调 r->write_event_handler = ngx_http_core_run_phases; // 执行http的10个阶段 ngx_http_core_run_phases(r); } static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_mirror_ctx_t *ctx; ngx_http_mirror_loc_conf_t *mlcf; if (r != r->main) { return NGX_DECLINED; } mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); // 没有配置子请求uri if (mlcf->mirror == NULL) { return NGX_DECLINED; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler"); if (mlcf->request_body) { ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); if (ctx) { return ctx->status; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->status = NGX_DONE; ngx_http_set_ctx(r, ctx, ngx_http_mirror_module); rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } return ngx_http_mirror_handler_internal(r); } static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r) { ngx_str_t *name; ngx_uint_t i; ngx_http_request_t *sr; ngx_http_mirror_loc_conf_t *mlcf; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); name = mlcf->mirror->elts; for (i = 0; i < mlcf->mirror->nelts; i++) { // 创建子请求,并添加到父请求的posted_requests if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, NGX_HTTP_SUBREQUEST_BACKGROUND) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } sr->header_only = 1; sr->method = r->method; sr->method_name = r->method_name; } return NGX_DECLINED; } // 执行子请求 void ngx_http_run_posted_requests(ngx_connection_t *c) { ngx_http_request_t *r; ngx_http_posted_request_t *pr; for ( ;; ) { if (c->destroyed) { return; } r = c->data; pr = r->main->posted_requests; if (pr == NULL) { return; } r->main->posted_requests = pr->next; r = pr->request; ngx_http_set_log_request(c->log, r); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http posted request: \"%V?%V\"", &r->uri, &r->args); // 调用ngx_http_subrequest函数添加子请求设置的回调ngx_http_handler r->write_event_handler(r); } }
+1
概述
ngx以前的版本代码11个阶段有个tryfile阶段,从1.13.3以后改为了NGX_HTTP_PRECONTENT_PHASE阶段,且新加了个mirror模块。
github master分支已经有该代码,nginx.org文档还没有说明。 1.13.4发布了该模块,同时文档也有了mirror模块的说明
mirror模块是以子请求的形式把原始请求镜像一份或多份。通过
mirror
来控制镜像的location,mirror_request_body
控制镜像请求是否镜像body。唯一的问题是原始uri不会镜像,可以通过$request_uri变量取得原始请求的uri。
指令
代码
mirro模块存储指令的结构体为:
在阶段NGX_HTTP_PRECONTENT_PHASE添加了回调函数ngx_http_mirror_handler。
解析完请求行请求头后会调用到ngx_http_process_request 函数中,该函数修改了可读可写事件的回调后调用ngx_http_handler函数执行http的10个阶段。执行完10个阶段后调用ngx_http_run_posted_requests再执行子请求。
该模块首先从注册到precontent阶段的回调函数ngx_http_mirror_handler开始执行,该回调函数调用了ngx_http_subrequest向父请求posted_requests(sr->main->posted_requests)中添加了子请求。
执行完10个阶段后调用ngx_http_run_posted_requests函数执行子请求。子请求其实就是把当前请求的内容复制一份添加到当前请求的posted_requests上,重新执行http的10个阶段。
代码: