mirror of
https://github.com/nginx/nginx.git
synced 2024-11-25 18:30:26 -06:00
<!--#include virtual=... set=... -->
This commit is contained in:
parent
0ab9e43714
commit
960100e371
@ -144,10 +144,10 @@ ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
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_request_t *r, ngx_chain_t *in)
|
||||
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);
|
||||
|
@ -395,6 +395,13 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
|
||||
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));
|
||||
|
@ -78,6 +78,10 @@ static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
|
||||
|
||||
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 ngx_http_next_body_filter;
|
||||
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_ssi_include_params[] = {
|
||||
{ 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_request_t *r, ngx_chain_t *in)
|
||||
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_request_t *r, ngx_chain_t *in)
|
||||
}
|
||||
}
|
||||
|
||||
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_request_t *r, ngx_str_t *name,
|
||||
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_request_t *r, ngx_str_t *name,
|
||||
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_request_t *r, ngx_http_ssi_ctx_t *ctx,
|
||||
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 *r, ngx_http_ssi_ctx_t *ctx,
|
||||
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 *r, ngx_http_ssi_ctx_t *ctx,
|
||||
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 *r, ngx_http_ssi_ctx_t *ctx,
|
||||
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 *r, ngx_http_ssi_ctx_t *ctx,
|
||||
|
||||
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 *r, ngx_http_ssi_ctx_t *ctx,
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -1980,6 +2052,48 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
|
||||
}
|
||||
|
||||
|
||||
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, ngx_http_ssi_ctx_t *ctx,
|
||||
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_http_ssi_ctx_t *ctx,
|
||||
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, ngx_http_ssi_ctx_t *ctx,
|
||||
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, ngx_http_ssi_ctx_t *ctx,
|
||||
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, 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, 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,
|
||||
|
@ -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;
|
||||
|
@ -1285,7 +1285,7 @@ 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 **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;
|
||||
@ -1353,9 +1353,8 @@ ngx_http_subrequest(ngx_http_request_t *r,
|
||||
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 *r,
|
||||
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 *r,
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -306,7 +306,7 @@ 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);
|
||||
|
||||
|
@ -1476,26 +1476,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
||||
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
|
||||
|
@ -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 {
|
||||
@ -344,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;
|
||||
@ -401,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;
|
||||
|
||||
|
@ -21,6 +21,7 @@ static void ngx_http_upstream_send_request(ngx_http_request_t *r,
|
||||
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_event_t *rev)
|
||||
|
||||
/* 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_event_t *rev)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user