ngx_int_t ngx_http_echo_exec_echo_location_async(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_request_t *sr; /* subrequest object */ ngx_str_t *computed_arg_elts; ngx_str_t location; ngx_str_t *url_args; ngx_str_t args; ngx_uint_t flags = 0; dd_enter(); computed_arg_elts = computed_args->elts; location = computed_arg_elts[0]; if (location.len == 0) { return NGX_ERROR; } if (computed_args->nelts > 1) { url_args = &computed_arg_elts[1]; } else { url_args = NULL; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_location_async sees unsafe uri: \"%V\"", &location); return NGX_ERROR; } if (args.len > 0 && url_args == NULL) { url_args = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } rc = ngx_http_subrequest(r, &location, url_args, &sr, NULL, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_echo_adjust_subrequest(sr); if (rc != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
static ngx_int_t ngx_http_set_form_input_multi(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) { ngx_http_form_input_ctx_t *ctx; ngx_int_t rc; dd_enter(); dd("set default return value"); ngx_str_set(res, ""); /* dd("set default return value"); */ if (r->done) { return NGX_OK; } ctx = ngx_http_get_module_ctx(r, ngx_http_form_input_module); if (ctx == NULL) { dd("ndk handler:null ctx"); return NGX_OK; } if (!ctx->done) { dd("ctx not done"); return NGX_OK; } rc = ngx_http_form_input_arg(r, v->data, v->len, res, 1); return rc; }
ngx_int_t ngx_http_srcache_fetch_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc) { ngx_http_srcache_ctx_t *ctx = data; ngx_http_srcache_ctx_t *pr_ctx; ngx_http_request_t *pr; dd_enter(); if (r != r->connection->data) { dd("waited: %d, rc: %d", (int) r->waited, (int) rc); } pr = r->parent; pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } if (ctx && ctx->parsing_cached_headers) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_fetch: cache sent truncated status line " "or headers"); pr_ctx->from_cache = 0; } pr_ctx->waiting_subrequest = 0; pr_ctx->request_done = 1; return rc; }
ngx_int_t ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ssize_t i, count; ngx_str_t *str; u_char *p; ngx_int_t rc; ngx_buf_t *buf; ngx_chain_t *cl; dd_enter(); computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; count = ngx_http_echo_atosz(computed_arg->data, computed_arg->len); if (count == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid size specified: \"%V\"", computed_arg); return NGX_HTTP_INTERNAL_SERVER_ERROR; } str = &computed_arg_elts[1]; if (count == 0 || str->len == 0) { rc = ngx_http_echo_send_header_if_needed(r, ctx); if (r->header_only || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_OK; } buf = ngx_create_temp_buf(r->pool, count * str->len); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } p = buf->pos; for (i = 0; i < count; i++) { p = ngx_copy(p, str->data, str->len); } buf->last = p; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->next = NULL; cl->buf = buf; return ngx_http_echo_send_chain_link(r, ctx, cl); }
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r, ngx_http_headers_more_header_val_t *hv, ngx_str_t *value) { dd_enter(); value->len = 0; return ngx_http_set_builtin_header(r, hv, value); }
ngx_int_t ngx_http_srcache_fetch_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc) { ngx_http_srcache_ctx_t *ctx = data; ngx_http_srcache_ctx_t *pr_ctx; ngx_http_request_t *pr; dd_enter(); if (r != r->connection->data) { dd("waited: %d, rc: %d", (int) r->waited, (int) rc); } pr = r->parent; pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } if (ctx == NULL) { return NGX_OK; } if (ctx->parsing_cached_headers) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_fetch: cache sent truncated status line " "or headers"); pr_ctx->from_cache = 0; } else if (r->headers_out.status >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { dd("HERE"); pr_ctx->from_cache = 0; } else if (!ctx->seen_subreq_eof) { #if 1 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_fetch: cache sent truncated " "response body"); pr_ctx->from_cache = 0; #endif } pr_ctx->waiting_subrequest = 0; pr_ctx->request_done = 1; return NGX_OK; }
ngx_int_t ngx_http_echo_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc) { ngx_http_echo_ctx_t *ctx = data; ngx_http_request_t *pr; ngx_http_echo_ctx_t *pr_ctx; dd_enter(); if (ctx->run_post_subrequest) { return rc; } ctx->run_post_subrequest = 1; pr = r->parent; pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_echo_module); if (pr_ctx == NULL) { return NGX_ERROR; } dd("mark ready %d", (int) pr_ctx->next_handler_cmd); pr_ctx->waiting = 0; pr_ctx->done = 1; pr->write_event_handler = ngx_http_echo_wev_handler; /* ensure that the parent request is (or will be) * posted out the head of the r->posted_requests chain */ if (r->main->posted_requests && r->main->posted_requests->request != pr) { rc = ngx_http_echo_post_request_at_head(pr, NULL); if (rc != NGX_OK) { return NGX_ERROR; } } return rc; }
ngx_int_t ngx_http_srcache_post_request_at_head(ngx_http_request_t *r, ngx_http_posted_request_t *pr) { dd_enter(); if (pr == NULL) { pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t)); if (pr == NULL) { return NGX_ERROR; } } pr->request = r; pr->next = r->main->posted_requests; r->main->posted_requests = pr; return NGX_OK; }
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r, ngx_http_headers_more_header_val_t *hv, ngx_str_t *value) { ngx_table_elt_t *h, **old; dd_enter(); if (hv->offset) { old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset); } else { old = NULL; } if (old == NULL || *old == NULL) { return ngx_http_set_header_helper(r, hv, value, old, 0); } h = *old; if (value->len == 0) { dd("clearing the builtin header"); h->hash = 0; h->value = *value; return NGX_OK; } h->hash = hv->hash; h->key = hv->key; h->value = *value; return NGX_OK; }
static ngx_int_t ngx_http_srcache_header_filter(ngx_http_request_t *r) { ngx_http_srcache_ctx_t *ctx, *pr_ctx; ngx_http_srcache_loc_conf_t *slcf; ngx_http_post_subrequest_t *ps; ngx_str_t skip; ngx_uint_t *sp; /* status pointer */ dd_enter(); dd("srcache header filter"); ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); if (r != r->main && ctx == NULL) { ps = r->post_subrequest; if (ps != NULL && (ps->handler == ngx_http_srcache_fetch_post_subrequest || ps->handler == ngx_http_srcache_store_post_subrequest) && ps->data != NULL) { /* the subrequest ctx has been cleared by * ngx_http_internal_redirect, resume it from the post_subrequest * data */ dd("resumed ctx from post_subrequest"); ctx = ps->data; ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); } } if (ctx == NULL || ctx->from_cache) { dd("bypass: %.*s", (int) r->uri.len, r->uri.data); return ngx_http_srcache_next_header_filter(r); } if (ctx->in_fetch_subrequest) { dd("in fetch subrequest"); pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { dd("parent ctx is null"); ctx->ignore_body = 1; return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch: subrequest returned status %ui", r->headers_out.status); if (r->headers_out.status != NGX_HTTP_OK) { dd("ignoring body because status == %d", (int) r->headers_out.status); ctx->ignore_body = 1; pr_ctx->waiting_subrequest = 0; /* pr_ctx->fetch_error = 1; */ r->header_sent = 1; return NGX_OK; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch decides to send the response in cache"); r->filter_need_in_memory = 1; pr_ctx->from_cache = 1; ctx->parsing_cached_headers = 1; r->header_sent = 1; return NGX_OK; } if (ctx->in_store_subrequest) { dd("in store subreuqest"); ctx->ignore_body = 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store: subrequest returned status %ui", r->headers_out.status); r->header_sent = 1; return NGX_OK; } slcf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (slcf->store == NULL) { dd("slcf->store is NULL"); return ngx_http_srcache_next_header_filter(r); } /* slcf->store != NULL */ #if 1 if (!(r->method & (slcf->cache_methods & ~NGX_HTTP_HEAD))) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to request method %V", &r->method_name); return ngx_http_srcache_next_header_filter(r); } #endif if (!slcf->ignore_content_encoding && r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "srcache_store skipped due to response header " "\"Content-Encoding: %V\" (maybe you forgot to disable " "compression on the backend?)", &r->headers_out.content_encoding->value); return ngx_http_srcache_next_header_filter(r); } if (slcf->resp_cache_control && ngx_http_srcache_response_no_cache(r, slcf, ctx) == NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to response header " "Cache-Control"); return ngx_http_srcache_next_header_filter(r); } if (slcf->store_skip != NULL && ngx_http_complex_value(r, slcf->store_skip, &skip) == NGX_OK && skip.len && (skip.len != 1 || skip.data[0] != '0')) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to the true value fed into " "srcache_store_skip: \"%V\"", &skip); ctx->store_skip = 1; return ngx_http_srcache_next_header_filter(r); } dd("error page: %d", (int) r->error_page); if (slcf->store_statuses != NULL) { sp = (ngx_uint_t *) slcf->store_statuses; while (r->headers_out.status < *sp) { sp++; } if (*sp == 0 || r->headers_out.status > *sp) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store bypassed because of unmatched " "status code %ui with srcache_store_statuses", r->headers_out.status); return ngx_http_srcache_next_header_filter(r); } /* r->headers_out.status == (ngx_uint_t) *sp */ } else { if (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_MOVED_TEMPORARILY && r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store bypassed because of unmatched status " "code %i (only 200, 301, or 302 are accepted by " "default)", r->headers_out.status); return ngx_http_srcache_next_header_filter(r); } } if (slcf->store_max_size != 0 && r->headers_out.content_length_n > 0 && r->headers_out.content_length_n + 15 /* just an approxiation for the response header size */ > (off_t) slcf->store_max_size) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store bypassed because of too large " "Content-Length response header: %O (limit is: %z)", r->headers_out.content_length_n, slcf->store_max_size); return ngx_http_srcache_next_header_filter(r); } dd("try to save the response header"); if (r != r->main) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_srcache not working in subrequests (yet)"); /* not allowd in subrquests */ return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store decides to store the response"); r->filter_need_in_memory = 1; ctx->http_status = r->headers_out.status; ctx->store_response = 1; return NGX_OK; }
static ngx_int_t ngx_http_srcache_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_srcache_ctx_t *ctx, *pr_ctx; ngx_int_t rc; ngx_str_t skip; ngx_chain_t *cl; ngx_http_srcache_loc_conf_t *slcf; size_t len; unsigned last; dd_enter(); if (in == NULL) { return ngx_http_srcache_next_body_filter(r, NULL); } ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); if (ctx == NULL || ctx->from_cache || ctx->store_skip) { dd("bypass: %.*s", (int) r->uri.len, r->uri.data); return ngx_http_srcache_next_body_filter(r, in); } if (ctx->ignore_body || ctx->in_store_subrequest/* || ctx->fetch_error */) { dd("ignore body: ignore body %d, in store sr %d", (int) ctx->ignore_body, (int) ctx->in_store_subrequest); ngx_http_srcache_discard_bufs(r->pool, in); return NGX_OK; } if (ctx->in_fetch_subrequest) { if (ctx->parsing_cached_headers) { /* parse the cached response's headers and * set r->parent->headers_out */ if (ctx->process_header == NULL) { dd("restore parent request header"); ctx->process_header = ngx_http_srcache_process_status_line; r->state = 0; /* sw_start */ } for (cl = in; cl; cl = cl->next) { if (ngx_buf_in_memory(cl->buf)) { dd("old pos %p, last %p", cl->buf->pos, cl->buf->last); rc = ctx->process_header(r, cl->buf); if (rc == NGX_AGAIN) { dd("AGAIN/OK: new pos %p, last %p", cl->buf->pos, cl->buf->last); continue; } if (rc == NGX_ERROR) { r->state = 0; /* sw_start */ ctx->parsing_cached_headers = 0; ctx->ignore_body = 1; ngx_http_srcache_discard_bufs(r->pool, cl); pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } pr_ctx->from_cache = 0; return NGX_OK; } /* rc == NGX_OK */ dd("OK: new pos %p, last %p", cl->buf->pos, cl->buf->last); dd("buf left: %.*s", (int) (cl->buf->last - cl->buf->pos), cl->buf->pos); ctx->parsing_cached_headers = 0; break; } } if (cl == NULL) { return NGX_OK; } if (cl->buf->pos == cl->buf->last) { cl = cl->next; } if (cl == NULL) { return NGX_OK; } in = cl; } dd("save the cached response body for parent"); pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } rc = ngx_http_srcache_add_copy_chain(r->pool, &pr_ctx->body_from_cache, in, &last); if (rc != NGX_OK) { return NGX_ERROR; } if (last) { ctx->seen_subreq_eof = 1; } ngx_http_srcache_discard_bufs(r->pool, in); return NGX_OK; } if (ctx->store_response) { dd("storing the response: %p", in); if (ctx->response_length == 0) { /* store the response header to ctx->body_to_cache */ if (ngx_http_srcache_store_response_header(r, ctx) == NGX_ERROR) { return NGX_ERROR; } if (ngx_http_srcache_next_header_filter(r) == NGX_ERROR) { return NGX_ERROR; } } for (cl = in; cl; cl = cl->next) { if (ngx_buf_in_memory(cl->buf)) { len = ngx_buf_size(cl->buf); ctx->response_length += len; ctx->response_body_length += len; } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (slcf->store_max_size != 0 && ctx->response_length > slcf->store_max_size) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store bypassed because response body " "exceeded maximum size: %z (limit is: %z)", ctx->response_length, slcf->store_max_size); ctx->store_response = 0; goto done; } rc = ngx_http_srcache_add_copy_chain(r->pool, &ctx->body_to_cache, in, &last); if (rc != NGX_OK) { ctx->store_response = 0; goto done; } if (last && r == r->main) { #if 1 if (r->headers_out.content_length_n > (off_t) ctx->response_body_length) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_store: skipped because response body " "truncated: %O > %uz", r->headers_out.content_length_n, ctx->response_body_length); ctx->store_response = 0; goto done; } if (r->headers_out.status >= NGX_HTTP_SPECIAL_RESPONSE && r->headers_out.status != ctx->http_status) { /* data truncation or body receive timeout */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_store: skipped due to new error status " "code %ui (old: %ui)", r->headers_out.status, ctx->http_status); ctx->store_response = 0; goto done; } #endif if (slcf->store_skip != NULL && ngx_http_complex_value(r, slcf->store_skip, &skip) == NGX_OK && skip.len && (skip.len != 1 || skip.data[0] != '0')) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to the true value in " "srcache_store_skip: \"%V\"", &skip); ctx->store_response = 0; goto done; } rc = ngx_http_srcache_store_subrequest(r, ctx); if (rc != NGX_OK) { ctx->store_response = 0; goto done; } } } else { dd("NO store response"); } done: return ngx_http_srcache_next_body_filter(r, in); }
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_headers_more_header_val_t *hv, ngx_str_t *value, ngx_table_elt_t **output_header, ngx_flag_t no_create) { ngx_table_elt_t *h; ngx_list_part_t *part; ngx_uint_t i; ngx_flag_t matched = 0; dd_enter(); part = &r->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if ( (!hv->wildcard && (h[i].key.len == hv->key.len && ngx_strncasecmp(h[i].key.data, hv->key.data, h[i].key.len) == 0)) || (hv->wildcard && (h[i].key.len >= hv->key.len-1 && ngx_strncasecmp(h[i].key.data, hv->key.data, hv->key.len-1) == 0)) ) { if (value->len == 0) { dd("clearing normal header for %.*s", (int) hv->key.len, hv->key.data); h[i].value.len = 0; h[i].hash = 0; } else { h[i].value = *value; h[i].hash = 1; } if (output_header) { *output_header = &h[i]; } matched = 1; } } if (matched){ return NGX_OK; } if ((hv->wildcard || no_create) && value->len == 0) { return NGX_OK; } /* XXX we still need to create header slot even if the value * is empty because some builtin headers like Last-Modified * relies on this to get cleared */ h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (value->len == 0) { h->hash = 0; } else { h->hash = hv->hash; } h->key = hv->key; h->value = *value; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); if (output_header) { *output_header = h; } return NGX_OK; }
static ngx_int_t ngx_http_srcache_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_srcache_ctx_t *ctx, *pr_ctx; ngx_int_t rc; ngx_chain_t *cl; ngx_flag_t last; ngx_http_srcache_loc_conf_t *slcf; dd_enter(); if (in == NULL) { return ngx_http_srcache_next_body_filter(r, NULL); } ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); if (ctx == NULL || ctx->from_cache || ctx->store_skip) { dd("bypass: %.*s", (int) r->uri.len, r->uri.data); return ngx_http_srcache_next_body_filter(r, in); } if (ctx->ignore_body || ctx->in_store_subrequest/* || ctx->fetch_error */) { dd("ignore body: ignore body %d, in store sr %d", (int) ctx->ignore_body, (int) ctx->in_store_subrequest); ngx_http_srcache_discard_bufs(r->pool, in); return NGX_OK; } if (ctx->in_fetch_subrequest) { if (ctx->parsing_cached_headers) { /* parse the cached response's headers and * set r->parent->headers_out */ if (ctx->process_header == NULL) { dd("restore parent request header"); ctx->process_header = ngx_http_srcache_process_status_line; r->state = 0; /* sw_start */ } for (cl = in; cl; cl = cl->next) { if (ngx_buf_in_memory(cl->buf)) { dd("old pos %p, last %p", cl->buf->pos, cl->buf->last); rc = ctx->process_header(r, cl->buf); if (rc == NGX_AGAIN) { dd("AGAIN/OK: new pos %p, last %p", cl->buf->pos, cl->buf->last); continue; } if (rc == NGX_ERROR) { r->state = 0; /* sw_start */ ctx->parsing_cached_headers = 0; ctx->ignore_body = 1; ngx_http_srcache_discard_bufs(r->pool, cl); pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } pr_ctx->from_cache = 0; return NGX_OK; } /* rc == NGX_OK */ dd("OK: new pos %p, last %p", cl->buf->pos, cl->buf->last); dd("buf left: %.*s", (int) (cl->buf->last - cl->buf->pos), cl->buf->pos); ctx->parsing_cached_headers = 0; break; } } if (cl == NULL) { return NGX_OK; } if (cl->buf->pos == cl->buf->last) { cl = cl->next; } if (cl == NULL) { return NGX_OK; } in = cl; } dd("save the cached response body for parent"); pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_srcache_filter_module); if (pr_ctx == NULL) { return NGX_ERROR; } rc = ngx_http_srcache_add_copy_chain(r->pool, &pr_ctx->body_from_cache, in); if (rc != NGX_OK) { return NGX_ERROR; } ngx_http_srcache_discard_bufs(r->pool, in); return NGX_OK; } if (ctx->store_response) { dd("storing the response: %p", in); if (ctx->response_length == 0) { /* store the response header to ctx->body_to_cache */ rc = ngx_http_srcache_store_response_header(r, ctx); if (rc == NGX_ERROR) { return NGX_ERROR; } } last = 0; for (cl = in; cl; cl = cl->next) { if (ngx_buf_in_memory(cl->buf)) { ctx->response_length += ngx_buf_size(cl->buf); } if (cl->buf->last_buf) { last = 1; break; } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (slcf->store_max_size != 0 && ctx->response_length > slcf->store_max_size) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store bypassed because response body exceeded " "maximum size: %z (limit is: %z)", ctx->response_length, slcf->store_max_size); ctx->store_response = 0; goto done; } rc = ngx_http_srcache_add_copy_chain(r->pool, &ctx->body_to_cache, in); if (rc != NGX_OK) { ctx->store_response = 0; goto done; } if (last && r == r->main) { rc = ngx_http_srcache_store_subrequest(r, ctx); if (rc != NGX_OK) { ctx->store_response = 0; goto done; } } } else { dd("NO store response"); } done: return ngx_http_srcache_next_body_filter(r, in); }
static ngx_int_t ngx_http_srcache_fetch_subrequest(ngx_http_request_t *r, ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_ctx_t *ctx) { ngx_http_srcache_ctx_t *sr_ctx; ngx_http_post_subrequest_t *psr; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_request_t *sr; ngx_int_t rc; ngx_http_srcache_parsed_request_t *parsed_sr; dd_enter(); parsed_sr = ngx_palloc(r->pool, sizeof(ngx_http_srcache_parsed_request_t)); if (parsed_sr == NULL) { return NGX_ERROR; } if (conf->fetch == NULL) { return NGX_ERROR; } parsed_sr->method = conf->fetch->method; parsed_sr->method_name = conf->fetch->method_name; parsed_sr->request_body = NULL; parsed_sr->content_length_n = -1; if (ngx_http_complex_value(r, &conf->fetch->location, &parsed_sr->location) != NGX_OK) { return NGX_ERROR; } if (parsed_sr->location.len == 0) { return NGX_ERROR; } if (ngx_http_complex_value(r, &conf->fetch->args, &parsed_sr->args) != NGX_OK) { return NGX_ERROR; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &parsed_sr->location, &args, &flags) != NGX_OK) { return NGX_ERROR; } if (args.len > 0 && parsed_sr->args.len == 0) { parsed_sr->args = args; } sr_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_ctx_t)); if (sr_ctx == NULL) { return NGX_ERROR; } sr_ctx->in_fetch_subrequest = 1; psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } psr->handler = ngx_http_srcache_fetch_post_subrequest; psr->data = sr_ctx; dd("firing the fetch subrequest"); dd("fetch location: %.*s", (int) parsed_sr->location.len, parsed_sr->location.data); dd("fetch args: %.*s", (int) parsed_sr->args.len, parsed_sr->args.data); rc = ngx_http_subrequest(r, &parsed_sr->location, &parsed_sr->args, &sr, psr, flags); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_srcache_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return NGX_ERROR; } ngx_http_set_ctx(sr, sr_ctx, ngx_http_srcache_filter_module); ctx->issued_fetch_subrequest = 1; return NGX_OK; }
ngx_int_t ngx_http_echo_exec_echo(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args, ngx_flag_t in_filter, ngx_array_t *opts) { ngx_uint_t i; ngx_buf_t *space_buf; ngx_buf_t *newline_buf; ngx_buf_t *buf; ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ngx_str_t *opt; ngx_chain_t *cl = NULL; /* the head of the chain link */ ngx_chain_t **ll = &cl; /* always point to the address of the last link */ dd_enter(); if (computed_args == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } computed_arg_elts = computed_args->elts; for (i = 0; i < computed_args->nelts; i++) { computed_arg = &computed_arg_elts[i]; if (computed_arg->len == 0) { buf = NULL; } else { buf = ngx_calloc_buf(r->pool); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } buf->start = buf->pos = computed_arg->data; buf->last = buf->end = computed_arg->data + computed_arg->len; buf->memory = 1; } if (cl == NULL) { cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = buf; cl->next = NULL; ll = &cl->next; } else { /* append a space first */ *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } space_buf = ngx_calloc_buf(r->pool); if (space_buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* nginx clears buf flags at the end of each request handling, * so we have to make a clone here. */ *space_buf = ngx_http_echo_space_buf; (*ll)->buf = space_buf; (*ll)->next = NULL; ll = &(*ll)->next; /* then append the buf only if it's non-empty */ if (buf) { *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } (*ll)->buf = buf; (*ll)->next = NULL; ll = &(*ll)->next; } } } /* end for */ if (cl && cl->buf == NULL) { cl = cl->next; } if (opts && opts->nelts > 0) { opt = opts->elts; /* FIXME handle other unrecognized options here */ if (opt[0].len == 1 && opt[0].data[0] == 'n') { goto done; } } /* append the newline character */ newline_buf = ngx_calloc_buf(r->pool); if (newline_buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } *newline_buf = ngx_http_echo_newline_buf; if (cl == NULL) { cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = newline_buf; cl->next = NULL; /* ll = &cl->next; */ } else { *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } (*ll)->buf = newline_buf; (*ll)->next = NULL; /* ll = &(*ll)->next; */ } done: if (cl == NULL || cl->buf == NULL) { return NGX_OK; } if (in_filter) { return ngx_http_echo_next_body_filter(r, cl); } return ngx_http_echo_send_chain_link(r, ctx, cl); }
void ngx_http_echo_wev_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_echo_ctx_t *ctx; dd_enter(); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_ERROR); return; } if (ctx->waiting && ! ctx->done) { if (r->main->posted_requests && r->main->posted_requests->request != r) { dd("HOT SPIN"); #if defined(nginx_version) && nginx_version >= 8012 ngx_http_post_request(r, NULL); #else ngx_http_post_request(r); #endif return; } } ctx->done = 0; ctx->next_handler_cmd++; rc = ngx_http_echo_run_cmds(r); dd("rc: %d", (int) rc); if (rc == NGX_DONE) { return; } if (rc == NGX_AGAIN) { dd("mark busy %d", (int) ctx->next_handler_cmd); ctx->waiting = 1; ctx->done = 0; } else { dd("mark ready %d", (int) ctx->next_handler_cmd); ctx->waiting = 0; ctx->done = 1; dd("finalizing with rc %d", (int) rc); dd("finalize request %.*s with %d", (int) r->uri.len, r->uri.data, (int) rc); ngx_http_finalize_request(r, rc); } }
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_headers_more_header_val_t *hv, ngx_str_t *value, ngx_table_elt_t **output_header) { ngx_table_elt_t *h; ngx_list_part_t *part; ngx_uint_t i; ngx_uint_t rc; dd_enter(); retry: part = &r->headers_in.headers.part; h = part->elts; for (i = 0; /* void */; i++) { dd("i: %d, part: %p", (int) i, part); if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].key.len == hv->key.len && ngx_strncasecmp(h[i].key.data, hv->key.data, h[i].key.len) == 0) { if (value->len == 0) { h[i].hash = 0; rc = ngx_http_headers_more_rm_header_helper( &r->headers_in.headers, part, i); if (rc == NGX_OK) { if (output_header) { *output_header = NULL; } goto retry; } } h[i].value = *value; if (output_header) { *output_header = &h[i]; dd("setting existing builtin input header"); } return NGX_OK; } } if (value->len == 0 || hv->replace) { return NGX_OK; } h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("created new header for %.*s", (int) hv->key.len, hv->key.data); if (value->len == 0) { h->hash = 0; } else { h->hash = hv->hash; } h->key = hv->key; h->value = *value; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); if (output_header) { *output_header = h; while (r != r->main) { r->parent->headers_in = r->headers_in; r = r->parent; } } return NGX_OK; }
/* an rewrite phase handler */ static ngx_int_t ngx_http_form_input_handler(ngx_http_request_t *r) { ngx_http_form_input_ctx_t *ctx; ngx_str_t value; ngx_int_t rc; dd_enter(); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http form_input rewrite phase handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_form_input_module); if (ctx != NULL) { if (ctx->done) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http form_input rewrite phase handler done"); return NGX_DECLINED; } return NGX_DONE; } if (r->method != NGX_HTTP_POST && r->method != NGX_HTTP_PUT) { return NGX_DECLINED; } if (r->headers_in.content_type == NULL || r->headers_in.content_type->value.data == NULL) { dd("content_type is %s", r->headers_in.content_type == NULL?"NULL": "NOT NULL"); return NGX_DECLINED; } value = r->headers_in.content_type->value; dd("r->headers_in.content_length_n:%d", (int) r->headers_in.content_length_n); /* just focus on x-www-form-urlencoded */ if (value.len < form_urlencoded_type_len || ngx_strncasecmp(value.data, (u_char *) form_urlencoded_type, form_urlencoded_type_len) != 0) { dd("not application/x-www-form-urlencoded"); return NGX_DECLINED; } dd("content type is application/x-www-form-urlencoded"); dd("create new ctx"); ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_form_input_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } /* set by ngx_pcalloc: * ctx->done = 0; * ctx->waiting_more_body = 0; */ ngx_http_set_ctx(r, ctx, ngx_http_form_input_module); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http form_input start to read client request body"); rc = ngx_http_read_client_request_body(r, ngx_http_form_input_post_read); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { #if (nginx_version < 1002006) || \ (nginx_version >= 1003000 && nginx_version < 1003009) r->main->count--; #endif return rc; } if (rc == NGX_AGAIN) { ctx->waiting_more_body = 1; return NGX_DONE; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http form_input has read the request body in one run"); return NGX_DECLINED; }