static ngx_int_t ngx_http_data_dome_auth_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_int_t rc; ngx_str_t val; ngx_str_t x_datadome_response; ngx_uint_t i; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_table_elt_t *location; ngx_http_data_dome_auth_ctx_t *ctx; ngx_http_data_dome_auth_conf_t *acf; // you can dissable this module in location or if level acf = ngx_http_get_module_loc_conf(r, ngx_http_data_dome_auth_module); if (acf->uri_lengths == NULL) { return NGX_DECLINED; } if (r->internal && acf->pass_internal_redirect) { return NGX_DECLINED; } // but module use main request context to keep the status // to prevent duplicated query to API server ctx = ngx_http_get_module_ctx(r->main, ngx_http_data_dome_auth_module); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0, "Data Dome auth request handler, ctx: %p", ctx); if (ctx != NULL) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0, "Data Dome auth request handler ctx: declined %d, processing: %d, done: %d", ctx->declined, ctx->processing, ctx->done); if (ctx->declined) { return NGX_DECLINED; } if (ctx->processing) { return NGX_OK; } if (!ctx->done) { return NGX_AGAIN; } if (ngx_http_data_dome_auth_set_variables(r, acf, ctx) != NGX_OK) { return NGX_ERROR; } if (acf->learning) { return NGX_OK; } if (ctx->subrequest_rc < NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } x_datadome_response.len = 0; part = &ctx->subrequest->headers_out.headers.part; header = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0) { continue; } if (header[i].key.len != sizeof("X-DataDomeResponse") - 1) { continue; } if (ngx_strncmp(header[i].key.data, "X-DataDomeResponse", header[i].key.len) != 0) { continue; } x_datadome_response = header[i].value; break; } if (x_datadome_response.len == 0) { ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0, "API server response hasn't got X-DataDomeResponse"); return NGX_DECLINED; } if ((ngx_uint_t)ngx_atoi(x_datadome_response.data, x_datadome_response.len) != ctx->subrequest->headers_out.status) { ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0, "API server response's X-DataDomeResponse (%V) != status (%d)", &x_datadome_response, ctx->subrequest->headers_out.status); return NGX_DECLINED; } if (ngx_http_data_dome_auth_execute_x_datadome_headers(r->main->pool, "X-DataDome-headers", &ctx->subrequest->headers_out.headers, &r->main->headers_out.headers) == NGX_ERROR) { return NGX_ERROR; } if (ngx_http_data_dome_auth_execute_x_datadome_headers(r->main->pool, "X-DataDome-request-headers", &ctx->subrequest->headers_out.headers, &r->main->headers_in.headers) == NGX_ERROR) { return NGX_ERROR; } switch (ctx->subrequest->headers_out.status) { case NGX_HTTP_MOVED_PERMANENTLY: case NGX_HTTP_MOVED_TEMPORARILY: case NGX_HTTP_UNAUTHORIZED: case NGX_HTTP_FORBIDDEN: part = &ctx->subrequest->headers_out.headers.part; header = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0) { continue; } if (header[i].key.len != sizeof("Location") - 1) { continue; } if (ngx_strncmp(header[i].key.data, "Location", header[i].key.len) != 0) { continue; } location = ngx_list_push(&r->main->headers_out.headers); if (location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } location->hash = 1; location->key = header[i].key; location->lowcase_key = header[i].lowcase_key; location->value = header[i].value; break; } // nginx reset upstream buffer length, so, use body lenght from header ;) val.len = ctx->subrequest->headers_out.content_length_n; val.data = ctx->subrequest->upstream->buffer.pos; // if response hasn't Content-Length and body the length was -1, fix it if (ctx->subrequest->headers_out.content_length_n < 0) { val.len = 0; } if (val.len == 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Data Dome auth send response without body: s: %d", ctx->subrequest->headers_out.status); return ctx->subrequest->headers_out.status; } ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Data Dome auth send response: s: %d, c: %V, b: %V", ctx->subrequest->headers_out.status, &ctx->subrequest->headers_out.content_type, &val); r->headers_out.status = ctx->subrequest->headers_out.status; r->headers_out.content_length_n = val.len; if (ctx->subrequest->headers_out.content_type.len) { r->headers_out.content_type_len = ctx->subrequest->headers_out.content_type.len; r->headers_out.content_type = ctx->subrequest->headers_out.content_type; } else { if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } if (r->method == NGX_HTTP_HEAD || val.len == 0) { rc = ngx_http_send_header(r); if (rc != NGX_OK) { return rc; } return NGX_DONE; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->pos = val.data; b->last = val.data + val.len; b->memory = val.len ? 1 : 0; b->last_buf = (r == r->main) ? 1 : 0; b->last_in_chain = 1; out.buf = b; out.next = NULL; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } if (r->header_only) { ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } rc = ngx_http_output_filter(r, &out); if (rc != NGX_OK) { return rc; } ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; case NGX_HTTP_OK: return NGX_OK; default: ngx_log_error(NGX_LOG_ERR, r->main->connection->log, 0, "Data Dome auth request unexpected status: %d, pass", ctx->subrequest->headers_out.status); return NGX_OK; } } ctx = ngx_pcalloc(r->main->pool, sizeof(ngx_http_data_dome_auth_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } if (ngx_http_script_run(r, &ctx->uri, acf->uri_lengths->elts, 0, acf->uri_values->elts) == NULL) { return NGX_ERROR; } if (ngx_strncmp(ctx->uri.data, "off", ctx->uri.len) == 0) { return NGX_DECLINED; } ngx_http_set_ctx(r->main, ctx, ngx_http_data_dome_auth_module); #if (NGX_PCRE) if (acf->uri_regex_exclusion) { if (ngx_regex_exec(acf->uri_regex_exclusion, &r->main->uri, NULL, 0) != NGX_REGEX_NO_MATCHED) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0, "Data Dome auth URI regex exclusion: \"%V\" match with URI: %V", &acf->uri_regex_exclusion_raw, &r->main->uri); ctx->declined = 1; return NGX_DECLINED; } } if (acf->uri_regex) { if (ngx_regex_exec(acf->uri_regex, &r->main->uri, NULL, 0) != NGX_REGEX_NO_MATCHED) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->main->connection->log, 0, "Data Dome auth URI regex: \"%V\" match with URI: %V", &acf->uri_regex_raw, &r->main->uri); goto validate; } ctx->declined = 1; return NGX_DECLINED; } validate: #endif ctx->processing = 1; // keep original read and write event handler because read client body may override it ctx->read_event_handler = r->main->read_event_handler; ctx->write_event_handler = r->main->write_event_handler; return ngx_http_data_dome_subrequest(r); }
static ngx_int_t ngx_http_auth_request_handler(ngx_http_request_t *r) { ngx_table_elt_t *h, *ho; ngx_http_request_t *sr; ngx_http_post_subrequest_t *ps; ngx_http_auth_request_ctx_t *ctx; ngx_http_auth_request_conf_t *arcf; arcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_request_module); if (arcf->uri.len == 0) { return NGX_DECLINED; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "auth request handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_auth_request_module); if (ctx != NULL) { if (!ctx->done) { return NGX_AGAIN; } /* * as soon as we are done - explicitly set variables to make * sure they will be available after internal redirects */ if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) { return NGX_ERROR; } /* return appropriate status */ if (ctx->status == NGX_HTTP_FORBIDDEN) { return ctx->status; } if (ctx->status == NGX_HTTP_UNAUTHORIZED) { sr = ctx->subrequest; h = sr->headers_out.www_authenticate; if (!h && sr->upstream) { h = sr->upstream->headers_in.www_authenticate; } if (h) { ho = ngx_list_push(&r->headers_out.headers); if (ho == NULL) { return NGX_ERROR; } *ho = *h; r->headers_out.www_authenticate = ho; } return ctx->status; } if (ctx->status >= NGX_HTTP_OK && ctx->status < NGX_HTTP_SPECIAL_RESPONSE) { return NGX_OK; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "auth request unexpected status: %ui", ctx->status); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (ps == NULL) { return NGX_ERROR; } ps->handler = ngx_http_auth_request_done; ps->data = ctx; if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps, NGX_HTTP_SUBREQUEST_WAITED) != NGX_OK) { return NGX_ERROR; } /* * allocate fake request body to avoid attempts to read it and to make * sure real body file (if already read) won't be closed by upstream */ sr->request_body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (sr->request_body == NULL) { return NGX_ERROR; } sr->header_only = 1; ctx->subrequest = sr; ngx_http_set_ctx(r, ctx, ngx_http_auth_request_module); return NGX_AGAIN; }
ngx_int_t ngx_http_lua_rewrite_handler(ngx_http_request_t *r) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; ngx_http_lua_main_conf_t *lmcf; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua rewrite handler, uri \"%V\"", &r->uri); lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); if (! lmcf->postponed_to_rewrite_phase_end) { ngx_http_core_main_conf_t *cmcf; ngx_http_phase_handler_t tmp; ngx_http_phase_handler_t *ph; ngx_http_phase_handler_t *cur_ph; ngx_http_phase_handler_t *last_ph; lmcf->postponed_to_rewrite_phase_end = 1; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; cur_ph = &ph[r->phase_handler]; last_ph = &ph[cur_ph->next - 1]; #if 0 if (cur_ph == last_ph) { dd("XXX our handler is already the last rewrite phase handler"); } #endif if (cur_ph < last_ph) { dd("swaping the contents of cur_ph and last_ph..."); tmp = *cur_ph; memmove(cur_ph, cur_ph + 1, (last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t)); *last_ph = tmp; r->phase_handler--; /* redo the current ph */ return NGX_DECLINED; } } llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->rewrite_handler == NULL) { dd("no rewrite handler found"); return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx: ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } dd("entered? %d", (int) ctx->entered_rewrite_phase); if (ctx->waiting_more_body) { return NGX_DONE; } if (ctx->entered_rewrite_phase) { dd("rewriteby: calling wev handler"); rc = ngx_http_lua_wev_handler(r); dd("rewriteby: wev handler returns %d", (int) rc); return rc; } if (llcf->force_read_body && ! ctx->read_body_done && ((r->method & NGX_HTTP_POST) || (r->method & NGX_HTTP_PUT))) { rc = ngx_http_read_client_request_body(r, ngx_http_lua_generic_phase_post_read); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_AGAIN) { ctx->waiting_more_body = 1; return NGX_DONE; } } dd("calling rewrite handler"); return llcf->rewrite_handler(r); }
ngx_int_t ngx_http_lua_content_handler(ngx_http_request_t *r) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua content handler, uri \"%V\"", &r->uri); llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->content_handler == NULL) { dd("no content handler found"); return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx: ctx = %p, size: %d", ctx, (int) sizeof(*ctx)); ctx->entry_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } dd("entered? %d", (int) ctx->entered_content_phase); if (ctx->waiting_more_body) { return NGX_DONE; } if (ctx->entered_content_phase) { dd("calling wev handler"); rc = ngx_http_lua_wev_handler(r); dd("wev handler returns %d", (int) rc); return rc; } if (llcf->force_read_body && !ctx->read_body_done) { r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; rc = ngx_http_read_client_request_body(r, ngx_http_lua_content_phase_post_read); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_AGAIN) { ctx->waiting_more_body = 1; return NGX_DONE; } } dd("setting entered"); ctx->entered_content_phase = 1; dd("calling content handler"); return llcf->content_handler(r); }
static ngx_int_t ngx_http_memcached_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->schema.len = sizeof("memcached://") - 1; u->schema.data = (u_char *) "memcached://"; u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; u->conf = &mlcf->upstream; u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; r->upstream = u; ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_MEMCACHED_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; u->input_filter_ctx = ctx; ngx_http_upstream_init(r); return NGX_DONE; }
ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) { size_t i; ngx_int_t rc; u_char *err_msg; size_t rlen; u_char *rdata; #if (NGX_PCRE) ngx_pool_t *old_pool; #endif ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("nargs: %d", (int) nargs); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } dd("setting new ctx: ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* set Lua VM panic handler */ lua_atpanic(L, ngx_http_lua_atpanic); /* initialize nginx context in Lua VM, code chunk at stack top sp = 1 */ ngx_http_lua_set_by_lua_env(L, r, nargs, args); /* passing directive arguments to the user code */ for (i = 0; i < nargs; i++) { lua_pushlstring(L, (const char *) args[i].data, args[i].len); } #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ old_pool = ngx_http_lua_pcre_malloc_init(r->pool); #endif /* protected call user code */ rc = lua_pcall(L, nargs, 1, 0); #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ ngx_http_lua_pcre_malloc_done(old_pool); #endif if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tostring(L, -1); if (err_msg != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-error) %s", err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ } return NGX_ERROR; } NGX_LUA_EXCEPTION_TRY { rdata = (u_char *) lua_tolstring(L, -1, &rlen); if (rdata) { val->data = ngx_pcalloc(r->pool, rlen); if (val->data == NULL) { return NGX_ERROR; } ngx_memcpy(val->data, rdata, rlen); val->len = rlen; } else { val->data = NULL; val->len = 0; } } NGX_LUA_EXCEPTION_CATCH { dd("nginx execution restored"); } /* clear Lua stack */ lua_settop(L, 0); return NGX_OK; }
/* ** [ENTRY POINT] does : this function called by nginx from the request handler */ static ngx_int_t ngx_http_modsecurity_handler(ngx_http_request_t *r) { ngx_http_modsecurity_loc_conf_t *cf; ngx_http_modsecurity_ctx_t *ctx; ngx_int_t rc; cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity); /* Process only main request */ if (r != r->main || !cf->enable) { return NGX_DECLINED; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler"); /* create / retrive request ctx */ if (r->internal) { ctx = ngx_http_get_module_pool_ctx(r, ngx_http_modsecurity); if (ctx) { /* we have already processed the request headers */ ngx_http_set_ctx(r, ctx, ngx_http_modsecurity); return NGX_DECLINED; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: request pool ctx empty"); } ctx = ngx_http_modsecurity_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_modsecurity); if (ngx_http_set_pool_ctx(r, ctx, ngx_http_modsecurity) != NGX_OK) { return NGX_ERROR; } /* load request to request rec */ if (ngx_http_modsecurity_load_request(r) != NGX_OK || ngx_http_modsecurity_load_headers_in(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* processing request headers */ rc = ngx_http_modsecurity_status(r, modsecProcessRequestHeaders(ctx->req)); if (rc != NGX_DECLINED) { return rc; } if (modsecContextState(ctx->req) == MODSEC_DISABLED) { return NGX_DECLINED; } if (r->method == NGX_HTTP_POST && modsecIsRequestBodyAccessEnabled(ctx->req) ) { /* read POST request body, should we process PUT? */ rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; } /* other method */ return ngx_http_modsecurity_status(r, modsecProcessRequestBody(ctx->req)); }
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_request_t *sr; 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, &sr, NULL, 0) != NGX_OK) { return NGX_ERROR; } } } if (conf->after_body.len == 0) { ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); return ngx_http_next_body_filter(r, in); } last = 0; for (cl = in; cl; cl = cl->next) { if (cl->buf->last_buf) { cl->buf->last_buf = 0; cl->buf->sync = 1; last = 1; } } rc = ngx_http_next_body_filter(r, in); if (rc == NGX_ERROR || !last || conf->after_body.len == 0) { return rc; } if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) != NGX_OK) { return NGX_ERROR; } ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); return ngx_http_send_special(r, NGX_HTTP_LAST); }
static void ngx_http_dav_ext_propfind_handler(ngx_http_request_t *r) { ngx_chain_t *c; ngx_buf_t *b; XML_Parser parser; ngx_uint_t status; ngx_http_dav_ext_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_dav_ext_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_dav_ext_ctx_t)); ngx_http_set_ctx(r, ctx, ngx_http_dav_ext_module); } c = r->request_body->bufs; status = NGX_OK; parser = XML_ParserCreate(NULL); XML_SetUserData(parser, ctx); XML_SetElementHandler(parser, ngx_http_dav_ext_start_xml_elt, ngx_http_dav_ext_end_xml_elt); for(; c != NULL && c->buf != NULL && !c->buf->last_buf; c = c->next) { b = c ->buf; if (!XML_Parse(parser, (const char*)b->pos, b->last - b->pos, b->last_buf)) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "dav_ext propfind XML error"); status = NGX_ERROR; break; } } XML_ParserFree(parser); if (status == NGX_OK) { r->headers_out.status = 207; ngx_str_set(&r->headers_out.status_line, "207 Multi-Status"); ngx_http_send_header(r); ngx_http_finalize_request(r, ngx_http_dav_ext_send_propfind(r)); } else { r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR; r->header_only = 1; r->headers_out.content_length_n = 0; ngx_http_finalize_request(r, ngx_http_send_header(r)); } }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-content-by-chunk) failed to create new coroutine to handle request!"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } ctx->cc = cc; ctx->cc_ref = cc_ref; /* }}} */ /* {{{ register request cleanup hooks */ cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
static ngx_int_t ngx_http_small_light_header_filter(ngx_http_request_t *r) { ngx_http_small_light_conf_t *srv_conf; ngx_http_small_light_conf_t *loc_conf; ngx_http_small_light_ctx_t *ctx; ngx_hash_init_t hash_init; ngx_str_t define_pattern; char *converter; if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->headers_out.content_length_n == 0) { return ngx_http_next_header_filter(r); } srv_conf = ngx_http_get_module_srv_conf(r, ngx_http_small_light_module); loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module); if (!loc_conf->enable) { return ngx_http_next_header_filter(r); } if (!loc_conf->enable_getparam_mode) { if(ngx_http_small_light_parse_define_pattern(r, &r->unparsed_uri, &define_pattern) != NGX_OK) { return ngx_http_next_header_filter(r); } } ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module); if (ctx) { ngx_http_set_ctx(r, NULL, ngx_http_small_light_module); return ngx_http_next_header_filter(r); } if ((ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ctx->params.keys.pool = r->pool; ctx->params.temp_pool = r->pool; if (ngx_hash_keys_array_init(&ctx->params, NGX_HASH_SMALL) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to init hash keys for parameters %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (loc_conf->enable_getparam_mode) { if (ngx_http_small_light_init_getparams(r, ctx, srv_conf) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to analyze parameters:%V %s:%d", &define_pattern, __FUNCTION__, __LINE__); return NGX_ERROR; } } else { if (ngx_http_small_light_init_params(r, ctx, &define_pattern, srv_conf) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to analyze parameters:%V %s:%d", &define_pattern, __FUNCTION__, __LINE__); return NGX_ERROR; } } hash_init.hash = &ctx->hash; hash_init.key = ngx_hash_key_lc; hash_init.max_size = 128; hash_init.bucket_size = ngx_cacheline_size; hash_init.name = "small_light_init_params"; hash_init.pool = ctx->params.keys.pool; hash_init.temp_pool = NULL; if (ngx_hash_init(&hash_init, ctx->params.keys.elts, ctx->params.keys.nelts) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to init hash table for parameters %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ctx->inf = (char *)r->headers_out.content_type.data; ctx->material_dir = &srv_conf->material_dir; ctx->imlib2_temp_dir = loc_conf->imlib2_temp_dir; ctx->radius_max = loc_conf->radius_max; ctx->sigma_max = loc_conf->sigma_max; if (r->headers_out.content_length_n < 0) { ctx->content_length = loc_conf->buffer_size; } else { ctx->content_length = r->headers_out.content_length_n; } converter = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "e"); if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_IMAGEMAGICK) == 0) { ctx->converter.init = ngx_http_small_light_imagemagick_init; ctx->converter.term = ngx_http_small_light_imagemagick_term; ctx->converter.process = ngx_http_small_light_imagemagick_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t)); #ifdef NGX_HTTP_SMALL_LIGHT_IMLIB2_ENABLED } else if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_IMLIB2) == 0) { ctx->converter.init = ngx_http_small_light_imlib2_init; ctx->converter.term = ngx_http_small_light_imlib2_term; ctx->converter.process = ngx_http_small_light_imlib2_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imlib2_ctx_t)); #endif #ifdef NGX_HTTP_SMALL_LIGHT_GD_ENABLED } else if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_GD) == 0) { ctx->converter.init = ngx_http_small_light_gd_init; ctx->converter.term = ngx_http_small_light_gd_term; ctx->converter.process = ngx_http_small_light_gd_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_gd_ctx_t)); #endif } else { ctx->converter.init = ngx_http_small_light_imagemagick_init; ctx->converter.term = ngx_http_small_light_imagemagick_term; ctx->converter.process = ngx_http_small_light_imagemagick_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t)); } if (ctx->ictx == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_small_light_module); if (r->headers_out.refresh) { r->headers_out.refresh->hash = 0; } r->main_filter_need_in_memory = 1; r->allow_ranges = 0; return NGX_OK; }
static ngx_int_t ngx_http_spdy_serverpush_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { off_t size; ngx_buf_t *b; ngx_chain_t *cl, *ll, *out, **ln; ngx_http_spdy_stream_t *stream; ngx_http_spdy_out_frame_t *frame; //ngx_int_t static_handler_return_value; ngx_output_chain_ctx_t *ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); ngx_http_set_ctx(r, ctx, ngx_http_spdy_serverpush_filter_module); ngx_int_t ret_SH = ngx_http_static_handler(r); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "static_handler return : %d", ret_SH); stream = myStream; if (stream == NULL) { return ngx_http_next_body_filter(r, in); } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy body filter \"%V?%V\"", &r->uri, &r->args); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Data in server Push "); if (myChain == NULL || r->header_only) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Ending"); if (stream->waiting) { return NGX_AGAIN; } r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED; return NGX_OK; } size = 0; ln = &out; ll = myChain; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "into for "); for ( ;; ) { b = ll->buf; //#if 1 if(b->file) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "file detected push : %d",(b->file_last-b->file_pos)); ngx_int_t my_size = b->file_last-b->file_pos; u_char* my_buf = ngx_pcalloc(r->pool,sizeof(u_char)*my_size); ngx_read_file(b->file, my_buf, my_size, 0); b->start = my_buf; b->pos = my_buf; b->last = my_buf+my_size;//+NGX_SPDY_FRAME_HEADER_SIZE; } if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "zero size buf in spdy body filter " "t:%d r:%d f:%d %p %p-%p %p %O-%O", b->temporary, b->recycled, b->in_file, b->start, b->pos, b->last, b->file, b->file_pos, b->file_last); ngx_debug_point(); return NGX_ERROR; } //#endif ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "out of for"); cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } size += ngx_buf_size(b); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Size %d ",size); cl->buf = b; *ln = cl; ln = &cl->next; if (ll->next == NULL) { break; } ll = ll->next; } if (size > NGX_SPDY_MAX_FRAME_SIZE) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "FIXME: chain too big in spdy filter: %O", size); return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ONE "); frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size, b->last_buf, out, cl); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "FOUR "); if (frame == NULL) { return NGX_ERROR; } ngx_http_spdy_queue_frame(stream->connection, frame); stream->waiting++; r->main->blocked++; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Data in server Push end"); ngx_http_spdy_serverpush_filter_send(r->connection, stream); return ngx_http_next_body_filter(r,in); }
static ngx_int_t ngx_http_eval_handler(ngx_http_request_t *r) { /* size_t loc_len; */ ngx_str_t args; ngx_str_t subrequest_uri; ngx_uint_t flags; /* ngx_http_core_loc_conf_t *clcf; */ ngx_http_eval_loc_conf_t *ecf; ngx_http_eval_ctx_t *ctx; ngx_http_eval_ctx_t *sr_ctx; ngx_http_request_t *sr; ngx_int_t rc; ngx_http_post_subrequest_t *psr; u_char *p; /* if(r != r->main) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); loc_len = r->valid_location ? clcf->name.len : 0; if(r->uri.len != loc_len) { r->uri.data += loc_len; r->uri.len -= loc_len; } else { r->uri.len = 1; } } */ ecf = ngx_http_get_module_loc_conf(r, ngx_http_eval_module); if(ecf->variables == NULL || !ecf->variables->nelts) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_eval_module); if(ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_eval_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->base_conf = ecf; ngx_http_set_ctx(r, ctx, ngx_http_eval_module); } if (ctx->done) { dd("subrequest done"); if(!ecf->escalate || ctx->status == NGX_OK || ctx->status == NGX_HTTP_OK) { return NGX_DECLINED; } dd("status: %d", (int) ctx->status); return ctx->status; } if (ctx->in_progress) { dd("still in progress"); return NGX_DONE; } psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } if(ngx_http_eval_init_variables(r, ctx, ecf) != NGX_OK) { return NGX_ERROR; } args = r->args; flags = 0; subrequest_uri.len = ecf->eval_location.len + r->uri.len; p = subrequest_uri.data = ngx_palloc(r->pool, subrequest_uri.len); if(p == NULL) { return NGX_ERROR; } p = ngx_copy(p, ecf->eval_location.data, ecf->eval_location.len); p = ngx_copy(p, r->uri.data, r->uri.len); if (ngx_http_parse_unsafe_uri(r, &subrequest_uri, &args, &flags) != NGX_OK) { return NGX_ERROR; } psr->handler = ngx_http_eval_post_subrequest_handler; psr->data = ctx; flags |= NGX_HTTP_SUBREQUEST_WAITED; dd("subrequest in memory : %d", (int) ecf->subrequest_in_memory); if (ecf->subrequest_in_memory) { flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; } else { } dd("issue subrequest"); rc = ngx_http_subrequest(r, &subrequest_uri, &args, &sr, psr, flags); if (rc == NGX_ERROR || rc == NGX_DONE) { return rc; } sr->discard_body = 1; ctx->in_progress = 1; /* XXX we don't allow eval in subrequests, i think? */ sr_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_eval_ctx_t)); if (sr_ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(sr, sr_ctx, ngx_http_eval_module); dd("wait for subrequest to complete"); return NGX_DONE; }
void ngx_php_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) { TSRMLS_FETCH(); char *buffer; int buffer_len, display; buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args); /* check for repeated errors to be ignored */ if (PG(ignore_repeated_errors) && PG(last_error_message)) { /* no check for PG(last_error_file) is needed since it cannot * be NULL if PG(last_error_message) is not NULL */ if (strcmp(PG(last_error_message), buffer) || (!PG(ignore_repeated_source) && ((PG(last_error_lineno) != (int)error_lineno) || strcmp(PG(last_error_file), error_filename)))) { display = 1; } else { display = 0; } } else { display = 1; } /* store the error if it has changed */ if (display) { if (PG(last_error_message)) { free(PG(last_error_message)); PG(last_error_message) = NULL; } if (PG(last_error_file)) { free(PG(last_error_file)); PG(last_error_file) = NULL; } if (!error_filename) { error_filename = "Unknown"; } PG(last_error_type) = type; PG(last_error_message) = strdup(buffer); PG(last_error_file) = strdup(error_filename); PG(last_error_lineno) = error_lineno; } /* according to error handling mode, suppress error, throw exception or show it */ if (EG(error_handling) != EH_NORMAL) { switch (type) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: case E_PARSE: /* fatal errors are real errors and cannot be made exceptions */ break; case E_STRICT: case E_DEPRECATED: case E_USER_DEPRECATED: /* for the sake of BC to old damaged code */ break; case E_NOTICE: case E_USER_NOTICE: /* notices are no errors and are not treated as such like E_WARNINGS */ break; default: /* throw an exception if we are in EH_THROW mode * but DO NOT overwrite a pending exception */ if (EG(error_handling) == EH_THROW && !EG(exception)) { zend_throw_error_exception(EG(exception_class), buffer, 0, type TSRMLS_CC); } efree(buffer); return; } } /* display/log the error if necessary */ if (display && (EG(error_reporting) & type || (type & E_CORE)) && (PG(log_errors) || PG(display_errors) ) ) { char *error_type_str; switch (type) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: error_type_str = "Fatal error"; break; case E_RECOVERABLE_ERROR: error_type_str = "Catchable fatal error"; break; case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: case E_USER_WARNING: error_type_str = "Warning"; break; case E_PARSE: error_type_str = "Parse error"; break; case E_NOTICE: case E_USER_NOTICE: error_type_str = "Notice"; break; case E_STRICT: error_type_str = "Strict Standards"; break; case E_DEPRECATED: case E_USER_DEPRECATED: error_type_str = "Deprecated"; break; default: error_type_str = "Unknown error"; break; } buffer_len = spprintf(&buffer, 0, "%s: %s in %s on line %d", error_type_str, buffer, error_filename, error_lineno); ngx_buf_t *b; ngx_http_php_rputs_chain_list_t *chain; ngx_http_php_ctx_t *ctx; ngx_http_request_t *r; u_char *u_str; ngx_str_t ns; r = ngx_php_request; ctx = ngx_http_get_module_ctx(r, ngx_http_php_module); if ( ctx == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", buffer); ngx_php_debug("ngx_php error handler, ctx is nil."); efree(buffer); zend_bailout(); ngx_http_php_zend_uthread_exit(r); return ; } ns.data = (u_char *)buffer; ns.len = buffer_len; if (ctx->rputs_chain == NULL){ chain = ngx_pcalloc(r->pool, sizeof(ngx_http_php_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; }else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; u_str = ngx_pstrdup(r->pool, &ns); //u_str[ns.len] = '\0'; (*chain->last)->buf->pos = u_str; (*chain->last)->buf->last = u_str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_php_module); if (r->headers_out.content_length_n == -1){ r->headers_out.content_length_n += ns.len + 1; }else { r->headers_out.content_length_n += ns.len; } if (!r->headers_out.status) { r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", buffer); ngx_php_debug("ngx_php error handler."); efree(buffer); zend_bailout(); ngx_http_php_zend_uthread_exit(r); return ; } /* Log if necessary */ if (!display) { efree(buffer); return; } efree(buffer); }
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; } 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; }
static int ngx_http_lua_ngx_location_capture_multi(lua_State *L) { ngx_http_request_t *r; ngx_http_request_t *sr = NULL; /* subrequest object */ ngx_http_post_subrequest_t *psr; ngx_http_lua_ctx_t *sr_ctx; ngx_http_lua_ctx_t *ctx; ngx_array_t *extra_vars; ngx_str_t uri; ngx_str_t args; ngx_str_t extra_args; ngx_uint_t flags; u_char *p; u_char *q; size_t len; size_t nargs; int rc; int n; int always_forward_body = 0; ngx_uint_t method; ngx_http_request_body_t *body; int type; ngx_buf_t *b; unsigned vars_action; ngx_uint_t nsubreqs; ngx_uint_t index; size_t sr_statuses_len; size_t sr_headers_len; size_t sr_bodies_len; size_t sr_flags_len; size_t ofs1, ofs2; unsigned custom_ctx; ngx_http_lua_co_ctx_t *coctx; ngx_http_lua_post_subrequest_data_t *psr_data; n = lua_gettop(L); if (n != 1) { return luaL_error(L, "only one argument is expected, but got %d", n); } luaL_checktype(L, 1, LUA_TTABLE); nsubreqs = lua_objlen(L, 1); if (nsubreqs == 0) { return luaL_error(L, "at least one subrequest should be specified"); } r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); coctx = ctx->cur_co_ctx; if (coctx == NULL) { return luaL_error(L, "no co ctx found"); } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua location capture, uri:\"%V\" c:%ud", &r->uri, r->main->count); sr_statuses_len = nsubreqs * sizeof(ngx_int_t); sr_headers_len = nsubreqs * sizeof(ngx_http_headers_out_t *); sr_bodies_len = nsubreqs * sizeof(ngx_str_t); sr_flags_len = nsubreqs * sizeof(uint8_t); p = ngx_pcalloc(r->pool, sr_statuses_len + sr_headers_len + sr_bodies_len + sr_flags_len); if (p == NULL) { return luaL_error(L, "no memory"); } coctx->sr_statuses = (void *) p; p += sr_statuses_len; coctx->sr_headers = (void *) p; p += sr_headers_len; coctx->sr_bodies = (void *) p; p += sr_bodies_len; coctx->sr_flags = (void *) p; coctx->nsubreqs = nsubreqs; coctx->pending_subreqs = 0; extra_vars = NULL; for (index = 0; index < nsubreqs; index++) { coctx->pending_subreqs++; lua_rawgeti(L, 1, index + 1); if (lua_isnil(L, -1)) { return luaL_error(L, "only array-like tables are allowed"); } dd("queries query: top %d", lua_gettop(L)); if (lua_type(L, -1) != LUA_TTABLE) { return luaL_error(L, "the query argument %d is not a table, " "but a %s", index, lua_typename(L, lua_type(L, -1))); } nargs = lua_objlen(L, -1); if (nargs != 1 && nargs != 2) { return luaL_error(L, "query argument %d expecting one or " "two arguments", index); } lua_rawgeti(L, 2, 1); /* queries query uri */ dd("queries query uri: %d", lua_gettop(L)); dd("first arg in first query: %s", lua_typename(L, lua_type(L, -1))); body = NULL; ngx_str_null(&extra_args); if (extra_vars != NULL) { /* flush out existing elements in the array */ extra_vars->nelts = 0; } vars_action = 0; custom_ctx = 0; if (nargs == 2) { /* check out the options table */ lua_rawgeti(L, 2, 2); /* queries query uri opts */ dd("queries query uri opts: %d", lua_gettop(L)); if (lua_type(L, 4) != LUA_TTABLE) { return luaL_error(L, "expecting table as the 2nd argument for " "subrequest %d, but got %s", index, luaL_typename(L, 4)); } dd("queries query uri opts: %d", lua_gettop(L)); /* check the args option */ lua_getfield(L, 4, "args"); type = lua_type(L, -1); switch (type) { case LUA_TTABLE: ngx_http_lua_process_args_option(r, L, -1, &extra_args); break; case LUA_TNIL: /* do nothing */ break; case LUA_TNUMBER: case LUA_TSTRING: extra_args.data = (u_char *) lua_tolstring(L, -1, &len); extra_args.len = len; break; default: return luaL_error(L, "Bad args option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the vars option */ lua_getfield(L, 4, "vars"); switch (lua_type(L, -1)) { case LUA_TTABLE: ngx_http_lua_process_vars_option(r, L, -1, &extra_vars); dd("post process vars top: %d", lua_gettop(L)); break; case LUA_TNIL: /* do nothing */ break; default: return luaL_error(L, "Bad vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the share_all_vars option */ lua_getfield(L, 4, "share_all_vars"); switch (lua_type(L, -1)) { case LUA_TNIL: /* do nothing */ break; case LUA_TBOOLEAN: if (lua_toboolean(L, -1)) { vars_action |= NGX_HTTP_LUA_SHARE_ALL_VARS; } break; default: return luaL_error(L, "Bad share_all_vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the copy_all_vars option */ lua_getfield(L, 4, "copy_all_vars"); switch (lua_type(L, -1)) { case LUA_TNIL: /* do nothing */ break; case LUA_TBOOLEAN: if (lua_toboolean(L, -1)) { vars_action |= NGX_HTTP_LUA_COPY_ALL_VARS; } break; default: return luaL_error(L, "Bad copy_all_vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the "forward_body" option */ lua_getfield(L, 4, "always_forward_body"); always_forward_body = lua_toboolean(L, -1); lua_pop(L, 1); dd("always foward body: %d", always_forward_body); /* check the "method" option */ lua_getfield(L, 4, "method"); type = lua_type(L, -1); if (type == LUA_TNIL) { method = NGX_HTTP_GET; } else { if (type != LUA_TNUMBER) { return luaL_error(L, "Bad http request method"); } method = (ngx_uint_t) lua_tonumber(L, -1); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the "ctx" option */ lua_getfield(L, 4, "ctx"); type = lua_type(L, -1); if (type != LUA_TNIL) { if (type != LUA_TTABLE) { return luaL_error(L, "Bad ctx option value type %s, " "expected a Lua table", lua_typename(L, type)); } custom_ctx = 1; } else { lua_pop(L, 1); } dd("queries query uri opts ctx?: %d", lua_gettop(L)); /* check the "body" option */ lua_getfield(L, 4, "body"); type = lua_type(L, -1); if (type != LUA_TNIL) { if (type != LUA_TSTRING && type != LUA_TNUMBER) { return luaL_error(L, "Bad http request body"); } body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (body == NULL) { return luaL_error(L, "no memory"); } q = (u_char *) lua_tolstring(L, -1, &len); dd("request body: [%.*s]", (int) len, q); if (len) { b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return luaL_error(L, "no memory"); } b->last = ngx_copy(b->last, q, len); body->bufs = ngx_alloc_chain_link(r->pool); if (body->bufs == NULL) { return luaL_error(L, "no memory"); } body->bufs->buf = b; body->bufs->next = NULL; body->buf = b; } } lua_pop(L, 1); /* pop the body */ /* stack: queries query uri opts ctx? */ lua_remove(L, 4); /* stack: queries query uri ctx? */ dd("queries query uri ctx?: %d", lua_gettop(L)); } else { method = NGX_HTTP_GET; } /* stack: queries query uri ctx? */ p = (u_char *) luaL_checklstring(L, 3, &len); uri.data = ngx_palloc(r->pool, len); if (uri.data == NULL) { return luaL_error(L, "memory allocation error"); } ngx_memcpy(uri.data, p, len); uri.len = len; ngx_str_null(&args); flags = 0; rc = ngx_http_parse_unsafe_uri(r, &uri, &args, &flags); if (rc != NGX_OK) { dd("rc = %d", (int) rc); return luaL_error(L, "unsafe uri in argument #1: %s", p); } if (args.len == 0) { if (extra_args.len) { p = ngx_palloc(r->pool, extra_args.len); if (p == NULL) { return luaL_error(L, "no memory"); } ngx_memcpy(p, extra_args.data, extra_args.len); args.data = p; args.len = extra_args.len; } } else if (extra_args.len) { /* concatenate the two parts of args together */ len = args.len + (sizeof("&") - 1) + extra_args.len; p = ngx_palloc(r->pool, len); if (p == NULL) { return luaL_error(L, "no memory"); } q = ngx_copy(p, args.data, args.len); *q++ = '&'; ngx_memcpy(q, extra_args.data, extra_args.len); args.data = p; args.len = len; } ofs1 = ngx_align(sizeof(ngx_http_post_subrequest_t), sizeof(void *)); ofs2 = ngx_align(sizeof(ngx_http_lua_ctx_t), sizeof(void *)); p = ngx_palloc(r->pool, ofs1 + ofs2 + sizeof(ngx_http_lua_post_subrequest_data_t)); if (p == NULL) { return luaL_error(L, "no memory"); } psr = (ngx_http_post_subrequest_t *) p; p += ofs1; sr_ctx = (ngx_http_lua_ctx_t *) p; ngx_http_lua_assert((void *) sr_ctx == ngx_align_ptr(sr_ctx, sizeof(void *))); p += ofs2; psr_data = (ngx_http_lua_post_subrequest_data_t *) p; ngx_http_lua_assert((void *) psr_data == ngx_align_ptr(psr_data, sizeof(void *))); ngx_memzero(sr_ctx, sizeof(ngx_http_lua_ctx_t)); /* set by ngx_memzero: * sr_ctx->run_post_subrequest = 0 * sr_ctx->free = NULL * sr_ctx->body = NULL */ psr_data->ctx = sr_ctx; psr_data->pr_co_ctx = coctx; psr->handler = ngx_http_lua_post_subrequest; psr->data = psr_data; rc = ngx_http_lua_subrequest(r, &uri, &args, &sr, psr, 0); if (rc != NGX_OK) { return luaL_error(L, "failed to issue subrequest: %d", (int) rc); } ngx_http_lua_init_ctx(sr, sr_ctx); sr_ctx->capture = 1; sr_ctx->index = index; sr_ctx->last_body = &sr_ctx->body; sr_ctx->vm_state = ctx->vm_state; ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module); rc = ngx_http_lua_adjust_subrequest(sr, method, always_forward_body, body, vars_action, extra_vars); if (rc != NGX_OK) { ngx_http_lua_cancel_subreq(sr); return luaL_error(L, "failed to adjust the subrequest: %d", (int) rc); } dd("queries query uri opts ctx? %d", lua_gettop(L)); /* stack: queries query uri ctx? */ if (custom_ctx) { ngx_http_lua_ngx_set_ctx_helper(L, sr, sr_ctx, -1); lua_pop(L, 3); } else { lua_pop(L, 2); } /* stack: queries */ } if (extra_vars) { ngx_array_destroy(extra_vars); } ctx->no_abort = 1; return lua_yield(L, 0); }
static ngx_int_t ngx_http_upstreamTest_handler(ngx_http_request_t *r) { static ngx_int_t visited_times = 0; ngx_http_upstreamTest_ctx_t *upstreamctx = ngx_http_get_module_ctx(r,ngx_http_upstreamTest_module); if(upstreamctx == NULL) { upstreamctx = ngx_pcalloc(r->pool,sizeof(ngx_http_upstreamTest_ctx_t)); if(upstreamctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r,upstreamctx,ngx_http_upstream_module); } if(ngx_http_upstream_create(r) != NGX_OK) { ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_http_upstream_create() failed"); return NGX_ERROR; } ngx_http_upstreamTest_conf_t *upstreamconf = (ngx_http_upstreamTest_conf_t *)ngx_http_get_module_loc_conf(r,ngx_http_upstreamTest_module); ngx_http_upstream_t *u = r->upstream; u->conf = &upstreamconf->upstream; u->buffering = upstreamconf->upstream.buffering; u->resolved = (ngx_http_upstream_resolved_t*)ngx_pcalloc(r->pool,sizeof(ngx_http_upstream_resolved_t)); if(u->resolved == NULL) { ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_pcalloc resolved error. %s",strerror(errno)); return NGX_ERROR; } // static struct sockaddr_in backendSockAddr; // backendSockAddr.sin_family = AF_INET; // backendSockAddr.sin_port = htons((in_port_t)7777); // backendSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr; // u->resolved->socklen = sizeof(struct sockaddr_in); // u->resolved->naddrs = 1; u->create_request = ngx_http_upstreamTest_create_request; u->process_header = ngx_http_upstreamTest_process_status_line; u->finalize_request = ngx_http_upstreamTest_finalize_request; // r->main->count++; // ngx_http_upstream_init(r); if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; u_char ngx_upstream_string[1024]; ngx_sprintf(ngx_upstream_string,"Visited times: %d",++visited_times); ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"ngx_upstream_string: %s",ngx_upstream_string); ngx_uint_t content_length = ngx_strlen(ngx_upstream_string); ngx_int_t rc; if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; rc = ngx_http_discard_request_body(r); if(rc != NGX_OK) { ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"discard requst_body failed!"); return rc; } ngx_str_set(&r->headers_out.content_type,"text/html"); if(r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"send respond head!"); return ngx_http_send_header(r); } ngx_buf_t *b; b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_chain_t out; out.buf = b; out.next = NULL; b->pos = ngx_upstream_string; b->last = ngx_upstream_string + content_length; b->memory = 1; b->last_buf = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) return rc; ngx_http_output_filter(r,&out); r->main->count++; ngx_http_upstream_init(r); return NGX_OK; }
//#define mechanics_debug //naxsi_modifiers_debug static ngx_int_t ngx_http_dummy_access_handler(ngx_http_request_t *r) { ngx_http_request_ctx_t *ctx; ngx_int_t rc; ngx_http_dummy_loc_conf_t *cf; ngx_http_core_loc_conf_t *clcf; struct tms tmsstart, tmsend; clock_t start, end; ngx_http_variable_value_t *lookup; static ngx_str_t learning_flag = ngx_string(RT_LEARNING); static ngx_str_t enable_flag = ngx_string(RT_ENABLE); static ngx_str_t post_action_flag = ngx_string(RT_POST_ACTION); ctx = ngx_http_get_module_ctx(r, ngx_http_naxsi_module); cf = ngx_http_get_module_loc_conf(r, ngx_http_naxsi_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); /* ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, */ /* "naxsi_entry_point"); */ if (ctx && ctx->over) return (NGX_DECLINED); if (ctx && ctx->wait_for_body) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "naxsi:NGX_AGAIN"); #endif return (NGX_DONE); } if (!cf) return (NGX_ERROR); /* the module is not enabled here */ if (!cf->enabled || cf->force_disabled) return (NGX_DECLINED); /* don't process internal requests. */ if (r->internal) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-DON'T PROCESS (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); #endif return (NGX_DECLINED); } #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-processing (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args), r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!", r->internal); #endif if (!ctx) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_request_ctx_t)); /* might have been set by a previous trigger */ if (ctx->learning) { clcf->post_action.data = 0; //cf->denied_url->data; clcf->post_action.len = 0; //cf->denied_url->len; } if (ctx == NULL) return NGX_ERROR; ngx_http_set_ctx(r, ctx, ngx_http_naxsi_module); #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig learning : %d", cf->learning ? 1 : 0); #endif ctx->learning = cf->learning; lookup = ngx_http_get_variable(r, &learning_flag, cf->flag_learning_h); if (lookup && !lookup->not_found) { ctx->learning = lookup->data[0] - '0'; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override learning : %d", ctx->learning ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] learning : %d", ctx->learning ? 1 : 0); #endif ctx->enabled = cf->enabled; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig enabled : %d", ctx->enabled ? 1 : 0); #endif lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h); if (lookup && !lookup->not_found) { ctx->enabled = lookup->data[0] - '0'; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override enable : %d", ctx->enabled ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] enabled : %d", ctx->enabled ? 1 : 0); #endif if (cf->learning) ctx->post_action = 1; else ctx->post_action = 0; #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : orig post_action : %d", ctx->post_action ? 1 : 0); #endif lookup = ngx_http_get_variable(r, &post_action_flag, cf->flag_post_action_h); if (lookup && !lookup->not_found) { ctx->post_action = lookup->data[0] - '0'; #ifdef naxsi_modifier_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : override post_action : %d", ctx->post_action ? 1 : 0); #endif } #ifdef naxsi_modifiers_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : [final] post_action : %d", ctx->post_action ? 1 : 0); #endif //--- /* the module is not enabled here */ if (!ctx->enabled) return (NGX_DECLINED); if ((r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) && !ctx->ready) { #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : before !"); #endif rc = ngx_http_read_client_request_body(r, ngx_http_dummy_payload_handler); /* this might happen quite often, especially with big files / ** low network speed. our handler is called when headers are read, ** but, often, the full body request hasn't yet, so ** read client request body will return ngx_again. Then we need ** to return ngx_done, wait for our handler to be called once ** body request arrived, and let him call core_run_phases ** to be able to process the request. */ if (rc == NGX_AGAIN) { ctx->wait_for_body = 1; #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : body_request : NGX_AGAIN !"); #endif return (NGX_DONE); } else if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { /* this debug print should be commented, but the thing is that ** according to what I read into nginx src code, it may happen ** and I haven't been abble to trigger this, so I just let it ** here to know when this special case will be triggered */ ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : SPECIAL RESPONSE !!!!"); return rc; } } else ctx->ready = 1; } if (ctx && ctx->ready && !ctx->over) { if ((start = times(&tmsstart)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); ngx_http_dummy_data_parse(ctx, r); cf->request_processed++; if ((end = times(&tmsend)) == (clock_t)-1) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-dummy : Failed to get time"); if (end - start > 0) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "[MORE THAN 1MS] times : start:%l end:%l diff:%l", start, end, (end-start)); ctx->over = 1; if (ctx->block) { cf->request_blocked++; rc = ngx_http_output_forbidden_page(ctx, r); //nothing: return (NGX_OK); //redirect : return (NGX_HTTP_OK); return (rc); } else if (ctx->log) rc = ngx_http_output_forbidden_page(ctx, r); } #ifdef mechanics_debug ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "NGX_FINISHED !"); #endif return (NGX_DECLINED); }
ngx_int_t ngx_http_drizzle_handler(ngx_http_request_t *r) { ngx_http_upstream_t *u; ngx_http_drizzle_loc_conf_t *dlcf; #if defined(nginx_version) && nginx_version < 8017 ngx_http_drizzle_ctx_t *dctx; #endif ngx_http_core_loc_conf_t *clcf; ngx_str_t target; ngx_url_t url; ngx_connection_t *c; dd("request: %p", r); dd("subrequest in memory: %d", (int) r->subrequest_in_memory); dd("connection: %p", r->connection); dd("connection log: %p", r->connection->log); if (r->subrequest_in_memory) { /* TODO: add support for subrequest in memory by * emitting output into u->buffer instead */ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_http_drizzle_module does not support " "subrequest in memory"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } dlcf = ngx_http_get_module_loc_conf(r, ngx_http_drizzle_module); if ((dlcf->default_query == NULL) && !(dlcf->methods_set & r->method)) { if (dlcf->methods_set != 0) { return NGX_HTTP_NOT_ALLOWED; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: missing \"drizzle_query\" in location \"%V\"", &clcf->name); return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("XXX upstream already exists? %p", r->upstream); #if defined(nginx_version) && \ ((nginx_version >= 7063 && nginx_version < 8000) \ || nginx_version >= 8007) dd("creating upstream......."); if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; #else /* 0.7.x < 0.7.63, 0.8.x < 0.8.7 */ dd("XXX create upstream"); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; # if (NGX_THREADS) u->peer.lock = &r->connection->lock; # endif r->upstream = u; #endif if (dlcf->complex_target) { /* variables used in the drizzle_pass directive */ if (ngx_http_complex_value(r, dlcf->complex_target, &target) != NGX_OK) { dd("failed to compile"); return NGX_ERROR; } if (target.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: handler: empty \"drizzle_pass\" target"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } url.host = target; url.port = 0; url.no_resolve = 1; dlcf->upstream.upstream = ngx_http_upstream_drizzle_add(r, &url); if (dlcf->upstream.upstream == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "drizzle: upstream \"%V\" not found", &target); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } #if defined(nginx_version) && nginx_version < 8017 dctx = ngx_pcalloc(r->pool, sizeof(ngx_http_drizzle_ctx_t)); if (dctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, dctx, ngx_http_drizzle_module); #endif u->schema.len = sizeof("drizzle://") - 1; u->schema.data = (u_char *) "drizzle://"; u->output.tag = (ngx_buf_tag_t) &ngx_http_drizzle_module; dd("drizzle tag: %p", (void *) u->output.tag); u->conf = &dlcf->upstream; u->create_request = ngx_http_drizzle_create_request; u->reinit_request = ngx_http_drizzle_reinit_request; u->process_header = ngx_http_drizzle_process_header; u->abort_request = ngx_http_drizzle_abort_request; u->finalize_request = ngx_http_drizzle_finalize_request; /* we bypass the upstream input filter mechanism in * ngx_http_upstream_process_headers */ u->input_filter_init = ngx_http_drizzle_input_filter_init; u->input_filter = ngx_http_drizzle_input_filter; u->input_filter_ctx = NULL; #if defined(nginx_version) && nginx_version >= 8011 r->main->count++; #endif dd("XXX connect timeout: %d", (int) dlcf->upstream.connect_timeout); ngx_http_upstream_dbd_init(r); /* override the read/write event handler to our own */ u->write_event_handler = ngx_http_drizzle_wev_handler; u->read_event_handler = ngx_http_drizzle_rev_handler; /* a bit hack-ish way to return error response (clean-up part) */ if ((u->peer.connection) && (u->peer.connection->fd == 0)) { c = u->peer.connection; u->peer.connection = NULL; if (c->write->timer_set) { ngx_del_timer(c->write); } ngx_free_connection(c); ngx_http_upstream_drizzle_finalize_request(r, u, #if defined(nginx_version) && (nginx_version >= 8017) NGX_HTTP_SERVICE_UNAVAILABLE); #else dctx->status ? dctx->status : NGX_HTTP_INTERNAL_SERVER_ERROR); #endif }
static mrb_value ngx_mrb_echo(mrb_state *mrb, mrb_value self) { mrb_value argv; ngx_buf_t *b; ngx_mrb_rputs_chain_list_t *chain; u_char *str; ngx_str_t ns; ngx_http_request_t *r = ngx_mrb_get_request(); ngx_http_mruby_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); mrb_get_args(mrb, "o", &argv); if (mrb_type(argv) != MRB_TT_STRING) { argv = mrb_funcall(mrb, argv, "to_s", 0, NULL); } ns.data = (u_char *)RSTRING_PTR( mrb_str_plus(mrb, argv, mrb_str_new_lit(mrb, "\n"))); ns.len = RSTRING_LEN(argv) + sizeof("\n") - 1; if (ns.len == 0) { return self; } if (ctx->rputs_chain == NULL) { chain = ngx_pcalloc(r->pool, sizeof(ngx_mrb_rputs_chain_list_t)); if (chain == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "failed to allocate memory"); } chain->out = ngx_alloc_chain_link(r->pool); if (chain->out == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "failed to allocate memory"); } chain->last = &chain->out; } else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); if ((*chain->last)->next == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "failed to allocate memory"); } chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); if (b == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "failed to allocate memory"); } (*chain->last)->buf = b; (*chain->last)->next = NULL; str = ngx_pstrdup(r->pool, &ns); if (str == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "failed to allocate memory"); } str[ns.len] = '\0'; (*chain->last)->buf->pos = str; (*chain->last)->buf->last = str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); if (r->headers_out.content_length_n == -1) { r->headers_out.content_length_n += ns.len + 1; } else { r->headers_out.content_length_n += ns.len; } return self; }
static ngx_int_t ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_connection_t *c; ngx_output_chain_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; ngx_http_copy_filter_conf_t *conf; c = r->connection; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http copy filter: \"%V?%V\"", &r->uri, &r->args); ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_copy_filter_module); conf = ngx_http_get_module_loc_conf(r, ngx_http_copy_filter_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ctx->sendfile = c->sendfile; ctx->need_in_memory = r->main_filter_need_in_memory || r->filter_need_in_memory; ctx->need_in_temp = r->filter_need_temporary; ctx->alignment = clcf->directio_alignment; ctx->pool = r->pool; ctx->bufs = conf->bufs; ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module; ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_body_filter; ctx->filter_ctx = r; #if (NGX_HAVE_FILE_AIO) if (ngx_file_aio) { if (clcf->aio) { ctx->aio_handler = ngx_http_copy_aio_handler; } #if (NGX_HAVE_AIO_SENDFILE) c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE); #endif } #endif if (in && in->buf && ngx_buf_size(in->buf)) { r->request_output = 1; } } #if (NGX_HAVE_FILE_AIO) ctx->aio = r->aio; #endif for ( ;; ) { rc = ngx_output_chain(ctx, in); if (ctx->in == NULL) { r->buffered &= ~NGX_HTTP_COPY_BUFFERED; } else { r->buffered |= NGX_HTTP_COPY_BUFFERED; } ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args); #if (NGX_HAVE_FILE_AIO && NGX_HAVE_AIO_SENDFILE) if (c->busy_sendfile) { ssize_t n; off_t offset; ngx_file_t *file; ngx_http_ephemeral_t *e; if (r->aio) { c->busy_sendfile = NULL; return rc; } file = c->busy_sendfile->file; offset = c->busy_sendfile->file_pos; if (file->aio) { c->busy_count = (offset == file->aio->last_offset) ? c->busy_count + 1 : 0; file->aio->last_offset = offset; if (c->busy_count > 2) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfile(%V) returned busy again", &file->name); c->aio_sendfile = 0; } } c->busy_sendfile = NULL; e = (ngx_http_ephemeral_t *) &r->uri_start; n = ngx_file_aio_read(file, &e->aio_preload, 1, offset, r->pool); if (n > 0) { in = NULL; continue; } rc = n; if (rc == NGX_AGAIN) { file->aio->data = r; file->aio->handler = ngx_http_copy_aio_sendfile_event_handler; r->main->blocked++; r->aio = 1; } } #endif return rc; } }
static ngx_int_t ngx_http_memcached_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; ngx_str_set(&u->schema, "memcached://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u->conf = &mlcf->upstream; u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_MEMCACHED_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; u->input_filter_ctx = ctx; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
ngx_int_t passenger_content_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; passenger_loc_conf_t *slcf; ngx_str_t path, base_uri; u_char *path_last, *end; u_char root_path_str[NGX_MAX_PATH + 1]; ngx_str_t root_path; size_t root, len; u_char page_cache_file_str[NGX_MAX_PATH + 1]; ngx_str_t page_cache_file; passenger_context_t *context; PP_Error error; if (passenger_main_conf.root_dir.len == 0) { return NGX_DECLINED; } else if (r->subrequest_in_memory) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_http_passenger_module does not support " "subrequest in memory"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module); /* Let the next content handler take care of this request if Phusion * Passenger is disabled for this URL. */ if (!slcf->enabled) { return NGX_DECLINED; } /* Let the next content handler take care of this request if this URL * maps to an existing file. */ path_last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (path_last != NULL && file_exists(path.data, 0)) { return NGX_DECLINED; } /* Create a string containing the root path. This path already * contains a trailing slash. */ end = ngx_copy(root_path_str, path.data, root); *end = '\0'; root_path.data = root_path_str; root_path.len = root; context = ngx_pcalloc(r->pool, sizeof(passenger_context_t)); if (context == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, context, ngx_http_passenger_module); /* Find the base URI for this web application, if any. */ if (find_base_uri(r, slcf, &base_uri)) { /* Store the found base URI into context->public_dir. We infer that the 'public' * directory of the web application is document root + base URI. */ len = root_path.len + base_uri.len + 1; context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len); end = ngx_copy(context->public_dir.data, root_path.data, root_path.len); end = ngx_copy(end, base_uri.data, base_uri.len); *end = '\0'; context->public_dir.len = len - 1; context->base_uri = base_uri; } else { /* No base URI directives are applicable for this request. So assume that * the web application's public directory is the document root. * context->base_uri is now a NULL string. */ len = sizeof(u_char *) * (root_path.len + 1); context->public_dir.data = ngx_palloc(r->pool, len); end = ngx_copy(context->public_dir.data, root_path.data, root_path.len); *end = '\0'; context->public_dir.len = root_path.len; } /* If there's a corresponding page cache file for this URL, then serve that * file instead. */ page_cache_file.data = page_cache_file_str; page_cache_file.len = sizeof(page_cache_file_str); if (map_uri_to_page_cache_file(r, &context->public_dir, path.data, path_last - path.data, &page_cache_file)) { return passenger_static_content_handler(r, &page_cache_file); } if (slcf->app_type.data == NULL) { pp_error_init(&error); if (slcf->app_root.data == NULL) { context->app_type = pp_app_type_detector_check_document_root( pp_app_type_detector, (const char *) context->public_dir.data, context->public_dir.len, context->base_uri.len != 0, &error); } else { context->app_type = pp_app_type_detector_check_app_root( pp_app_type_detector, (const char *) slcf->app_root.data, slcf->app_root.len, &error); } if (context->app_type == PAT_NONE) { return NGX_DECLINED; } else if (context->app_type == PAT_ERROR) { if (error.errnoCode == EACCES) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "%s; This error means that the Nginx worker process (PID %d, " "running as UID %d) does not have permission to access this file. " "Please read the manual to learn how to fix this problem: " "section 'Troubleshooting' -> 'Upon accessing the web app, Nginx " "reports a \"Permission denied\" error'; Extra info", error.message, (int) getpid(), (int) getuid()); } else { ngx_log_error(NGX_LOG_ALERT, r->connection->log, (error.errnoCode == PP_NO_ERRNO) ? 0 : error.errnoCode, "%s", error.message); } pp_error_destroy(&error); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { context->app_type = pp_get_app_type2((const char *) slcf->app_type.data, slcf->app_type.len); if (context->app_type == PAT_NONE) { return NGX_DECLINED; } } /* Setup upstream stuff and prepare sending the request to the backend. */ if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; u->schema = pp_schema_string; u->output.tag = (ngx_buf_tag_t) &ngx_http_passenger_module; set_upstream_server_address(u, &slcf->upstream_config); u->conf = &slcf->upstream_config; #if (NGX_HTTP_CACHE) u->create_key = create_key; #endif u->create_request = create_request; u->reinit_request = reinit_request; u->process_header = process_status_line; u->abort_request = abort_request; u->finalize_request = finalize_request; r->state = 0; u->buffering = slcf->upstream_config.buffering; u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); if (u->pipe == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->pipe->input_filter = ngx_event_pipe_copy_input_filter; u->pipe->input_ctx = r; rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); fix_peer_address(r); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; }
static ngx_int_t ngx_http_charset_header_filter(ngx_http_request_t *r) { ngx_int_t charset, source_charset; ngx_str_t *mc, *from, *to, s; ngx_uint_t n; ngx_http_charset_t *charsets; ngx_http_charset_ctx_t *ctx; ngx_http_variable_value_t *vv; ngx_http_charset_loc_conf_t *lcf, *mlcf; ngx_http_charset_main_conf_t *mcf; mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module); charsets = mcf->charsets.elts; n = mcf->charsets.nelts; /* destination charset */ if (r == r->main) { if (!r->ignore_content_encoding && r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) { return ngx_http_next_header_filter(r); } if (r->headers_out.content_type.len == 0) { return ngx_http_next_header_filter(r); } if (r->headers_out.override_charset && r->headers_out.override_charset->len) { charset = ngx_http_charset_get_charset(charsets, n, r->headers_out.override_charset); if (charset == NGX_HTTP_NO_CHARSET) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unknown charset \"%V\" to override", r->headers_out.override_charset); return ngx_http_next_header_filter(r); } } else { mlcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module); charset = mlcf->charset; if (charset == NGX_HTTP_NO_CHARSET) { return ngx_http_next_header_filter(r); } if (r->headers_out.charset.len) { if (mlcf->override_charset == 0) { return ngx_http_next_header_filter(r); } } else { if (ngx_http_test_content_type(r, &mlcf->types) == NULL) { return ngx_http_next_header_filter(r); } } if (charset >= NGX_HTTP_CHARSET_VAR) { vv = ngx_http_get_indexed_variable(r, charset - NGX_HTTP_CHARSET_VAR); if (vv == NULL || vv->not_found) { return NGX_ERROR; } s.len = vv->len; s.data = vv->data; charset = ngx_http_charset_get_charset(charsets, n, &s); } } } else { ctx = ngx_http_get_module_ctx(r->main, ngx_http_charset_filter_module); if (ctx == NULL) { mc = &r->main->headers_out.charset; if (mc->len == 0) { return ngx_http_next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r->main, ctx, ngx_http_charset_filter_module); charset = ngx_http_charset_get_charset(charsets, n, mc); ctx->charset = charset; } else { charset = ctx->charset; } } /* source charset */ if (r->headers_out.charset.len == 0) { lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module); source_charset = lcf->source_charset; if (source_charset >= NGX_HTTP_CHARSET_VAR) { vv = ngx_http_get_indexed_variable(r, source_charset - NGX_HTTP_CHARSET_VAR); if (vv == NULL || vv->not_found) { return NGX_ERROR; } s.len = vv->len; s.data = vv->data; source_charset = ngx_http_charset_get_charset(charsets, n, &s); } if (charset != NGX_HTTP_NO_CHARSET) { return ngx_http_charset_set_charset(r, mcf->charsets.elts, charset, source_charset); } if (source_charset == NGX_CONF_UNSET) { return ngx_http_next_header_filter(r); } from = &charsets[source_charset].name; to = &r->main->headers_out.charset; goto no_charset_map; } source_charset = ngx_http_charset_get_charset(charsets, n, &r->headers_out.charset); if (charset == NGX_HTTP_NO_CHARSET || source_charset == NGX_HTTP_NO_CHARSET) { if (charset != source_charset || ngx_strcasecmp(r->main->headers_out.charset.data, r->headers_out.charset.data) != 0) { from = &r->headers_out.charset; to = (charset == NGX_HTTP_NO_CHARSET) ? &r->main->headers_out.charset: &charsets[charset].name; goto no_charset_map; } return ngx_http_next_header_filter(r); } if (source_charset != charset && (charsets[source_charset].tables == NULL || charsets[source_charset].tables[charset] == NULL)) { from = &charsets[source_charset].name; to = &charsets[charset].name; goto no_charset_map; } r->headers_out.content_type.len = r->headers_out.content_type_len; return ngx_http_charset_set_charset(r, mcf->charsets.elts, charset, source_charset); no_charset_map: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no \"charset_map\" between the charsets \"%V\" and \"%V\"", from, to); return ngx_http_next_header_filter(r); }
static ngx_int_t ngx_http_redis_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis_ctx_t *ctx; ngx_http_redis_loc_conf_t *rlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 if (ngx_http_upstream_create(r) != NGX_OK) { #else rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { #endif return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 u = r->upstream; #endif #if defined nginx_version && nginx_version >= 8037 ngx_str_set(&u->schema, "redis://"); #else u->schema.len = sizeof("redis://") - 1; u->schema.data = (u_char *) "redis://"; #endif #if defined nginx_version && nginx_version >= 8011 u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #else u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #endif #if defined nginx_version && nginx_version >= 8011 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); #else u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #endif u->conf = &rlcf->upstream; u->create_request = ngx_http_redis_create_request; u->reinit_request = ngx_http_redis_reinit_request; u->process_header = ngx_http_redis_process_header; u->abort_request = ngx_http_redis_abort_request; u->finalize_request = ngx_http_redis_finalize_request; #if defined nginx_version && nginx_version < 8011 r->upstream = u; #endif ctx = ngx_palloc(r->pool, sizeof(ngx_http_redis_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_REDIS_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_redis_module); u->input_filter_init = ngx_http_redis_filter_init; u->input_filter = ngx_http_redis_filter; u->input_filter_ctx = ctx; #if defined nginx_version && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; } static ngx_int_t ngx_http_redis_create_request(ngx_http_request_t *r) { size_t len; uintptr_t escape; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_redis_ctx_t *ctx; ngx_http_variable_value_t *vv[2]; ngx_http_redis_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); vv[0] = ngx_http_get_indexed_variable(r, ngx_http_redis_db_index); /* * If user do not select redis database in nginx.conf by redis_db * variable, just add size of "select 0" to request. This is add * some overhead in talk with redis, but this way simplify parsing * the redis answer in ngx_http_redis_process_header(). */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); len = sizeof("select 0") - 1; } else { len = sizeof("select ") - 1 + vv[0]->len; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %s redis database", vv[0]->data); } len += sizeof(CRLF) - 1; vv[1] = ngx_http_get_indexed_variable(r, rlcf->index); /* If nginx.conf have no redis_key return error. */ if (vv[1] == NULL || vv[1]->not_found || vv[1]->len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the \"$redis_key\" variable is not set"); return NGX_ERROR; } /* Count have space required escape symbols. */ escape = 2 * ngx_escape_uri(NULL, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); len += sizeof("get ") - 1 + vv[1]->len + escape + sizeof(CRLF) - 1; /* Create temporary buffer for request with size len. */ b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; /* Add "select " for request. */ *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e'; *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' '; /* Get context redis_db from configuration file. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* * Add "0" as redis number db to request if redis_db undefined, * othervise add real number from context. */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); *b->last++ = '0'; } else { b->last = ngx_copy(b->last, vv[0]->data, vv[0]->len); ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %V redis database", &ctx->key); } /* Add "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* Add "get" command with space. */ *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' '; /* Get context redis_key from nginx.conf. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* * If no escape symbols then copy data as is, othervise use * escape-copy function. */ if (escape == 0) { b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len); } else { b->last = (u_char *) ngx_escape_uri(b->last, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); } ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http redis request: \"%V\"", &ctx->key); /* Add one more "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* * Summary, the request looks like this: * "select $redis_db\r\nget $redis_key\r\n", where * $redis_db and $redis_key are variable's values. */ return NGX_OK; }
static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) { ngx_table_elt_t *h; ngx_http_gzip_ctx_t *ctx; ngx_http_gzip_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); if (!conf->enable || (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_FORBIDDEN && r->headers_out.status != NGX_HTTP_NOT_FOUND) || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || (r->headers_out.content_length_n != -1 && r->headers_out.content_length_n < conf->min_length) || ngx_http_test_content_type(r, &conf->types) == NULL || r->header_only) { return ngx_http_next_header_filter(r); } r->gzip_vary = 1; #if (NGX_HTTP_DEGRADATION) { ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->gzip_disable_degradation && ngx_http_degraded(r)) { return ngx_http_next_header_filter(r); } } #endif if (!r->gzip_tested) { if (ngx_http_gzip_ok(r) != NGX_OK) { return ngx_http_next_header_filter(r); } } else if (!r->gzip_ok) { return ngx_http_next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_gzip_filter_module); ctx->request = r; ctx->buffering = (conf->postpone_gzipping != 0); ngx_http_gzip_filter_memory(r, ctx); h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NGX_ERROR; } h->hash = 1; ngx_str_set(&h->key, "Content-Encoding"); ngx_str_set(&h->value, "gzip"); r->headers_out.content_encoding = h; r->main_filter_need_in_memory = 1; ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); ngx_http_weak_etag(r); return ngx_http_next_header_filter(r); }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; lua_State *co; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx, ctx = %p, size: %d", ctx, (int) sizeof(*ctx)); ctx->entry_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(co, LUA_GLOBALSINDEX); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(co, &ngx_http_lua_request_key); lua_pushlightuserdata(co, r); lua_rawset(co, LUA_GLOBALSINDEX); /* }}} */ ctx->entry_co = co; ctx->cur_co = co; ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->entry_ref = co_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_CONTENT; return ngx_http_lua_run_thread(L, r, ctx, 0); }
ngx_int_t ngx_http_srcache_access_handler(ngx_http_request_t *r) { ngx_str_t skip; ngx_int_t rc; ngx_http_srcache_loc_conf_t *conf; ngx_http_srcache_main_conf_t *smcf; ngx_http_srcache_ctx_t *ctx; ngx_chain_t *cl; size_t len; unsigned no_store; /* access phase handlers are skipped in subrequests, * so the current request must be a main request */ conf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (conf->fetch == NULL && conf->store == NULL) { dd("bypass: %.*s", (int) r->uri.len, r->uri.data); return NGX_DECLINED; } dd("store defined? %p", conf->store); dd("req method: %lu", (unsigned long) r->method); dd("cache methods: %lu", (unsigned long) conf->cache_methods); if (!(r->method & conf->cache_methods)) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch and srcache_store skipped due to request " "method %V", &r->method_name); return NGX_DECLINED; } if (conf->req_cache_control && ngx_http_srcache_request_no_cache(r, &no_store) == NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch skipped due to request headers " "\"Cache-Control: no-cache\" or \"Pragma: no-cache\""); if (!no_store) { /* register a ctx to give a chance to srcache_store to run */ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to request header " "\"Cache-Control: no-store\""); } return NGX_DECLINED; } if (conf->fetch_skip != NULL && ngx_http_complex_value(r, conf->fetch_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_fetch skipped due to the true value fed into " "srcache_fetch_skip: \"%V\"", &skip); /* register a ctx to give a chance to srcache_store to run */ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); if (ctx != NULL) { /* if (ctx->fetch_error) { return NGX_DECLINED; } */ if (ctx->waiting_subrequest) { dd("waiting subrequest"); return NGX_AGAIN; } if (ctx->waiting_request_body) { return NGX_AGAIN; } if (ctx->request_body_done == 1) { ctx->request_body_done = 0; goto do_fetch_subrequest; } if (ctx->request_done) { dd("request done"); if (ngx_http_post_request(r, NULL) != NGX_OK) { return NGX_ERROR; } if (!ctx->from_cache) { return NGX_DECLINED; } dd("sending header"); if (ctx->body_from_cache) { len = 0; for (cl = ctx->body_from_cache; cl->next; cl = cl->next) { len += ngx_buf_size(cl->buf); } len += ngx_buf_size(cl->buf); cl->buf->last_buf = 1; r->headers_out.content_length_n = len; rc = ngx_http_srcache_fetch_header_filter(r); dd("srcache fetch header returned %d", (int) rc); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } #if 1 if (r->header_only) { return NGX_HTTP_OK; } #endif if (!r->filter_finalize) { rc = ngx_http_srcache_next_body_filter(r, ctx->body_from_cache); if (rc == NGX_ERROR) { r->connection->error = 1; return NGX_ERROR; } if (rc > NGX_OK) { return rc; } } dd("sent body from cache: %d", (int) rc); dd("finalize from here..."); ngx_http_finalize_request(r, rc); /* dd("r->main->count (post): %d", (int) r->main->count); */ return NGX_DONE; } return NGX_DECLINED; } } else { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); } smcf = ngx_http_get_module_main_conf(r, ngx_http_srcache_filter_module); if (!smcf->postponed_to_access_phase_end) { ngx_http_core_main_conf_t *cmcf; ngx_http_phase_handler_t tmp; ngx_http_phase_handler_t *ph; ngx_http_phase_handler_t *cur_ph; ngx_http_phase_handler_t *last_ph; smcf->postponed_to_access_phase_end = 1; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; cur_ph = &ph[r->phase_handler]; /* we should skip the post_access phase handler here too */ last_ph = &ph[cur_ph->next - 2]; if (cur_ph < last_ph) { dd("swaping the contents of cur_ph and last_ph..."); tmp = *cur_ph; memmove(cur_ph, cur_ph + 1, (last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t)); *last_ph = tmp; r->phase_handler--; /* redo the current ph */ return NGX_DECLINED; } } if (conf->fetch == NULL) { dd("fetch is not defined"); return NGX_DECLINED; } dd("running phase handler..."); if (!r->request_body) { dd("reading request body: ctx = %p", ctx); rc = ngx_http_read_client_request_body(r, ngx_http_srcache_post_read_body); if (rc == NGX_ERROR || rc > NGX_OK) { #if (nginx_version < 1002006) \ || (nginx_version >= 1003000 && nginx_version < 1003009) r->main->count--; #endif return rc; } if (rc == NGX_AGAIN) { ctx->waiting_request_body = 1; return NGX_AGAIN; } /* rc == NGX_OK */ } do_fetch_subrequest: /* issue a subrequest to fetch cached stuff (if any) */ rc = ngx_http_srcache_fetch_subrequest(r, conf, ctx); if (rc != NGX_OK) { return rc; } ctx->waiting_subrequest = 1; dd("quit"); return NGX_AGAIN; }
static ngx_int_t ngx_http_req_status_handler(ngx_http_request_t *r) { size_t len; uint32_t hash; ngx_str_t key; ngx_uint_t i; ngx_time_t *tp; ngx_shm_zone_t **pzone; ngx_pool_cleanup_t *cln; ngx_http_req_status_ctx_t *r_ctx; ngx_http_req_status_zone_t *ctx; ngx_http_req_status_node_t *ssn; ngx_http_req_status_loc_conf_t *rlcf; ngx_http_req_status_zone_node_t *pzn; r_ctx = ngx_http_get_module_ctx(r, ngx_http_req_status_module); rlcf = ngx_http_get_module_loc_conf(r, ngx_http_req_status_module); do { pzone = rlcf->req_zones.elts; for (i = 0; i < rlcf->req_zones.nelts; i++) { ctx = pzone[i]->data; if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { continue; } if (key.len == 0) { continue; } if (key.len > 65535) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "req-status, the value of the \"%V\" variable " "is more than 65535 bytes: \"%v\"", &ctx->key.value, &key); continue; } if (r_ctx == NULL) { r_ctx = ngx_palloc(r->pool, sizeof(ngx_http_req_status_ctx_t)); if (r_ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_array_init(&r_ctx->req_zones, r->pool, 2, sizeof(ngx_http_req_status_zone_node_t)) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_req_status_cleanup; cln->data = r_ctx; ngx_http_set_ctx(r, r_ctx, ngx_http_req_status_module); } hash = ngx_crc32_short(key.data, key.len); ngx_shmtx_lock(&ctx->shpool->mutex); ssn = ngx_http_req_status_lookup(ctx, hash, &key); if (ssn == NULL) { len = sizeof(ngx_http_req_status_node_t) + key.len + 1; ssn = ngx_slab_alloc_locked(ctx->shpool, len); if (ssn == NULL) { ngx_http_req_status_expire(ctx); ssn = ngx_slab_alloc_locked(ctx->shpool, len); if (ssn == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "req-status, slab alloc fail, zone = \"%V\", " "key = \"%V\", size = %uz", &ctx->shm_zone->shm.name, &key, len); ngx_shmtx_unlock(&ctx->shpool->mutex); continue; } } ssn->node.key = hash; ssn->len = key.len; ssn->count = 1; ngx_memzero(&ssn->data, sizeof(ssn->data)); ngx_memcpy(ssn->key, key.data, key.len); ssn->key[key.len] = '\0'; ssn->last_traffic_update = 0; ngx_rbtree_insert(&ctx->sh->rbtree, &ssn->node); } tp = ngx_timeofday(); ssn->data.requests ++; ssn->active ++; if (ssn->active > ssn->data.max_active) { ssn->data.max_active = ssn->active; } ngx_queue_insert_head(&ctx->sh->queue, &ssn->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); pzn = ngx_array_push(&r_ctx->req_zones); if (pzn == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } pzn->node = ssn; pzn->zone = ctx; } rlcf = rlcf->parent; } while (rlcf); return NGX_DECLINED; }
static ngx_int_t ngx_http_tfs_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_tfs_t *t; ngx_http_tfs_loc_conf_t *tlcf; ngx_http_tfs_srv_conf_t *tscf; ngx_http_tfs_main_conf_t *tmcf; tlcf = ngx_http_get_module_loc_conf(r, ngx_http_tfs_module); tscf = ngx_http_get_module_srv_conf(r, ngx_http_tfs_module); tmcf = ngx_http_get_module_main_conf(r, ngx_http_tfs_module); t = ngx_pcalloc(r->pool, sizeof(ngx_http_tfs_t)); if (t == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "alloc ngx_http_tfs_t failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } t->pool = r->pool; t->data = r; t->log = r->connection->log; t->loc_conf = tlcf; t->srv_conf = tscf; t->main_conf = tmcf; t->output.tag = (ngx_buf_tag_t) &ngx_http_tfs_module; if (tmcf->local_block_cache_ctx != NULL) { t->block_cache_ctx.use_cache |= NGX_HTTP_TFS_LOCAL_BLOCK_CACHE; t->block_cache_ctx.local_ctx = tmcf->local_block_cache_ctx; } if (tmcf->enable_remote_block_cache == NGX_HTTP_TFS_YES) { t->block_cache_ctx.use_cache |= NGX_HTTP_TFS_REMOTE_BLOCK_CACHE; } t->block_cache_ctx.remote_ctx.data = t; t->block_cache_ctx.remote_ctx.tair_instance = &tmcf->remote_block_cache_instance; t->block_cache_ctx.curr_lookup_cache = NGX_HTTP_TFS_LOCAL_BLOCK_CACHE; rc = ngx_http_restful_parse(r, &t->r_ctx); if (rc != NGX_OK) { return rc; } t->header_only = r->header_only; if (!t->loc_conf->upstream->enable_rcs && t->r_ctx.version == 2) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "custom file requires tfs_enable_rcs on," " and make sure you have MetaServer and RootServer!"); return NGX_HTTP_BAD_REQUEST; } switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_CREATE_DIR: case NGX_HTTP_TFS_ACTION_CREATE_FILE: case NGX_HTTP_TFS_ACTION_REMOVE_DIR: case NGX_HTTP_TFS_ACTION_REMOVE_FILE: case NGX_HTTP_TFS_ACTION_MOVE_DIR: case NGX_HTTP_TFS_ACTION_MOVE_FILE: case NGX_HTTP_TFS_ACTION_LS_DIR: case NGX_HTTP_TFS_ACTION_LS_FILE: case NGX_HTTP_TFS_ACTION_STAT_FILE: case NGX_HTTP_TFS_ACTION_KEEPALIVE: case NGX_HTTP_TFS_ACTION_READ_FILE: case NGX_HTTP_TFS_ACTION_GET_APPID: rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } r->headers_out.content_length_n = -1; ngx_http_set_ctx(r, t, ngx_http_tfs_module); r->main->count++; ngx_http_tfs_read_body_handler(r); break; case NGX_HTTP_TFS_ACTION_WRITE_FILE: r->headers_out.content_length_n = -1; ngx_http_set_ctx(r, t, ngx_http_tfs_module); rc = ngx_http_read_client_request_body(r, ngx_http_tfs_read_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } break; } return NGX_DONE; }