Mercurial > hg > nginx-ranges
changeset 248:acd2ec3541cb NGINX_0_4_9
nginx 0.4.9
*) Feature: the "set" parameter in the "include" SSI command.
*) Feature: the ngx_http_perl_module now tests the nginx.pm module
version.
line wrap: on
line diff
--- a/CHANGES +++ b/CHANGES @@ -1,4 +1,12 @@ +Changes with nginx 0.4.9 13 Oct 2006 + + *) Feature: the "set" parameter in the "include" SSI command. + + *) Feature: the ngx_http_perl_module now tests the nginx.pm module + version. + + Changes with nginx 0.4.8 11 Oct 2006 *) Bugfix: if an "include" SSI command were before another "include"
--- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,12 @@ +Изменения в nginx 0.4.9 13.10.2006 + + *) Добавление: параметр set в команде SSI include. + + *) Добавление: модуль ngx_http_perl_module теперь проверяет версию + модуля nginx.pm. + + Изменения в nginx 0.4.8 11.10.2006 *) Исправление: если до команды SSI include с параметром wait
--- a/README +++ b/README @@ -1,3 +1,4 @@ -Documentation is available at http://sysoev.ru/nginx/ only. +The Russian documentation is available at http://sysoev.ru/nginx/ +The English documentation is available at http://nginx.net
--- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.4.8" +#define NGINX_VERSION "0.4.9" +#define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin"
--- a/src/core/ngx_crc.h +++ b/src/core/ngx_crc.h @@ -10,15 +10,16 @@ /* 32-bit crc16 */ -static ngx_inline uint32_t ngx_crc(char *data, size_t len) +static ngx_inline uint32_t +ngx_crc(char *data, size_t len) { uint32_t sum; for (sum = 0; len; len--) { /* - * gcc 2.95.2 x86 and icc 7.1.006 compile that operator - * into the single "rol" opcode. + * gcc 2.95.2 x86 and icc 7.1.006 compile + * that operator into the single "rol" opcode, * msvc 6.0sp2 compiles it into four opcodes. */ sum = sum >> 1 | sum << 31;
--- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -144,10 +144,10 @@ ngx_http_addition_body_filter(ngx_http_r ctx->before_body_sent = 1; if (conf->before_body.len) { - if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) - == NGX_ERROR) - { - return NGX_ERROR; + rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0); + + if (rc == NGX_ERROR || rc == NGX_DONE) { + return rc; } } } @@ -168,10 +168,10 @@ ngx_http_addition_body_filter(ngx_http_r return rc; } - if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) - == NGX_ERROR) - { - return NGX_ERROR; + rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0); + + if (rc == NGX_ERROR || rc == NGX_DONE) { + return rc; } ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
--- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -135,7 +135,7 @@ ngx_http_autoindex_handler(ngx_http_requ { u_char *last, *filename, scale; off_t length; - size_t len, copy, allocated; + size_t len, copy, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; @@ -174,7 +174,8 @@ ngx_http_autoindex_handler(ngx_http_requ /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */ - last = ngx_http_map_uri_to_path(r, &path, NGX_HTTP_AUTOINDEX_PREALLOCATE); + last = ngx_http_map_uri_to_path(r, &path, &root, + NGX_HTTP_AUTOINDEX_PREALLOCATE); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; }
--- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -102,6 +102,7 @@ static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r) { char *failed; + size_t root; ngx_int_t rc; ngx_str_t path; ngx_file_info_t fi; @@ -152,7 +153,7 @@ ngx_http_dav_handler(ngx_http_request_t return rc; } - ngx_http_map_uri_to_path(r, &path, 0); + ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http delete filename: \"%s\"", path.data); @@ -219,7 +220,7 @@ ngx_http_dav_handler(ngx_http_request_t return rc; } - ngx_http_map_uri_to_path(r, &path, 0); + ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http mkcol path: \"%s\"", path.data); @@ -245,6 +246,7 @@ ngx_http_dav_put_handler(ngx_http_reques { char *failed; u_char *name; + size_t root; time_t date; ngx_err_t err; ngx_str_t *temp, path; @@ -252,7 +254,7 @@ ngx_http_dav_put_handler(ngx_http_reques ngx_file_info_t fi; ngx_http_dav_loc_conf_t *dlcf; - ngx_http_map_uri_to_path(r, &path, 0); + ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http put filename: \"%s\"", path.data);
--- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -395,6 +395,13 @@ ngx_http_fastcgi_handler(ngx_http_reques ngx_http_upstream_t *u; ngx_http_fastcgi_loc_conf_t *flcf; + if (r->subrequest_in_memory) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "ngx_http_fastcgi_module does not support " + "subrequest in memeory"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
--- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -62,6 +62,7 @@ ngx_http_flv_handler(ngx_http_request_t { u_char *p; off_t start, len; + size_t root; ngx_fd_t fd; ngx_int_t rc; ngx_uint_t level, i; @@ -94,7 +95,7 @@ ngx_http_flv_handler(ngx_http_request_t return rc; } - if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) { + if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; }
--- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -28,6 +28,8 @@ typedef struct { ngx_str_t path; ngx_str_t index; + size_t root; + ngx_uint_t tested; /* unsigned tested:1 */ } ngx_http_index_ctx_t; @@ -200,7 +202,7 @@ ngx_http_index_handler(ngx_http_request_ if (len > (size_t) (ctx->path.data + ctx->path.len - ctx->index.data)) { - last = ngx_http_map_uri_to_path(r, &ctx->path, len); + last = ngx_http_map_uri_to_path(r, &ctx->path, &ctx->root, len); if (last == NULL) { return NGX_ERROR; } @@ -291,7 +293,7 @@ ngx_http_index_handler(ngx_http_request_ uri.len = r->uri.len + ctx->index.len - 1; if (!clcf->alias) { - uri.data = ctx->path.data + r->root_length; + uri.data = ctx->path.data + ctx->root; } else { uri.data = ngx_palloc(r->pool, uri.len);
--- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -78,6 +78,10 @@ static ngx_int_t ngx_http_ssi_evaluate_s static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); +static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, + ngx_int_t rc); +static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, + ngx_int_t rc); static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r, @@ -197,11 +201,14 @@ static ngx_http_output_body_filter_pt static u_char ngx_http_ssi_string[] = "<!--"; static ngx_str_t ngx_http_ssi_none = ngx_string("(none)"); +static ngx_str_t ngx_http_ssi_null_string = ngx_null_string; + #define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0 #define NGX_HTTP_SSI_INCLUDE_FILE 1 #define NGX_HTTP_SSI_INCLUDE_WAIT 2 -#define NGX_HTTP_SSI_INCLUDE_STUB 3 +#define NGX_HTTP_SSI_INCLUDE_SET 3 +#define NGX_HTTP_SSI_INCLUDE_STUB 4 #define NGX_HTTP_SSI_ECHO_VAR 0 #define NGX_HTTP_SSI_ECHO_DEFAULT 1 @@ -221,6 +228,7 @@ static ngx_http_ssi_param_t ngx_http_ss { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 }, { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 }, { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 }, + { ngx_string("set"), NGX_HTTP_SSI_INCLUDE_SET, 0, 0 }, { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 }, { ngx_null_string, 0, 0, 0 } }; @@ -382,7 +390,6 @@ ngx_http_ssi_body_filter(ngx_http_reques ngx_uint_t i, index; ngx_chain_t *cl, **ll; ngx_table_elt_t *param; - ngx_connection_t *c; ngx_http_request_t *pr; ngx_http_ssi_ctx_t *ctx, *mctx; ngx_http_ssi_block_t *bl; @@ -801,24 +808,14 @@ ngx_http_ssi_body_filter(ngx_http_reques } } - c = r->connection; - rc = cmd->handler(r, ctx, params); - if (c->destroyed) { - return NGX_DONE; - } - if (rc == NGX_OK) { continue; } - if (rc == NGX_AGAIN) { - return NGX_AGAIN; - } - - if (rc == NGX_ERROR) { - return NGX_ERROR; + if (rc == NGX_DONE || rc == NGX_AGAIN || rc == NGX_ERROR) { + return rc; } } @@ -1538,6 +1535,7 @@ ngx_http_ssi_get_variable(ngx_http_reque ngx_uint_t key) { ngx_uint_t i; + ngx_list_part_t *part; ngx_http_ssi_var_t *var; ngx_http_ssi_ctx_t *ctx; @@ -1547,8 +1545,21 @@ ngx_http_ssi_get_variable(ngx_http_reque return NULL; } - var = ctx->variables->elts; - for (i = 0; i < ctx->variables->nelts; i++) { + part = &ctx->variables->part; + var = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + var = part->elts; + i = 0; + } + if (name->len != var[i].name.len) { continue; } @@ -1693,7 +1704,7 @@ ngx_http_ssi_evaluate_string(ngx_http_re ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the closing bracket in \"%V\" " "variable is missing", &var); - return NGX_ERROR; + return NGX_HTTP_SSI_ERROR; } if (var.len == 0) { @@ -1820,7 +1831,7 @@ invalid_variable: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid variable name in \"%V\"", text); - return NGX_ERROR; + return NGX_HTTP_SSI_ERROR; } @@ -1828,18 +1839,21 @@ static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_int_t rc; - ngx_str_t *uri, *file, *wait, *stub, args; - ngx_buf_t *b; - ngx_uint_t flags, i; - ngx_chain_t *out, *cl, *tl, **ll; - ngx_http_request_t *sr; - ngx_http_ssi_ctx_t *mctx; - ngx_http_ssi_block_t *bl; + ngx_int_t rc, key; + ngx_str_t *uri, *file, *wait, *set, *stub, args; + ngx_buf_t *b; + ngx_uint_t flags, i; + ngx_chain_t *cl, *tl, **ll; + ngx_http_request_t *sr; + ngx_http_ssi_var_t *var; + ngx_http_ssi_ctx_t *mctx; + ngx_http_ssi_block_t *bl; + ngx_http_post_subrequest_t *psr; uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]; file = params[NGX_HTTP_SSI_INCLUDE_FILE]; wait = params[NGX_HTTP_SSI_INCLUDE_WAIT]; + set = params[NGX_HTTP_SSI_INCLUDE_SET]; stub = params[NGX_HTTP_SSI_INCLUDE_STUB]; if (uri && file) { @@ -1855,6 +1869,13 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_HTTP_SSI_ERROR; } + if (set && stub) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"set\" and \"stub\" may not be used together " + "in \"include\" SSI command"); + return NGX_HTTP_SSI_ERROR; + } + if (wait) { if (uri == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -1878,10 +1899,10 @@ ngx_http_ssi_include(ngx_http_request_t uri = file; } - if (ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX) - != NGX_OK) - { - return NGX_HTTP_SSI_ERROR; + rc = ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX); + + if (rc != NGX_OK) { + return rc; } args.len = 0; @@ -1895,11 +1916,11 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_HTTP_SSI_ERROR; } - out = NULL; + psr = NULL; + + mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); if (stub) { - mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); - if (mctx->blocks) { bl = mctx->blocks->elts; for (i = 0; i < mctx->blocks->nelts; i++) { @@ -1917,9 +1938,16 @@ ngx_http_ssi_include(ngx_http_request_t found: + psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); + if (psr == NULL) { + return NGX_ERROR; + } + + psr->handler = ngx_http_ssi_stub_output; + if (bl[i].count++) { - ll = &out; + ll = (ngx_chain_t **) &psr->data; for (tl = bl[i].bufs; tl; tl = tl->next) { @@ -1952,17 +1980,61 @@ ngx_http_ssi_include(ngx_http_request_t } } else { - out = bl[i].bufs; + psr->data = bl[i].bufs; } } - rc = ngx_http_subrequest(r, uri, &args, &sr, out, flags); + if (set) { + key = 0; + + for (i = 0; i < set->len; i++) { + set->data[i] = ngx_tolower(set->data[i]); + key = ngx_hash(key, set->data[i]); + } + + psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); + if (psr == NULL) { + return NGX_ERROR; + } + + psr->handler = ngx_http_ssi_set_variable; + psr->data = ngx_http_ssi_get_variable(r, set, key); + + if (psr->data == NULL) { + + if (mctx->variables == NULL) { + mctx->variables = ngx_list_create(r->pool, 4, + sizeof(ngx_http_ssi_var_t)); + if (mctx->variables == NULL) { + return NGX_ERROR; + } + } + + var = ngx_list_push(mctx->variables); + if (var == NULL) { + return NGX_ERROR; + } + + var->name = *set; + var->key = key; + var->value = ngx_http_ssi_null_string; + psr->data = &var->value; + } + + flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; + } + + rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags); + + if (rc == NGX_DONE) { + return NGX_DONE; + } if (rc == NGX_ERROR) { return NGX_HTTP_SSI_ERROR; } - if (wait == NULL) { + if (wait == NULL && set == NULL) { return NGX_OK; } @@ -1981,6 +2053,48 @@ ngx_http_ssi_include(ngx_http_request_t static ngx_int_t +ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc) +{ + ngx_chain_t *out; + + if (rc == NGX_ERROR || r->connection->error || r->request_output) { + return rc; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "ssi stub output: \"%V?%V\"", &r->uri, &r->args); + + out = data; + + if (!r->header_sent) { + if (ngx_http_set_content_type(r) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_http_send_header(r) == NGX_ERROR) { + return NGX_ERROR; + } + } + + return ngx_http_output_filter(r, out); +} + + +static ngx_int_t +ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc) +{ + ngx_str_t *value = data; + + if (r->upstream) { + value->len = r->upstream->buffer.last - r->upstream->buffer.pos; + value->data = r->upstream->buffer.pos; + } + + return rc; +} + + +static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { @@ -2090,7 +2204,7 @@ static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_int_t key; + ngx_int_t key, rc; ngx_uint_t i; ngx_str_t *name, *value, *vv; ngx_http_ssi_var_t *var; @@ -2099,10 +2213,10 @@ ngx_http_ssi_set(ngx_http_request_t *r, mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); if (mctx->variables == NULL) { - mctx->variables = ngx_array_create(r->pool, 4, - sizeof(ngx_http_ssi_var_t)); + mctx->variables = ngx_list_create(r->pool, 4, + sizeof(ngx_http_ssi_var_t)); if (mctx->variables == NULL) { - return NGX_HTTP_SSI_ERROR; + return NGX_ERROR; } } @@ -2112,8 +2226,10 @@ ngx_http_ssi_set(ngx_http_request_t *r, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ssi set \"%V\" \"%V\"", name, value); - if (ngx_http_ssi_evaluate_string(r, ctx, value, 0) != NGX_OK) { - return NGX_HTTP_SSI_ERROR; + rc = ngx_http_ssi_evaluate_string(r, ctx, value, 0); + + if (rc != NGX_OK) { + return rc; } key = 0; @@ -2130,9 +2246,9 @@ ngx_http_ssi_set(ngx_http_request_t *r, return NGX_OK; } - var = ngx_array_push(mctx->variables); + var = ngx_list_push(mctx->variables); if (var == NULL) { - return NGX_HTTP_SSI_ERROR; + return NGX_ERROR; } var->name = *name; @@ -2209,8 +2325,10 @@ ngx_http_ssi_if(ngx_http_request_t *r, n ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "left: \"%V\"", &left); - if (ngx_http_ssi_evaluate_string(r, ctx, &left, flags) != NGX_OK) { - return NGX_HTTP_SSI_ERROR; + rc = ngx_http_ssi_evaluate_string(r, ctx, &left, flags); + + if (rc != NGX_OK) { + return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -2271,8 +2389,10 @@ ngx_http_ssi_if(ngx_http_request_t *r, n ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "right: \"%V\"", &right); - if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) { - return NGX_HTTP_SSI_ERROR; + rc = ngx_http_ssi_evaluate_string(r, ctx, &right, flags); + + if (rc != NGX_OK) { + return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
--- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -56,7 +56,7 @@ typedef struct { size_t value_len; - ngx_array_t *variables; + ngx_list_t *variables; ngx_array_t *blocks; unsigned conditional:2;
--- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -73,6 +73,7 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r) { u_char *last, *location; + size_t root; ngx_fd_t fd; ngx_int_t rc; ngx_uint_t level; @@ -112,7 +113,7 @@ ngx_http_static_handler(ngx_http_request * so we do not need to reserve memory for '/' for possible redirect */ - last = ngx_http_map_uri_to_path(r, &path, 0); + last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; }
--- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -17,7 +17,7 @@ our @EXPORT = qw( HTTP_SERVER_ERROR ); -our $VERSION = '0.4.0'; +our $VERSION = '0.4.9'; require XSLoader; XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -453,6 +453,7 @@ filename(r) CODE: dXSTARG; + size_t root; ngx_http_request_t *r; ngx_http_perl_ctx_t *ctx; @@ -463,7 +464,7 @@ filename(r) goto done; } - if (ngx_http_map_uri_to_path(r, &ctx->filename, 0) == NULL) { + if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) { XSRETURN_UNDEF; }
--- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -565,7 +565,9 @@ ngx_http_perl_create_interpreter(ngx_htt ngx_log_t *log) { int n; - char *embedding[6]; + STRLEN len; + SV *sv; + char *ver, *embedding[6]; PerlInterpreter *perl; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter"); @@ -634,6 +636,16 @@ ngx_http_perl_create_interpreter(ngx_htt goto fail; } + sv = get_sv("nginx::VERSION", FALSE); + ver = SvPV(sv, len); + + if (ngx_strcmp(ver, NGINX_VERSION) != 0) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "version " NGINX_VERSION " of nginx.pm is required, " + "but %s was found", ver); + goto fail; + } + if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) { goto fail; }
--- a/src/http/modules/perl/ngx_http_perl_module.h +++ b/src/http/modules/perl/ngx_http_perl_module.h @@ -11,6 +11,7 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> +#include <nginx.h> #include <EXTERN.h> #include <perl.h>
--- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -794,6 +794,7 @@ ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { + size_t root; ngx_int_t rc; ngx_str_t path; @@ -830,7 +831,7 @@ ngx_http_core_content_phase(ngx_http_req if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) { - if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) { + if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "directory index of \"%V\" is forbidden", &path); } @@ -1157,7 +1158,7 @@ ngx_http_output_filter(ngx_http_request_ u_char * ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path, - size_t reserved) + size_t *root_length, size_t reserved) { u_char *last; size_t alias; @@ -1178,7 +1179,7 @@ ngx_http_map_uri_to_path(ngx_http_reques if (clcf->root_lengths == NULL) { - r->root_length = clcf->root.len; + *root_length = clcf->root.len; path->len = clcf->root.len + reserved; @@ -1201,8 +1202,8 @@ ngx_http_map_uri_to_path(ngx_http_reques return NULL; } - r->root_length = path->len - reserved; - last = path->data + r->root_length; + *root_length = path->len - reserved; + last = path->data + *root_length; } last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1); @@ -1284,7 +1285,7 @@ ngx_http_auth_basic_user(ngx_http_reques ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr, - ngx_chain_t *out, ngx_uint_t flags) + ngx_http_post_subrequest_t *ps, ngx_uint_t flags) { ngx_connection_t *c; ngx_http_request_t *sr; @@ -1341,7 +1342,6 @@ ngx_http_subrequest(ngx_http_request_t * sr->method = NGX_HTTP_GET; sr->http_version = r->http_version; - sr->http_major = r->http_minor; sr->request_line = r->request_line; sr->uri = *uri; @@ -1353,9 +1353,8 @@ ngx_http_subrequest(ngx_http_request_t * ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http subrequest \"%V?%V\"", uri, &sr->args); - if (flags & NGX_HTTP_ZERO_IN_URI) { - sr->zero_in_uri = 1; - } + sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0; + sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; sr->unparsed_uri = r->unparsed_uri; sr->method_name = r->method_name; @@ -1365,9 +1364,9 @@ ngx_http_subrequest(ngx_http_request_t * return NGX_ERROR; } - sr->out = out; sr->main = r->main; sr->parent = r; + sr->post_subrequest = ps; sr->read_event_handler = ngx_http_request_empty_handler; sr->write_event_handler = ngx_http_request_empty_handler; @@ -1431,7 +1430,7 @@ ngx_http_subrequest(ngx_http_request_t * return NGX_AGAIN; } - return NGX_OK; + return NGX_DONE; }
--- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -301,12 +301,12 @@ ngx_int_t ngx_http_core_content_phase(ng ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r); ngx_int_t ngx_http_set_exten(ngx_http_request_t *r); u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name, - size_t reserved); + size_t *root_length, size_t reserved); ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r); ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr, - ngx_chain_t *out, ngx_uint_t flags); + ngx_http_post_subrequest_t *psr, ngx_uint_t flags); ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args);
--- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1476,26 +1476,8 @@ ngx_http_finalize_request(ngx_http_reque return; } - if (r != r->main - && rc != NGX_ERROR - && !r->connection->error - && !r->request_output - && r->out) - { - if (!r->header_sent) { - rc = ngx_http_set_content_type(r); - - if (rc == NGX_OK) { - rc = ngx_http_send_header(r); - - if (rc != NGX_ERROR) { - rc = ngx_http_output_filter(r, r->out); - } - } - - } else { - rc = ngx_http_output_filter(r, r->out); - } + if (r != r->main && r->post_subrequest) { + rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc); } if (rc == NGX_ERROR
--- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -47,7 +47,9 @@ #define NGX_HTTP_PARSE_INVALID_HEADER 13 + #define NGX_HTTP_ZERO_IN_URI 1 +#define NGX_HTTP_SUBREQUEST_IN_MEMORY 2 #define NGX_HTTP_OK 200 @@ -287,6 +289,15 @@ struct ngx_http_cleanup_s { }; +typedef ngx_int_t (*ngx_http_post_subrequest_pt)(ngx_http_request_t *r, + void *data, ngx_int_t rc); + +typedef struct { + ngx_http_post_subrequest_pt handler; + void *data; +} ngx_http_post_subrequest_t; + + typedef struct ngx_http_postponed_request_s ngx_http_postponed_request_t; struct ngx_http_postponed_request_s { @@ -330,8 +341,6 @@ struct ngx_http_request_s { ngx_uint_t method; ngx_uint_t http_version; - ngx_uint_t http_major; - ngx_uint_t http_minor; ngx_str_t request_line; ngx_str_t uri; @@ -346,6 +355,7 @@ struct ngx_http_request_s { ngx_http_request_t *main; ngx_http_request_t *parent; ngx_http_postponed_request_t *postponed; + ngx_http_post_subrequest_t *post_subrequest; uint32_t in_addr; ngx_uint_t port; @@ -359,8 +369,6 @@ struct ngx_http_request_s { ngx_http_variable_value_t *variables; - size_t root_length; - size_t limit_rate; /* used to learn the Apache compatible response length without a header */ @@ -405,6 +413,7 @@ struct ngx_http_request_s { unsigned request_body_file_log_level:3; unsigned fast_subrequest:1; + unsigned subrequest_in_memory:1; unsigned header_timeout_set:1; @@ -456,6 +465,7 @@ struct ngx_http_request_s { unsigned subrequests:8; /* used to parse HTTP headers */ + ngx_uint_t state; u_char *uri_start; u_char *uri_end; @@ -475,6 +485,9 @@ struct ngx_http_request_s { u_char *header_start; u_char *header_end; + unsigned http_minor:16; + unsigned http_major:16; + ngx_uint_t header_hash; ngx_uint_t lowcase_index; u_char lowcase_header[NGX_HTTP_LC_HEADER_LEN];
--- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -21,6 +21,7 @@ static void ngx_http_upstream_send_reque ngx_http_upstream_t *u); static void ngx_http_upstream_send_request_handler(ngx_event_t *wev); static void ngx_http_upstream_process_header(ngx_event_t *rev); +static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev); static void ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u); static void @@ -1061,6 +1062,12 @@ ngx_http_upstream_process_header(ngx_eve /* rc == NGX_OK */ + if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST + && r->subrequest_in_memory) + { + u->buffer.last = u->buffer.pos; + } + if (u->headers_in.status_n == NGX_HTTP_INTERNAL_SERVER_ERROR) { if (u->peer.tries > 1 @@ -1248,7 +1255,109 @@ ngx_http_upstream_process_header(ngx_eve u->length = NGX_MAX_SIZE_T_VALUE; } - ngx_http_upstream_send_response(r, u); + if (!r->subrequest_in_memory) { + ngx_http_upstream_send_response(r, u); + return; + } + + /* subrequest content in memory */ + + if (u->input_filter == NULL) { + u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; + u->input_filter = ngx_http_upstream_non_buffered_filter; + u->input_filter_ctx = r; + } + + if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + if (u->buffer.last - u->buffer.pos >= (ssize_t) u->length) { + if (u->input_filter(u->input_filter_ctx, 0) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + rev->handler = ngx_http_upstream_process_body_in_memory; + + ngx_http_upstream_process_body_in_memory(rev); +} + + +static void +ngx_http_upstream_process_body_in_memory(ngx_event_t *rev) +{ + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + + c = rev->data; + r = c->data; + u = r->upstream; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream process body on memory"); + + if (rev->timedout) { + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); + ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT); + return; + } + + b = &u->buffer; + + for ( ;; ) { + + size = b->end - b->last; + + if (size == 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "upstream buffer is too small to read repsonse"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + n = c->recv(c, b->last, size); + + if (n == NGX_AGAIN) { + break; + } + + if (n == 0 || n == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, n); + return; + } + + if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (!rev->ready) { + break; + } + } + + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + + if (rev->active) { + ngx_add_timer(rev, u->conf->read_timeout); + + } else if (rev->timer_set) { + ngx_del_timer(rev); + } }
--- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -852,9 +852,10 @@ static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + size_t root; ngx_str_t path; - if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) { + if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { return NGX_ERROR; }