diff options
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_addition_filter_module.c | 228 | ||||
-rw-r--r-- | src/http/modules/ngx_http_chunked_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 14 | ||||
-rw-r--r-- | src/http/modules/ngx_http_memcached_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 22 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssi_filter_module.c | 63 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssi_filter_module.h | 10 | ||||
-rw-r--r-- | src/http/modules/perl/nginx.xs | 29 | ||||
-rw-r--r-- | src/http/modules/perl/ngx_http_perl_module.c | 49 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 5 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 2 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 17 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_variables.c | 29 |
14 files changed, 435 insertions, 38 deletions
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c new file mode 100644 index 000000000..efd622e5a --- /dev/null +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -0,0 +1,228 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_http.h> + + +typedef struct { + ngx_str_t before_body; + ngx_str_t after_body; +} ngx_http_addition_conf_t; + + +typedef struct { + unsigned before_body_sent:1; + unsigned after_body_sent:1; +} ngx_http_addition_ctx_t; + + +static ngx_int_t ngx_http_addition_filter_init(ngx_cycle_t *cycle); +static void *ngx_http_addition_create_conf(ngx_conf_t *cf); +static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_command_t ngx_http_addition_commands[] = { + + { ngx_string("add_before_body"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_addition_conf_t, before_body), + NULL }, + + { ngx_string("add_after_body"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_addition_conf_t, after_body), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_addition_filter_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_addition_create_conf, /* create location configuration */ + ngx_http_addition_merge_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_addition_filter_module = { + NGX_MODULE_V1, + &ngx_http_addition_filter_module_ctx, /* module context */ + ngx_http_addition_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + ngx_http_addition_filter_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; + + +static ngx_int_t +ngx_http_addition_header_filter(ngx_http_request_t *r) +{ + ngx_http_addition_ctx_t *ctx; + ngx_http_addition_conf_t *conf; + + if (r->headers_out.status != NGX_HTTP_OK || r != r->main) { + return ngx_http_next_header_filter(r); + } + + if (ngx_strncasecmp(r->headers_out.content_type.data, "text/html", + sizeof("text/html") - 1) + != 0) + { + return ngx_http_next_header_filter(r); + } + + conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); + + if (conf->before_body.len == 0 && conf->after_body.len == 0) { + return ngx_http_next_header_filter(r); + } + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module); + + ngx_http_clear_content_length(r); + ngx_http_clear_accept_ranges(r); + + return ngx_http_next_header_filter(r); +} + + +static ngx_int_t +ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + ngx_int_t rc; + ngx_uint_t last; + ngx_chain_t *cl; + ngx_http_addition_ctx_t *ctx; + ngx_http_addition_conf_t *conf; + + if (in == NULL || r->header_only) { + return ngx_http_next_body_filter(r, in); + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module); + + if (ctx == NULL) { + return ngx_http_next_body_filter(r, in); + } + + conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module); + + if (!ctx->before_body_sent) { + ctx->before_body_sent = 1; + + if (conf->before_body.len) { + if (ngx_http_subrequest(r, &conf->before_body, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + } + } + + last = 0; + + for (cl = in; cl; cl = cl->next) { + if (cl->buf->last_buf) { + cl->buf->last_buf = 0; + last = 1; + } + } + + rc = ngx_http_next_body_filter(r, in); + + if (rc == NGX_ERROR + || !last + || ctx->after_body_sent + || conf->after_body.len == 0) + { + return rc; + } + + if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + + ctx->after_body_sent = 1; + + return ngx_http_send_special(r, NGX_HTTP_LAST); +} + + +static ngx_int_t +ngx_http_addition_filter_init(ngx_cycle_t *cycle) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_addition_header_filter; + + ngx_http_next_body_filter = ngx_http_top_body_filter; + ngx_http_top_body_filter = ngx_http_addition_body_filter; + + return NGX_OK; +} + + +static void * +ngx_http_addition_create_conf(ngx_conf_t *cf) +{ + ngx_http_addition_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->before_body.len = 0; + * conf->before_body.date = NULL; + * conf->after_body.len = 0; + * conf->after_body.date = NULL; + */ + + return conf; +} + + +static char * +ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_addition_conf_t *prev = parent; + ngx_http_addition_conf_t *conf = child; + + ngx_conf_merge_str_value(conf->before_body, prev->before_body, ""); + ngx_conf_merge_str_value(conf->after_body, prev->after_body, ""); + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index d8d12088c..45110c59e 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -23,7 +23,7 @@ static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { NULL, /* merge server configuration */ NULL, /* create location configuration */ - NULL, /* merge location configuration */ + NULL /* merge location configuration */ }; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 66e221f2b..ee603d17d 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -170,7 +170,7 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = { static ngx_command_t ngx_http_fastcgi_commands[] = { { ngx_string("fastcgi_pass"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_fastcgi_pass, NGX_HTTP_LOC_CONF_OFFSET, 0, @@ -183,6 +183,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { offsetof(ngx_http_fastcgi_loc_conf_t, index), NULL }, + { ngx_string("fastcgi_ignore_client_abort"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort), + NULL }, + { ngx_string("fastcgi_connect_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -1470,6 +1477,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) */ conf->upstream.buffering = NGX_CONF_UNSET; + conf->upstream.ignore_client_abort = NGX_CONF_UNSET; conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; @@ -1520,6 +1528,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); + ngx_conf_merge_value(conf->upstream.ignore_client_abort, + prev->upstream.ignore_client_abort, 0); + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -1670,6 +1681,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->peers == NULL) { conf->peers = prev->peers; + conf->upstream.schema = prev->upstream.schema; } if (conf->params_source == NULL) { diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c index 89a568d2e..73c018ed9 100644 --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -517,6 +517,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) conf->upstream.cyclic_temp_file = 0; /* the hardcoded values */ + conf->upstream.buffering = 0; + conf->upstream.ignore_client_abort = 0; conf->upstream.send_lowat = 0; conf->upstream.bufs.num = 0; conf->upstream.busy_buffers_size = 0; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index f8dfdc4e1..e96ba042e 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -130,7 +130,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { static ngx_command_t ngx_http_proxy_commands[] = { { ngx_string("proxy_pass"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_proxy_pass, NGX_HTTP_LOC_CONF_OFFSET, 0, @@ -150,6 +150,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering), NULL }, + { ngx_string("proxy_ignore_client_abort"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort), + NULL }, + { ngx_string("proxy_connect_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -1415,6 +1422,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) */ conf->upstream.buffering = NGX_CONF_UNSET; + conf->upstream.ignore_client_abort = NGX_CONF_UNSET; conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; @@ -1468,6 +1476,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); + ngx_conf_merge_value(conf->upstream.ignore_client_abort, + prev->upstream.ignore_client_abort, 0); + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -1654,6 +1665,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->peers == NULL) { conf->peers = prev->peers; + + conf->host_header = prev->host_header; + conf->port_text = prev->port_text; + conf->upstream.schema = prev->upstream.schema; } @@ -2057,11 +2072,12 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if (NGX_PCRE) - if (clcf->regex) { + if (clcf->regex || clcf->noname) { if (plcf->upstream.uri.len) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"proxy_pass\" may not have URI part in " - "location given by regular expression"); + "location given by regular expression or " + "inside the \"if\" statement"); return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 1b528f7fb..f116634e8 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -13,6 +13,7 @@ #define NGX_HTTP_SSI_DATE_LEN 2048 #define NGX_HTTP_SSI_ADD_PREFIX 1 +#define NGX_HTTP_SSI_ADD_ZERO 2 typedef struct { @@ -247,8 +248,12 @@ static ngx_http_ssi_command_t ngx_http_ssi_commands[] = { { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 }, { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 }, - { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 }, - { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, 1, 0 }, + { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params, + NGX_HTTP_SSI_COND_IF, 0 }, + { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, + NGX_HTTP_SSI_COND_IF, 0 }, + { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, + NGX_HTTP_SSI_COND_ELSE, 0 }, { ngx_null_string, NULL, NULL, 0, 0 } }; @@ -523,7 +528,17 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) continue; } - if (!ctx->output && !cmd->conditional) { + if (cmd->conditional + && (ctx->conditional == 0 + || ctx->conditional > cmd->conditional)) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid context of SSI command: \"%V\"", + &ctx->command); + goto ssi_error; + } + + if (!ctx->output && cmd->conditional == 0) { continue; } @@ -926,6 +941,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx) ctx->key = ngx_hash(ctx->key, ch); ctx->params.nelts = 0; + state = ssi_command_state; break; } @@ -1565,7 +1581,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } } - p = ngx_palloc(r->pool, len); + p = ngx_palloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0)); if (p == NULL) { return NGX_ERROR; } @@ -1809,13 +1825,26 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, u_char *p, *last; ngx_str_t *expr, left, right; ngx_int_t rc; - ngx_uint_t negative, noregex; + ngx_uint_t negative, noregex, flags; #if (NGX_PCRE) ngx_str_t err; ngx_regex_t *regex; u_char errstr[NGX_MAX_CONF_ERRSTR]; #endif + if (ctx->command.len == 2) { + if (ctx->conditional) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the \"if\" command inside the \"if\" command"); + return NGX_HTTP_SSI_ERROR; + } + } + + if (ctx->output_chosen) { + ctx->output = 0; + return NGX_OK; + } + expr = params[NGX_HTTP_SSI_IF_EXPR]; left.data = expr->data; @@ -1857,11 +1886,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, if (p == last) { if (left.len) { ctx->output = 1; + ctx->output_chosen = 1; } else { ctx->output = 0; } + ctx->conditional = NGX_HTTP_SSI_COND_IF; + return NGX_OK; } @@ -1887,11 +1919,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } noregex = 0; + flags = NGX_HTTP_SSI_ADD_ZERO; last--; p++; } else { noregex = 1; + flags = 0; + + if (p < last - 1 && p[0] == '\\' && p[1] == '/') { + p++; + } } right.len = last - p; @@ -1900,7 +1938,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "right: \"%V\"", &right); - if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) { + if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } @@ -1948,11 +1986,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, if ((rc == 0 && !negative) || (rc != 0 && negative)) { ctx->output = 1; + ctx->output_chosen = 1; } else { ctx->output = 0; } + ctx->conditional = NGX_HTTP_SSI_COND_IF; + return NGX_OK; invalid_expression: @@ -1968,7 +2009,13 @@ static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ctx->output = !ctx->output; + if (ctx->output_chosen) { + ctx->output = 0; + } else { + ctx->output = 1; + } + + ctx->conditional = NGX_HTTP_SSI_COND_ELSE; return NGX_OK; } @@ -1979,6 +2026,8 @@ ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { ctx->output = 1; + ctx->output_chosen = 0; + ctx->conditional = 0; return NGX_OK; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h index 5337e942a..eff236050 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -20,6 +20,10 @@ #define NGX_HTTP_SSI_PARAMS_N 4 +#define NGX_HTTP_SSI_COND_IF 1 +#define NGX_HTTP_SSI_COND_ELSE 2 + + typedef struct { ngx_hash_t hash; ngx_hash_keys_arrays_t commands; @@ -54,7 +58,9 @@ typedef struct { ngx_array_t variables; - ngx_uint_t output; /* unsigned output:1; */ + unsigned conditional:2; + unsigned output:1; + unsigned output_chosen:1; void *value_buf; ngx_str_t timefmt; @@ -80,7 +86,7 @@ typedef struct { ngx_http_ssi_command_pt handler; ngx_http_ssi_param_t *params; - unsigned conditional:1; + unsigned conditional:2; unsigned flush:1; } ngx_http_ssi_command_t; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index 4d57bb63e..d0453ea8d 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -178,6 +178,35 @@ args(r, ...) char * +request_method(r) + nginx r + + CODE: + + RETVAL = ngx_palloc(r->pool, r->method_name.len + 1); + if (RETVAL == NULL) { + XSRETURN_UNDEF; + } + + ngx_cpystrn((u_char *) RETVAL, r->method_name.data, r->method_name.len + 1); + + OUTPUT: + RETVAL + + +char * +remote_addr(r) + nginx r + + CODE: + + RETVAL = (char *) r->connection->addr_text.data; + + OUTPUT: + RETVAL + + +char * header_in(r, key) nginx r SV *key diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index 0bcad5ccb..e453dc38b 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -39,6 +39,7 @@ static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); #endif +static void ngx_http_perl_handle_request(ngx_http_request_t *r); static ngx_int_t ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf, PerlInterpreter **perl, ngx_log_t *log); @@ -174,23 +175,39 @@ ngx_http_perl_xs_init(pTHX) static ngx_int_t ngx_http_perl_handler(ngx_http_request_t *r) { - ngx_int_t rc; - ngx_str_t uri, args; - ngx_http_perl_ctx_t *ctx; - ngx_http_perl_loc_conf_t *plcf; - ngx_http_perl_main_conf_t *pmcf; + ngx_int_t rc; /* TODO: Win32 */ if (r->zero_in_uri) { return NGX_HTTP_NOT_FOUND; } + rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request); + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + return rc; + } + + return NGX_DONE; +} + + +static void +ngx_http_perl_handle_request(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_str_t uri, args; + ngx_http_perl_ctx_t *ctx; + ngx_http_perl_loc_conf_t *plcf; + ngx_http_perl_main_conf_t *pmcf; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler"); /* mod_perl's content handler assumes that content type was already set */ if (ngx_http_set_content_type(r) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); @@ -198,7 +215,8 @@ ngx_http_perl_handler(ngx_http_request_t *r) if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { - return NGX_ERROR; + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); @@ -209,7 +227,8 @@ ngx_http_perl_handler(ngx_http_request_t *r) rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log); if (rc != NGX_OK) { - return rc; + ngx_http_finalize_request(r, rc); + return; } { @@ -235,20 +254,24 @@ ngx_http_perl_handler(ngx_http_request_t *r) if (ctx->redirect_uri.len) { uri = ctx->redirect_uri; args = ctx->redirect_args; + + } else { + uri.len = 0; } ctx->filename = NULL; ctx->redirect_uri.len = 0; if (uri.len) { - return ngx_http_internal_redirect(r, &uri, &args); + ngx_http_internal_redirect(r, &uri, &args); + return; } if (rc == NGX_OK || rc == NGX_HTTP_OK) { - return ngx_http_send_special(r, NGX_HTTP_LAST); + ngx_http_send_special(r, NGX_HTTP_LAST); } - return rc; + ngx_http_finalize_request(r, rc); } @@ -448,6 +471,10 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) } #endif + if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) { + return NGX_CONF_ERROR; + } + PERL_SYS_INIT(&ngx_argc, &ngx_argv); pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 870dd8bcc..514658ca2 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1503,6 +1503,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } + if (!r->post_action) { + r->request_complete = 1; + } + if (ngx_http_post_action(r) == NGX_OK) { return; } @@ -2254,6 +2258,7 @@ ngx_http_post_action(ngx_http_request_t *r) r->http_version = NGX_HTTP_VERSION_9; r->header_only = 1; + r->post_action = 1; ngx_http_internal_redirect(r, &clcf->post_action, NULL); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 8450b0434..7e1a43b5d 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -405,6 +405,8 @@ struct ngx_http_request_s { unsigned lingering_close:1; unsigned discard_body:1; unsigned internal:1; + unsigned post_action:1; + unsigned request_complete:1; unsigned done:1; unsigned utf8:1; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 9fd1a1ebd..bfaed70a5 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -277,9 +277,9 @@ ngx_http_upstream_init(ngx_http_request_t *r) ngx_del_timer(c->read); } - if (!(r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) { - /* not a post_action */ + u = r->upstream; + if (!r->post_action && !u->conf->ignore_client_abort) { r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; } @@ -296,8 +296,6 @@ ngx_http_upstream_init(ngx_http_request_t *r) } } - u = r->upstream; - if (r->request_body) { u->request_bufs = r->request_body->bufs; } @@ -1208,10 +1206,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) rc = ngx_http_send_header(r); - if (rc == NGX_ERROR - || rc > NGX_OK - /* post_action */ - || (r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) { + if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) { ngx_http_upstream_finalize_request(r, u, rc); return; } @@ -1947,11 +1942,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r, r->connection->log->action = "sending to client"; - if (rc == 0 - && r == r->main - /* not a post_action */ - && !(r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) - { + if (rc == 0 && r == r->main && !r->post_action) { rc = ngx_http_send_special(r, NGX_HTTP_LAST); } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 117def185..4d07c3e7e 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -73,6 +73,7 @@ typedef struct { ngx_flag_t pass_request_headers; ngx_flag_t pass_request_body; + ngx_flag_t ignore_client_abort; ngx_flag_t redirect_errors; ngx_flag_t cyclic_temp_file; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 1370162c1..261592978 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -44,6 +44,8 @@ static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); /* @@ -135,6 +137,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent, 0, 0, 0 }, + { ngx_string("request_completion"), ngx_http_variable_request_completion, + 0, 0, 0 }, + { ngx_null_string, NULL, 0, 0, 0 } }; @@ -798,6 +803,30 @@ ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, } +static ngx_int_t +ngx_http_variable_request_completion(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->request_complete) { + v->len = 2; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = (u_char *) "OK"; + + return NGX_OK; + } + + v->len = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = (u_char *) ""; + + return NGX_OK; +} + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { |