ngx_int_t ngx_postgres_process_response(ngx_http_request_t *r, PGresult *res) { ngx_postgres_loc_conf_t *pglcf; ngx_postgres_ctx_t *pgctx; ngx_postgres_rewrite_conf_t *pgrcf; ngx_postgres_variable_t *pgvar; ngx_str_t *store; char *affected; size_t affected_len; ngx_uint_t i; ngx_int_t rc; dd("entering"); pglcf = ngx_http_get_module_loc_conf(r, ngx_postgres_module); pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); /* set $postgres_columns */ pgctx->var_cols = PQnfields(res); /* set $postgres_rows */ pgctx->var_rows = PQntuples(res); /* set $postgres_affected */ if (ngx_strncmp(PQcmdStatus(res), "SELECT", sizeof("SELECT") - 1)) { affected = PQcmdTuples(res); affected_len = ngx_strlen(affected); if (affected_len) { pgctx->var_affected = ngx_atoi((u_char *) affected, affected_len); } } if (pglcf->rewrites) { /* process rewrites */ pgrcf = pglcf->rewrites->elts; for (i = 0; i < pglcf->rewrites->nelts; i++) { rc = pgrcf[i].handler(r, &pgrcf[i]); if (rc != NGX_DECLINED) { if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { dd("returning NGX_DONE, status %d", (int) rc); pgctx->status = rc; return NGX_DONE; } pgctx->status = rc; break; } } } if (pglcf->variables) { /* set custom variables */ pgvar = pglcf->variables->elts; store = pgctx->variables->elts; for (i = 0; i < pglcf->variables->nelts; i++) { store[i] = ngx_postgres_variable_set_custom(r, res, &pgvar[i]); if ((store[i].len == 0) && (pgvar[i].value.required)) { dd("returning NGX_DONE, status NGX_HTTP_INTERNAL_SERVER_ERROR"); pgctx->status = NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_DONE; } } } if (pglcf->output_handler) { /* generate output */ dd("returning"); return pglcf->output_handler(r, res); } dd("returning NGX_DONE"); return NGX_DONE; }
static int ngx_http_lua_ngx_header_set(lua_State *L) { ngx_http_request_t *r; u_char *p; ngx_str_t key; ngx_str_t value; ngx_uint_t i; size_t len; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; ngx_uint_t n; ngx_http_lua_loc_conf_t *llcf; 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"); } ngx_http_lua_check_fake_request2(L, r, ctx); if (ctx->headers_sent) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to " "set ngx.header.HEADER after sending out " "response headers"); return 0; } /* we skip the first argument that is the table */ p = (u_char *) luaL_checklstring(L, 2, &len); dd("key: %.*s, len %d", (int) len, p, (int) len); key.data = ngx_palloc(r->pool, len + 1); if (key.data == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(key.data, p, len); key.data[len] = '\0'; key.len = len; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->transform_underscores_in_resp_headers) { /* replace "_" with "-" */ p = key.data; for (i = 0; i < len; i++) { if (p[i] == '_') { p[i] = '-'; } } } if (!ctx->headers_set) { rc = ngx_http_set_content_type(r); if (rc != NGX_OK) { return luaL_error(L, "failed to set default content type: %d", (int) rc); } ctx->headers_set = 1; } if (lua_type(L, 3) == LUA_TNIL) { value.data = NULL; value.len = 0; } else if (lua_type(L, 3) == LUA_TTABLE) { n = luaL_getn(L, 3); if (n == 0) { value.data = NULL; value.len = 0; } else { for (i = 1; i <= n; i++) { dd("header value table index %d", (int) i); lua_rawgeti(L, 3, i); p = (u_char *) luaL_checklstring(L, -1, &len); value.data = ngx_palloc(r->pool, len); if (value.data == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(value.data, p, len); value.len = len; rc = ngx_http_lua_set_output_header(r, key, value, i == 1 /* override */); if (rc == NGX_ERROR) { return luaL_error(L, "failed to set header %s (error: %d)", key.data, (int) rc); } } return 0; } } else { p = (u_char *) luaL_checklstring(L, 3, &len); value.data = ngx_palloc(r->pool, len); if (value.data == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(value.data, p, len); value.len = len; } dd("key: %.*s, value: %.*s", (int) key.len, key.data, (int) value.len, value.data); rc = ngx_http_lua_set_output_header(r, key, value, 1 /* override */); if (rc == NGX_ERROR) { return luaL_error(L, "failed to set header %s (error: %d)", key.data, (int) rc); } return 0; }
static ngx_int_t ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_str_t *ct; ngx_chain_t out; ngx_http_image_filter_ctx_t *ctx; ngx_http_image_filter_conf_t *conf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image filter"); if (in == NULL) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } switch (ctx->phase) { case NGX_HTTP_IMAGE_START: ctx->type = ngx_http_image_test(r, in); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (ctx->type == NGX_HTTP_IMAGE_NONE) { if (conf->filter == NGX_HTTP_IMAGE_SIZE) { out.buf = ngx_http_image_json(r, NULL); if (out.buf) { out.next = NULL; ctx->phase = NGX_HTTP_IMAGE_DONE; return ngx_http_image_send(r, ctx, &out); } } return ngx_http_filter_finalize_request(r, &ngx_http_image_filter_module, NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); } /* override content type */ ct = &ngx_http_image_types[ctx->type - 1]; r->headers_out.content_type_len = ct->len; r->headers_out.content_type = *ct; r->headers_out.content_type_lowcase = NULL; if (conf->filter == NGX_HTTP_IMAGE_TEST) { ctx->phase = NGX_HTTP_IMAGE_PASS; return ngx_http_image_send(r, ctx, in); } ctx->phase = NGX_HTTP_IMAGE_READ; /* fall through */ case NGX_HTTP_IMAGE_READ: rc = ngx_http_image_read(r, in); if (rc == NGX_AGAIN) { return NGX_OK; } if (rc == NGX_ERROR) { return ngx_http_filter_finalize_request(r, &ngx_http_image_filter_module, NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); } /* fall through */ case NGX_HTTP_IMAGE_PROCESS: out.buf = ngx_http_image_process(r); if (out.buf == NULL) { return ngx_http_filter_finalize_request(r, &ngx_http_image_filter_module, NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); } out.next = NULL; ctx->phase = NGX_HTTP_IMAGE_PASS; return ngx_http_image_send(r, ctx, &out); case NGX_HTTP_IMAGE_PASS: return ngx_http_next_body_filter(r, in); default: /* NGX_HTTP_IMAGE_DONE */ rc = ngx_http_next_body_filter(r, NULL); /* NGX_ERROR resets any pending data */ return (rc == NGX_OK) ? NGX_ERROR : rc; } }
ngx_int_t ngx_postgres_upstream_init_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *uscf) { ngx_postgres_upstream_peer_data_t *pgdt; ngx_postgres_upstream_srv_conf_t *pgscf; ngx_postgres_loc_conf_t *pglcf; ngx_postgres_ctx_t *pgctx; ngx_http_core_loc_conf_t *clcf; ngx_http_upstream_t *u; ngx_postgres_mixed_t *query; ngx_str_t sql; ngx_uint_t i; dd("entering"); pgdt = ngx_pcalloc(r->pool, sizeof(ngx_postgres_upstream_peer_data_t)); if (pgdt == NULL) { goto failed; } u = r->upstream; pgdt->upstream = u; pgdt->request = r; pgscf = ngx_http_conf_upstream_srv_conf(uscf, ngx_postgres_module); pglcf = ngx_http_get_module_loc_conf(r, ngx_postgres_module); pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); pgdt->srv_conf = pgscf; pgdt->loc_conf = pglcf; u->peer.data = pgdt; u->peer.get = ngx_postgres_upstream_get_peer; u->peer.free = ngx_postgres_upstream_free_peer; if (pglcf->query.methods_set & r->method) { /* method-specific query */ dd("using method-specific query"); query = pglcf->query.methods->elts; for (i = 0; i < pglcf->query.methods->nelts; i++) { if (query[i].key & r->method) { query = &query[i]; break; } } if (i == pglcf->query.methods->nelts) { goto failed; } } else { /* default query */ dd("using default query"); query = pglcf->query.def; } if (query->cv) { /* complex value */ dd("using complex value"); if (ngx_http_complex_value(r, query->cv, &sql) != NGX_OK) { goto failed; } if (sql.len == 0) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "postgres: empty \"postgres_query\" (was: \"%V\")" " in location \"%V\"", &query->cv->value, &clcf->name); goto failed; } pgdt->query = sql; } else { /* simple value */ dd("using simple value"); pgdt->query = query->sv; } /* set $postgres_query */ pgctx->var_query = pgdt->query; dd("returning NGX_OK"); return NGX_OK; failed: #if defined(nginx_version) && (nginx_version >= 8017) dd("returning NGX_ERROR"); return NGX_ERROR; #else r->upstream->peer.data = NULL; dd("returning NGX_OK (NGX_ERROR)"); return NGX_OK; #endif }
static ngx_int_t ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; uint8_t old_context; ngx_http_cleanup_t *cln; ngx_http_lua_main_conf_t *lmcf; lua_State *L; ngx_chain_t *out; ngx_buf_tag_t tag; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua body filter for user lua code, uri \"%V\"", &r->uri); if (in == NULL) { return ngx_http_next_body_filter(r, in); } llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->body_filter_handler == NULL) { dd("no body filter handler found"); return ngx_http_next_body_filter(r, in); } 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); } 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; } old_context = ctx->context; ctx->context = NGX_HTTP_LUA_CONTEXT_BODY_FILTER; dd("calling body filter handler"); rc = llcf->body_filter_handler(r, in); dd("calling body filter handler returned %d", (int) rc); ctx->context = old_context; if (rc != NGX_OK) { return NGX_ERROR; } lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); L = lmcf->lua; lua_pushlightuserdata(L, &ngx_http_lua_body_filter_chain_key); lua_rawget(L, LUA_GLOBALSINDEX); out = lua_touserdata(L, -1); lua_pop(L, 1); if (in == out) { return ngx_http_next_body_filter(r, in); } /* in != out */ rc = ngx_http_next_body_filter(r, out); if (rc == NGX_ERROR) { return NGX_ERROR; } tag = (ngx_buf_tag_t) &ngx_http_lua_module; #if nginx_version >= 1001004 ngx_chain_update_chains(r->pool, #else ngx_chain_update_chains( #endif &ctx->free_bufs, &ctx->busy_bufs, &out, tag); return rc; }
/** * @brief Handler function for POST operation. * * * @param r http request as defined by nxinx framework */ void rp_bazaar_post_read(ngx_http_request_t *r) { int len = 0, buffers = 0; char *msg_pos; ngx_chain_t *chain_link; rp_bazaar_ctx_t *ctx; fprintf(stderr, "%s\n", __FUNCTION__); ctx = ngx_http_get_module_ctx(r, ngx_http_rp_module); if(ctx == NULL) { fprintf(stderr, "%s: Cannot get request context\n", __FUNCTION__); goto done; } ctx->in_status = 0; ctx->in_buffer_len = 0; if((r->request_body == NULL) || (r->request_body->bufs == NULL)) { fprintf(stderr, "%s: body is empty\n", __FUNCTION__); ctx->in_status = -1; goto done; } if(r->request_body->temp_file) { fprintf(stderr, "%s: data in temp file (not supported - check client_body_buffer_size parameter\n", __FUNCTION__); ctx->in_status = -1; goto done; } /* check the size of the body */ for(chain_link = r->request_body->bufs; chain_link != NULL; chain_link = chain_link->next) { len += chain_link->buf->last - chain_link->buf->pos; buffers++; if(chain_link->buf->in_file) { ctx->in_status = -1; goto done; } } /* allocate memory for the buffer of the body */ ctx->in_buffer = (char *)ngx_palloc(r->pool, (len + 1)*sizeof(char)); ctx->in_buffer_len = (len+1); if(ctx->in_buffer == NULL) { fprintf(stderr, "%s: can not allocate memory\n", __FUNCTION__); ctx->in_status = -1; goto done; } /* collect body into one buffer */ msg_pos = ctx->in_buffer; for(chain_link = r->request_body->bufs; chain_link != NULL; chain_link = chain_link->next) { ngx_buf_t *buf = chain_link->buf; msg_pos = (char *)ngx_copy(msg_pos, (char *)buf->pos, buf->last - buf->pos); } ctx->in_buffer[len] = '\0'; char *host = (char *)r->headers_in.server.data; action_e act = eInstall; int ret = rp_bazaar_interpret(r, &act); if(ret != 0) { /* Redirect to Bazaar installation error */ fprintf(stderr, "Bazaar %s failed (ret: %d)\n", bazaar_acts[act].name, ret); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_install.html", host); } else { /* Success - redirect back to Bazaar through Red Pitaya */ snprintf(ctx->redirect, c_redirect_len, "http://%s/bazaar", host); } done: if (ctx->finalize_on_post_handler) { ngx_http_finalize_request(r, rp_module_redirect(r, ctx->redirect)); } else { ngx_http_finalize_request(r, NGX_DONE); } }
static mrb_value ngx_mrb_rputs(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(argv); ns.len = RSTRING_LEN(argv); 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_redis_create_request(ngx_http_request_t *r) { ngx_int_t rc = NGX_ERROR; ngx_http_redis_loc_conf_t *rlcf; ngx_http_redis_ctx_t *ctx; ngx_http_variable_value_t *vv; ngx_http_upstream_t *u = r->upstream; ngx_chain_t *cl = NULL; u_char *p, *last; ngx_str_t command; ngx_int_t command_hash = 0; ngx_http_redis_command_process_t *proc; if (r->args.len == 0) { return NGX_ERROR; } ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); vv = ngx_http_get_indexed_variable(r, rlcf->index); if (vv == NULL || vv->not_found || vv->len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the \"$redis_key\" variable is not set"); return NGX_ERROR; } p = r->args.data; last = p + r->args.len; for (; p != last; p++) { if (*p == '&') { break; } } command.data = r->args.data; command.len = p - command.data; command_hash = ngx_hash_key_lc(command.data, command.len); proc = ngx_hash_find(&ctx->command_hash, command_hash, command.data, command.len); if (proc && proc->create_request_handler) { rc = proc->create_request_handler(r, p+1, last, vv, &cl); } /* switch (*p) { case 'g': case 'G': rc = ngx_http_redis_process_get(r, p, last, vv, &cl); break; case 'A': case 'a': rc = ngx_http_redis_process_append(r, p, last, vv, &cl); break; default: break; } */ if (rc != NGX_OK) { return rc; } u->request_bufs = cl; return NGX_OK; }
ngx_int_t ngx_http_lua_wev_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_lua_ctx_t *ctx; ngx_http_lua_main_conf_t *lmcf; lua_State *cc; ngx_str_t *body_str; ngx_http_headers_out_t *sr_headers; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_uint_t i, index; dd("wev handler %.*s %.*s a:%d, postponed:%p", (int) r->uri.len, r->uri.data, (int) ngx_cached_err_log_time.len, ngx_cached_err_log_time.data, r == r->connection->data, r->postponed); #if 0 ngx_http_lua_dump_postponed(r); #endif ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { goto error; } dd("ctx = %p", ctx); dd("request done: %d", (int) r->done); dd("cleanup done: %p", ctx->cleanup); if (ctx->cleanup == NULL) { /* already done */ dd("cleanup is null: %.*s", (int) r->uri.len, r->uri.data); if (ctx->entered_content_phase) { ngx_http_finalize_request(r, ngx_http_lua_flush_postponed_outputs(r)); } return NGX_OK; } dd("waiting: %d, done: %d", (int) ctx->waiting, ctx->done); if (ctx->waiting && ! ctx->done) { dd("%.*s waiting and not done", (int) r->uri.len, r->uri.data); #if 0 ngx_http_lua_dump_postponed(r); #endif if (r == r->connection->data && r->postponed) { if (r->postponed->request) { r->connection->data = r->postponed->request; #if defined(nginx_version) && nginx_version >= 8012 ngx_http_post_request(r->postponed->request, NULL); #else ngx_http_post_request(r->postponed->request); #endif } else { ngx_http_lua_flush_postponed_outputs(r); } } return NGX_DONE; } ctx->done = 0; dd("nsubreqs: %d", (int) ctx->nsubreqs); for (index = 0; index < ctx->nsubreqs; index++) { dd("summary: reqs %d, subquery %d, waiting %d, req %.*s", (int) ctx->nsubreqs, (int) index, (int) ctx->waiting, (int) r->uri.len, r->uri.data); cc = ctx->cc; /* {{{ construct ret value */ lua_newtable(cc); /* copy captured status */ lua_pushinteger(cc, ctx->sr_statuses[index]); lua_setfield(cc, -2, "status"); /* copy captured body */ body_str = &ctx->sr_bodies[index]; lua_pushlstring(cc, (char *) body_str->data, body_str->len); lua_setfield(cc, -2, "body"); if (body_str->data) { dd("free body buffer ASAP"); ngx_pfree(r->pool, body_str->data); } /* copy captured headers */ lua_newtable(cc); /* res.header */ sr_headers = ctx->sr_headers[index]; dd("saving subrequest response headers"); part = &sr_headers->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; } dd("checking sr header %.*s", (int) header[i].key.len, header[i].key.data); #if 1 if (header[i].hash == 0) { continue; } #endif header[i].hash = 0; dd("pushing sr header %.*s", (int) header[i].key.len, header[i].key.data); lua_pushlstring(cc, (char *) header[i].key.data, header[i].key.len); /* header key */ lua_pushvalue(cc, -1); /* stack: table key key */ /* check if header already exists */ lua_rawget(cc, -3); /* stack: table key value */ if (lua_isnil(cc, -1)) { lua_pop(cc, 1); /* stack: table key */ lua_pushlstring(cc, (char *) header[i].value.data, header[i].value.len); /* stack: table key value */ lua_rawset(cc, -3); /* stack: table */ } else { if (! lua_istable(cc, -1)) { /* already inserted one value */ lua_createtable(cc, 4, 0); /* stack: table key value table */ lua_insert(cc, -2); /* stack: table key table value */ lua_rawseti(cc, -2, 1); /* stack: table key table */ lua_pushlstring(cc, (char *) header[i].value.data, header[i].value.len); /* stack: table key table value */ lua_rawseti(cc, -2, lua_objlen(cc, -2) + 1); /* stack: table key table */ lua_rawset(cc, -3); /* stack: table */ } else { lua_pushlstring(cc, (char *) header[i].value.data, header[i].value.len); /* stack: table key table value */ lua_rawseti(cc, -2, lua_objlen(cc, -2) + 1); /* stack: table key table */ lua_pop(cc, 2); /* stack: table */ } } } if (sr_headers->content_type.len) { lua_pushliteral(cc, "Content-Type"); /* header key */ lua_pushlstring(cc, (char *) sr_headers->content_type.data, sr_headers->content_type.len); /* head key value */ lua_rawset(cc, -3); /* head */ } if (sr_headers->content_length == NULL && sr_headers->content_length_n >= 0) { lua_pushliteral(cc, "Content-Length"); /* header key */ lua_pushnumber(cc, sr_headers->content_length_n); /* head key value */ lua_rawset(cc, -3); /* head */ } /* to work-around an issue in ngx_http_static_module * (github issue #41) */ if (sr_headers->location && sr_headers->location->value.len) { lua_pushliteral(cc, "Location"); /* header key */ lua_pushlstring(cc, (char *) sr_headers->location->value.data, sr_headers->location->value.len); /* head key value */ lua_rawset(cc, -3); /* head */ } lua_setfield(cc, -2, "header"); /* }}} */ } dd("free sr_statues/headers/bodies memory ASAP"); #if 1 ngx_pfree(r->pool, ctx->sr_statuses); ctx->sr_statuses = NULL; ctx->sr_headers = NULL; ctx->sr_bodies = NULL; #endif lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); dd("about to run thread for %.*s...", (int) r->uri.len, r->uri.data); rc = ngx_http_lua_run_thread(lmcf->lua, r, ctx, ctx->nsubreqs); dd("already run thread for %.*s: %d", (int) r->uri.len, r->uri.data, (int) rc); if (rc == NGX_AGAIN) { return NGX_DONE; } if (rc == NGX_DONE) { if (ctx->entered_content_phase) { ngx_http_finalize_request(r, rc); } return NGX_OK; } dd("entered content phase: %d", (int) ctx->entered_content_phase); if (ctx->entered_content_phase) { ngx_http_finalize_request(r, rc); return NGX_DONE; } if (rc == NGX_OK) { return NGX_DECLINED; } return rc; error: if (ctx->entered_content_phase) { ngx_http_finalize_request(r, ctx->headers_sent ? NGX_ERROR: NGX_HTTP_INTERNAL_SERVER_ERROR); } return NGX_ERROR; }
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; 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", ctx); ctx->cc_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 */ 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); /* }}} */ ctx->cc = cc; ctx->cc_ref = cc_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; } /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
static ngx_int_t ngx_http_reqstat_log_handler(ngx_http_request_t *r) { u_char *p; ngx_int_t *indicator, iv; ngx_uint_t i, j, k, status, utries; ngx_time_t *tp; ngx_msec_int_t ms, total_ms; ngx_shm_zone_t **shm_zone, *z; ngx_http_reqstat_ctx_t *ctx; ngx_http_reqstat_conf_t *slcf; ngx_http_reqstat_rbnode_t *fnode, **fnode_store; ngx_http_upstream_state_t *state; ngx_http_variable_value_t *v; ngx_http_reqstat_store_t *store; slcf = ngx_http_get_module_loc_conf(r, ngx_http_reqstat_module); if (slcf->monitor == NULL) { return NGX_OK; } store = ngx_http_get_module_ctx(r, ngx_http_reqstat_module); if (store == NULL) { store = ngx_http_reqstat_create_store(r, slcf); if (store == NULL) { return NGX_ERROR; } } if (store->bypass) { return NGX_OK; } shm_zone = slcf->monitor->elts; fnode_store = store->monitor_index.elts; for (i = 0; i < store->monitor_index.nelts; i++) { fnode = fnode_store[i]; if (r->connection->requests == 1) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_CONN_TOTAL, 1); } ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_REQ_TOTAL, 1); ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_BYTES_IN, r->connection->received - (store ? store->recv : 0)); if (r->err_status) { status = r->err_status; } else if (r->headers_out.status) { status = r->headers_out.status; } else if (r->http_version == NGX_HTTP_VERSION_9) { status = 9; } else { status = 0; } if (status >= 200 && status < 300) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_2XX, 1); switch (status) { case 200: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_200, 1); break; case 206: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_206, 1); break; default: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS, 1); break; } } else if (status >= 300 && status < 400) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_3XX, 1); switch (status) { case 302: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_302, 1); break; case 304: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_304, 1); break; default: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS, 1); break; } } else if (status >= 400 && status < 500) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_4XX, 1); switch (status) { case 403: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_403, 1); break; case 404: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_404, 1); break; case 416: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_416, 1); break; case 499: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_499, 1); break; default: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS, 1); break; } } else if (status >= 500 && status < 600) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_5XX, 1); switch (status) { case 500: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_500, 1); break; case 502: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_502, 1); break; case 503: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_503, 1); break; case 504: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_504, 1); break; case 508: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_508, 1); break; default: ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS, 1); break; } } else { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_STATUS, 1); ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS, 1); } /* response status of last upstream peer */ if (r->upstream_states != NULL && r->upstream_states->nelts > 0) { ngx_http_upstream_state_t *state = r->upstream_states->elts; status = state[r->upstream_states->nelts - 1].status; if (status >= 400 && status < 500) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_4XX, 1); } else if (status >= 500 && status < 600) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_5XX, 1); } } tp = ngx_timeofday(); ms = (ngx_msec_int_t) ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = ngx_max(ms, 0); ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_RT, ms); if (r->upstream_states != NULL && r->upstream_states->nelts > 0) { ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_REQ, 1); j = 0; total_ms = 0; utries = 0; state = r->upstream_states->elts; for ( ;; ) { utries++; ms = (ngx_msec_int_t) (state[j].response_sec * 1000 + state[j].response_msec); ms = ngx_max(ms, 0); total_ms += ms; if (++j == r->upstream_states->nelts) { break; } if (state[j].peer == NULL) { if (++j == r->upstream_states->nelts) { break; } } } ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_RT, total_ms); ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_TRIES, utries); } z = shm_zone[i]; ctx = z->data; if (ctx->user_defined) { indicator = ctx->user_defined->elts; for (j = 0; j < ctx->user_defined->nelts; j++) { v = ngx_http_get_indexed_variable(r, indicator[j]); if (v == NULL || v->not_found || !v->valid) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "variable is uninitialized"); continue; } for (k = 0, p = v->data + v->len - 1; p >= v->data; p--) { if (*p == '.') { k = v->data + v->len - 1 - p; continue; } if (*p < '0' || *p > '9') { break; } } p++; if (k) { iv = ngx_atofp(p, v->data + v->len - p, k); } else { iv = ngx_atoi(p, v->data + v->len - p); } if (iv == NGX_ERROR) { continue; } ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_EXTRA(j), iv); } } } return NGX_OK; }
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; 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", 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_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_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, i; 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; //The start of the unified protocol GET request const char *get_request_start = "*2\r\n$3\r\nGET\r\n$"; //Buffer to store the char version of the key - max size char key_len_buf[8]; //Bad code //TODO: use ngx_get_num_size( to remove the need for this const char* key_len_ptr = &key_len_buf[0]; int key_len; 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; } key_len = sprintf(key_len_buf,"%d",vv[1]->len); //Work out how long the request is going to be //14 = length of request_start len += 14 + key_len + sizeof(CRLF) - 1 + vv[1]->len + sizeof(CRLF) - 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "redis request length: %d", len); /* 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. */ for(i=0;i<14;i++){ *b->last++ = get_request_start[i]; } /* Add length */ while(key_len != 0){ *b->last++ = *key_len_ptr; key_len--; key_len_ptr ++; } /* Add one more "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* Get context redis_key from nginx.conf. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* Copy the key into the request buffer */ b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len); 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; }
/* initialize lua coroutine for caching new SSL session */ static ngx_int_t ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) { size_t len; u_char *err_msg; ngx_int_t rc; ngx_http_lua_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE; /* init nginx context in Lua VM */ ngx_http_lua_set_req(L, r); ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); /* {{{ make new env inheriting main thread's globals table */ lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ ngx_http_lua_get_globals_table(L); lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ /* protected call user code */ rc = lua_pcall(L, 0, 1, 1); lua_remove(L, 1); /* remove traceback function */ dd("rc == %d", (int) rc); if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { err_msg = (u_char *) "unknown reason"; len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to run session_store_by_lua*: %*s", len, err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ ngx_http_lua_finalize_request(r, rc); return NGX_ERROR; } lua_settop(L, 0); /* clear remaining elems on stack */ ngx_http_lua_finalize_request(r, rc); return rc; }
static ngx_int_t ngx_http_redis2_create_request(ngx_http_request_t *r) { ngx_buf_t *b; ngx_chain_t *cl; ngx_http_redis2_loc_conf_t *rlcf; ngx_str_t query; ngx_str_t query_count; ngx_int_t rc; ngx_http_redis2_ctx_t *ctx; ngx_int_t n; ctx = ngx_http_get_module_ctx(r, ngx_http_redis2_module); rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis2_module); if (rlcf->queries) { ctx->query_count = rlcf->queries->nelts; rc = ngx_http_redis2_build_query(r, rlcf->queries, &b); if (rc != NGX_OK) { return rc; } } else if (rlcf->literal_query.len == 0) { if (rlcf->complex_query == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no redis2 query specified or the query is empty"); return NGX_ERROR; } if (ngx_http_complex_value(r, rlcf->complex_query, &query) != NGX_OK) { return NGX_ERROR; } if (query.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the redis query is empty"); return NGX_ERROR; } if (rlcf->complex_query_count == NULL) { ctx->query_count = 1; } else { if (ngx_http_complex_value(r, rlcf->complex_query_count, &query_count) != NGX_OK) { return NGX_ERROR; } if (query_count.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the N argument to redis2_raw_queries is empty"); return NGX_ERROR; } n = ngx_atoi(query_count.data, query_count.len); if (n == NGX_ERROR || n == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the N argument to redis2_raw_queries is invalid"); return NGX_ERROR; } ctx->query_count = n; } b = ngx_create_temp_buf(r->pool, query.len); if (b == NULL) { return NGX_ERROR; } b->last = ngx_copy(b->pos, query.data, query.len); } else { ctx->query_count = 1; b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->pos = rlcf->literal_query.data; b->last = b->pos + rlcf->literal_query.len; b->memory = 1; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http redis2 request: \"%V\"", &rlcf->literal_query); return NGX_OK; }
static ngx_int_t ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { int rc; ngx_chain_t *cl; ngx_http_gunzip_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module); if (ctx == NULL || ctx->done) { return ngx_http_next_body_filter(r, in); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http gunzip filter"); if (!ctx->started) { if (ngx_http_gunzip_filter_inflate_start(r, ctx) != NGX_OK) { goto failed; } } if (in) { if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) { goto failed; } } if (ctx->nomem) { /* flush busy buffers */ if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { goto failed; } cl = NULL; ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl, (ngx_buf_tag_t) &ngx_http_gunzip_filter_module); ctx->nomem = 0; } for ( ;; ) { /* cycle while we can write to a client */ for ( ;; ) { /* cycle while there is data to feed zlib and ... */ rc = ngx_http_gunzip_filter_add_data(r, ctx); if (rc == NGX_DECLINED) { break; } if (rc == NGX_AGAIN) { continue; } /* ... there are buffers to write zlib output */ rc = ngx_http_gunzip_filter_get_buf(r, ctx); if (rc == NGX_DECLINED) { break; } if (rc == NGX_ERROR) { goto failed; } rc = ngx_http_gunzip_filter_inflate(r, ctx); if (rc == NGX_OK) { break; } if (rc == NGX_ERROR) { goto failed; } /* rc == NGX_AGAIN */ } if (ctx->out == NULL) { return ctx->busy ? NGX_AGAIN : NGX_OK; } rc = ngx_http_next_body_filter(r, ctx->out); if (rc == NGX_ERROR) { goto failed; } ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out, (ngx_buf_tag_t) &ngx_http_gunzip_filter_module); ctx->last_out = &ctx->out; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "gunzip out: %p", ctx->out); ctx->nomem = 0; if (ctx->done) { return rc; } } /* unreachable */ failed: ctx->done = 1; return NGX_ERROR; }
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) { rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0); if (rc == NGX_ERROR || rc == NGX_DONE) { return rc; } } } 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; } rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0); if (rc == NGX_ERROR || rc == NGX_DONE) { return rc; } ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); return ngx_http_send_special(r, NGX_HTTP_LAST); }
static int ngx_http_lua_ngx_redirect(lua_State *L) { ngx_http_lua_ctx_t *ctx; ngx_int_t rc; int n; u_char *p; u_char *uri; size_t len; ngx_http_request_t *r; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting one or two arguments"); } p = (u_char *) luaL_checklstring(L, 1, &len); if (n == 2) { rc = (ngx_int_t) luaL_checknumber(L, 2); if (rc != NGX_HTTP_MOVED_TEMPORARILY && rc != NGX_HTTP_MOVED_PERMANENTLY) { return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY and " "ngx.HTTP_MOVED_PERMANENTLY are allowed"); } } else { rc = NGX_HTTP_MOVED_TEMPORARILY; } lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); 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 request ctx found"); } if (ctx->headers_sent) { return luaL_error(L, "attempt to call ngx.redirect after sending out " "the headers"); } uri = ngx_palloc(r->pool, len); if (uri == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(uri, p, len); r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return luaL_error(L, "out of memory"); } r->headers_out.location->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('l', 'o'), 'c'), 'a'), 't'), 'i'), 'o'), 'n'); #if 0 dd("location hash: %lu == %lu", (unsigned long) r->headers_out.location->hash, (unsigned long) ngx_hash_key_lc((u_char *) "Location", sizeof("Location") - 1)); #endif r->headers_out.location->value.len = len; r->headers_out.location->value.data = uri; ngx_str_set(&r->headers_out.location->key, "Location"); r->headers_out.status = rc; ctx->exit_code = rc; ctx->exited = 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua redirect to \"%V\" with code %i", &r->headers_out.location->value, ctx->exit_code); return lua_yield(L, 0); }
/** * @brief Handler function for operation. * * Function parses the POST request, which is defined by JSON packet and * installs/removes the archive. * * @param[in] r HTTP request as defined by NGINX framework * @param[out] act Bazaar action * @retval 0 successful operation * @retval !=0 failure */ int rp_bazaar_interpret(ngx_http_request_t *r, action_e *act) { rp_bazaar_ctx_t *ctx; cJSON *req_body = NULL; cJSON *j_cmd = NULL; cJSON *j_url = NULL; cJSON *j_app = NULL; cJSON *j_md5 = NULL; cJSON *j_tok = NULL; char *urld = NULL; char *action = NULL; int ret = 0; fprintf(stderr, "%s\n", __FUNCTION__); *act = eUnknown; ctx = ngx_http_get_module_ctx(r, ngx_http_rp_module); if(ctx == NULL) { fprintf(stderr, "%s: Cannot get request context\n", __FUNCTION__); return -1; } /* check if this is a POST operation */ if(!(r->method & NGX_HTTP_POST)) { return rp_module_cmd_error(&ctx->json_root, "Expected POST method", NULL, r->pool); } /* check for payload buffers */ if((ctx->in_buffer_len == 0) || (ctx->in_buffer == NULL) || (ctx->in_status != 0)) { fprintf(stderr, "Body is empty, unknown error\n"); return -1; } /* parse incoming body to cJSON and search for 'params' */ fprintf(stderr, "Bazaar install/remove: Received body: %s\n", ctx->in_buffer); urld = url_decode(ctx->in_buffer); cJSON_Minify(urld); /* Get rid of "payload=" header */ char *urld_strip = memchr(urld, '{', 10); req_body = cJSON_Parse(urld_strip, r->pool); if (urld) free (urld); if(req_body == NULL) { fprintf(stderr, "Can not parse incoming body to JSON\n"); return -1; } /* "command" object */ j_cmd = cJSON_GetObjectItem(req_body, "command"); if(j_cmd == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'command' in req body\n"); return -1; } /* Install/Upgrade */ if ( !strncmp(j_cmd->valuestring, "install", sizeof("install")) ) { *act = eInstall; action = j_cmd->valuestring; } if ( !strncmp(j_cmd->valuestring, "upgrade", sizeof("upgrade")) ) { *act = eUpgrade; action = j_cmd->valuestring; } if ( (*act == eInstall) || (*act == eUpgrade) ) { /* "archive" object */ j_url = cJSON_GetObjectItem(req_body, "archive"); if(j_url == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'archive' in req body\n"); return -1; } /* "md5" object */ j_md5 = cJSON_GetObjectItem(req_body, "md5"); if(j_md5 == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'md5' in req body\n"); return -1; } } /* Uninstall */ if (!strncmp(j_cmd->valuestring, "uninstall", sizeof("uninstall"))) { *act = eRemove; action = "remove"; } /* Unknown action */ if (!action) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Unknown action: %s\n", j_cmd->valuestring); return -1; } /* "app_id" object */ j_app = cJSON_GetObjectItem(req_body, "app_id"); if(j_app == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'app_id' in req body\n"); return -1; } /* "token" object */ j_tok = cJSON_GetObjectItem(req_body, "token"); if(j_tok == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'token' in req body\n"); return -1; } if (strncmp(j_tok->valuestring, g_token, c_token_len)) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Unauthorized Bazaar %s request\n", action); return -1; } /* Call bazaar script */ char cmd[256]; switch (*act) { case eInstall: case eUpgrade: fprintf(stderr, "Installing: %s\n", j_url->valuestring); sprintf(cmd, "bazaar install %s %s %s", j_app->valuestring, j_url->valuestring, j_md5->valuestring); break; case eRemove: fprintf(stderr, "Removing: %s\n", j_app->valuestring); sprintf(cmd, "bazaar remove %s", j_app->valuestring); break; default: fprintf(stderr, "Unknown Bazaar action: %s\n", j_cmd->valuestring); ret = -1; goto out; } ret = system(cmd); out: /* release our resources */ cJSON_Delete(req_body, r->pool); return ret; }
static ngx_int_t ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { int wellFormed; ngx_chain_t *cl; ngx_http_xslt_filter_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xslt filter body"); if (in == NULL) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module); if (ctx == NULL || ctx->done) { return ngx_http_next_body_filter(r, in); } for (cl = in; cl; cl = cl->next) { if (ngx_http_xslt_add_chunk(r, ctx, cl->buf) != NGX_OK) { if (ctx->ctxt->myDoc) { #if (NGX_HTTP_XSLT_REUSE_DTD) ctx->ctxt->myDoc->extSubset = NULL; #endif xmlFreeDoc(ctx->ctxt->myDoc); } xmlFreeParserCtxt(ctx->ctxt); return ngx_http_xslt_send(r, ctx, NULL); } if (cl->buf->last_buf || cl->buf->last_in_chain) { ctx->doc = ctx->ctxt->myDoc; #if (NGX_HTTP_XSLT_REUSE_DTD) ctx->doc->extSubset = NULL; #endif wellFormed = ctx->ctxt->wellFormed; xmlFreeParserCtxt(ctx->ctxt); if (wellFormed) { return ngx_http_xslt_send(r, ctx, ngx_http_xslt_apply_stylesheet(r, ctx)); } xmlFreeDoc(ctx->doc); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "not well formed XML document"); return ngx_http_xslt_send(r, ctx, NULL); } } return NGX_OK; }
static int ngx_http_lua_ngx_echo(lua_State *L, unsigned newline) { ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; const char *p; size_t len; size_t size; ngx_buf_t *b; ngx_chain_t *cl; ngx_int_t rc; int i; int nargs; int type; const char *msg; ngx_buf_tag_t tag; lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); 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 request ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); if (r->header_only) { return 0; } if (ctx->eof) { return luaL_error(L, "seen eof already"); } nargs = lua_gettop(L); size = 0; for (i = 1; i <= nargs; i++) { type = lua_type(L, i); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: lua_tolstring(L, i, &len); size += len; break; case LUA_TNIL: size += sizeof("nil") - 1; break; case LUA_TBOOLEAN: if (lua_toboolean(L, i)) { size += sizeof("true") - 1; } else { size += sizeof("false") - 1; } break; case LUA_TTABLE: size += ngx_http_lua_calc_strlen_in_table(L, i, i, 0 /* strict */); break; case LUA_TLIGHTUSERDATA: dd("userdata: %p", lua_touserdata(L, i)); if (lua_touserdata(L, i) == NULL) { size += sizeof("null") - 1; break; } continue; default: msg = lua_pushfstring(L, "string, number, boolean, nil, " "ngx.null, or array table expected, " "but got %s", lua_typename(L, type)); return luaL_argerror(L, i, msg); } } if (newline) { size += sizeof("\n") - 1; } if (size == 0) { /* do nothing for empty strings */ return 0; } tag = (ngx_buf_tag_t) &ngx_http_lua_module; cl = ngx_http_lua_chains_get_free_buf(r->connection->log, r->pool, &ctx->free_bufs, size, tag); if (cl == NULL) { return luaL_error(L, "out of memory"); } b = cl->buf; for (i = 1; i <= nargs; i++) { type = lua_type(L, i); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: p = lua_tolstring(L, i, &len); b->last = ngx_copy(b->last, (u_char *) p, len); break; case LUA_TNIL: *b->last++ = 'n'; *b->last++ = 'i'; *b->last++ = 'l'; break; case LUA_TBOOLEAN: if (lua_toboolean(L, i)) { *b->last++ = 't'; *b->last++ = 'r'; *b->last++ = 'u'; *b->last++ = 'e'; } else { *b->last++ = 'f'; *b->last++ = 'a'; *b->last++ = 'l'; *b->last++ = 's'; *b->last++ = 'e'; } break; case LUA_TTABLE: b->last = ngx_http_lua_copy_str_in_table(L, i, b->last); break; case LUA_TLIGHTUSERDATA: *b->last++ = 'n'; *b->last++ = 'u'; *b->last++ = 'l'; *b->last++ = 'l'; break; default: return luaL_error(L, "impossible to reach here"); } } if (newline) { *b->last++ = '\n'; } #if 0 if (b->last != b->end) { return luaL_error(L, "buffer error: %p != %p", b->last, b->end); } #endif ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, newline ? "lua say response" : "lua print response"); rc = ngx_http_lua_send_chain_link(r, ctx, cl); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return luaL_error(L, "failed to send data through the output filters"); } dd("downstream write: %d, buf len: %d", (int) rc, (int) (b->last - b->pos)); if (!ctx->out) { #if nginx_version >= 1001004 ngx_chain_update_chains(r->pool, #else ngx_chain_update_chains( #endif &ctx->free_bufs, &ctx->busy_bufs, &cl, tag); dd("out lua buf tag: %p, buffered: %x, busy bufs: %p", &ngx_http_lua_module, (int) r->connection->buffered, ctx->busy_bufs); }
static int ngx_http_lua_ngx_redirect(lua_State *L) { ngx_http_lua_ctx_t *ctx; ngx_int_t rc; int n; u_char *p; u_char *uri; size_t len; ngx_table_elt_t *h; ngx_http_request_t *r; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting one or two arguments"); } p = (u_char *) luaL_checklstring(L, 1, &len); if (n == 2) { rc = (ngx_int_t) luaL_checknumber(L, 2); if (rc != NGX_HTTP_MOVED_TEMPORARILY && rc != NGX_HTTP_MOVED_PERMANENTLY && rc != NGX_HTTP_TEMPORARY_REDIRECT) { return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY, " "ngx.HTTP_MOVED_PERMANENTLY, and " "ngx.HTTP_TEMPORARY_REDIRECT are allowed"); } } else { rc = NGX_HTTP_MOVED_TEMPORARILY; } 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 request ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); ngx_http_lua_check_if_abortable(L, ctx); if (r->header_sent || ctx->header_sent) { return luaL_error(L, "attempt to call ngx.redirect after sending out " "the headers"); } uri = ngx_palloc(r->pool, len); if (uri == NULL) { return luaL_error(L, "no memory"); } ngx_memcpy(uri, p, len); h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return luaL_error(L, "no memory"); } h->hash = ngx_http_lua_location_hash; #if 0 dd("location hash: %lu == %lu", (unsigned long) h->hash, (unsigned long) ngx_hash_key_lc((u_char *) "Location", sizeof("Location") - 1)); #endif h->value.len = len; h->value.data = uri; ngx_str_set(&h->key, "Location"); r->headers_out.status = rc; ctx->exit_code = rc; ctx->exited = 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua redirect to \"%V\" with code %i", &h->value, ctx->exit_code); if (len && uri[0] != '/') { r->headers_out.location = h; } /* * we do not set r->headers_out.location here to avoid the handling * the local redirects without a host name by ngx_http_header_filter() */ return lua_yield(L, 0); }
ngx_int_t ngx_postgres_upstream_get_peer(ngx_peer_connection_t *pc, void *data) { ngx_postgres_upstream_peer_data_t *pgdt = data; ngx_postgres_upstream_srv_conf_t *pgscf; #if defined(nginx_version) && (nginx_version < 8017) ngx_postgres_ctx_t *pgctx; #endif ngx_postgres_upstream_peers_t *peers; ngx_postgres_upstream_peer_t *peer; ngx_connection_t *pgxc = NULL; int fd; ngx_event_t *rev, *wev; ngx_int_t rc; u_char *connstring, *last; size_t len; dd("entering"); #if defined(nginx_version) && (nginx_version < 8017) if (data == NULL) { goto failed; } pgctx = ngx_http_get_module_ctx(pgdt->request, ngx_postgres_module); #endif pgscf = pgdt->srv_conf; pgdt->failed = 0; if (pgscf->max_cached && pgscf->single) { rc = ngx_postgres_keepalive_get_peer_single(pc, pgdt, pgscf); if (rc != NGX_DECLINED) { /* re-use keepalive peer */ dd("re-using keepalive peer (single)"); pgdt->state = state_db_send_query; ngx_postgres_process_events(pgdt->request); dd("returning NGX_AGAIN"); return NGX_AGAIN; } } peers = pgscf->peers; if (pgscf->current > peers->number - 1) { pgscf->current = 0; } peer = &peers->peer[pgscf->current++]; pgdt->name.len = peer->name.len; pgdt->name.data = peer->name.data; pc->name = &pgdt->name; pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->cached = 0; if ((pgscf->max_cached) && (!pgscf->single)) { rc = ngx_postgres_keepalive_get_peer_multi(pc, pgdt, pgscf); if (rc != NGX_DECLINED) { /* re-use keepalive peer */ dd("re-using keepalive peer (multi)"); pgdt->state = state_db_send_query; ngx_postgres_process_events(pgdt->request); dd("returning NGX_AGAIN"); return NGX_AGAIN; } } if ((pgscf->reject) && (pgscf->active_conns >= pgscf->max_cached)) { ngx_log_error(NGX_LOG_INFO, pc->log, 0, "postgres: keepalive connection pool is full," " rejecting request to upstream \"%V\"", &peer->name); /* a bit hack-ish way to return error response (setup part) */ pc->connection = ngx_get_connection(0, pc->log); #if defined(nginx_version) && (nginx_version < 8017) pgctx->status = NGX_HTTP_SERVICE_UNAVAILABLE; #endif dd("returning NGX_AGAIN (NGX_HTTP_SERVICE_UNAVAILABLE)"); return NGX_AGAIN; } /* sizeof("...") - 1 + 1 (for spaces and '\0' omitted */ len = sizeof("hostaddr=") + peer->host.len + sizeof("port=") + sizeof("65535") - 1 + sizeof("dbname=") + peer->dbname.len + sizeof("user="******"password="******"sslmode=disable"); connstring = ngx_pnalloc(pgdt->request->pool, len); if (connstring == NULL) { #if defined(nginx_version) && (nginx_version >= 8017) dd("returning NGX_ERROR"); return NGX_ERROR; #else goto failed; #endif } /* TODO add unix sockets */ last = ngx_snprintf(connstring, len - 1, "hostaddr=%V port=%d dbname=%V user=%V password=%V" " sslmode=disable", &peer->host, peer->port, &peer->dbname, &peer->user, &peer->password); *last = '\0'; dd("PostgreSQL connection string: %s", connstring); /* * internal checks in PQsetnonblocking are taking care of any * PQconnectStart failures, so we don't need to check them here. */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "postgres: connecting"); pgdt->pgconn = PQconnectStart((const char *)connstring); if (PQsetnonblocking(pgdt->pgconn, 1) == -1) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "postgres: connection failed: %s in upstream \"%V\"", PQerrorMessage(pgdt->pgconn), &peer->name); PQfinish(pgdt->pgconn); pgdt->pgconn = NULL; #if defined(nginx_version) && (nginx_version >= 8017) dd("returning NGX_DECLINED"); return NGX_DECLINED; #else pgctx->status = NGX_HTTP_BAD_GATEWAY; goto failed; #endif } #if defined(DDEBUG) && (DDEBUG > 1) PQtrace(pgdt->pgconn, stderr); #endif dd("connection status:%d", (int) PQstatus(pgdt->pgconn)); /* take spot in keepalive connection pool */ pgscf->active_conns++; /* add the file descriptor (fd) into an nginx connection structure */ fd = PQsocket(pgdt->pgconn); if (fd == -1) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "postgres: failed to get connection fd"); goto invalid; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "postgres: connection fd:%d", fd); pgxc = pc->connection = ngx_get_connection(fd, pc->log); if (pgxc == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "postgres: failed to get a free nginx connection"); goto invalid; } pgxc->log = pc->log; pgxc->log_error = pc->log_error; pgxc->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); rev = pgxc->read; wev = pgxc->write; rev->log = pc->log; wev->log = pc->log; /* register the connection with postgres connection fd into the * nginx event model */ if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { dd("NGX_USE_RTSIG_EVENT"); if (ngx_add_conn(pgxc) != NGX_OK) { goto bad_add; } } else if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { dd("NGX_USE_CLEAR_EVENT"); if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { goto bad_add; } if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { goto bad_add; } } else { dd("NGX_USE_LEVEL_EVENT"); if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) { goto bad_add; } if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT) != NGX_OK) { goto bad_add; } } pgxc->log->action = "connecting to PostgreSQL database"; pgdt->state = state_db_connect; dd("returning NGX_AGAIN"); return NGX_AGAIN; bad_add: ngx_log_error(NGX_LOG_ERR, pc->log, 0, "postgres: failed to add nginx connection"); invalid: ngx_postgres_upstream_free_connection(pc->log, pc->connection, pgdt->pgconn, pgscf); #if defined(nginx_version) && (nginx_version >= 8017) dd("returning NGX_ERROR"); return NGX_ERROR; #else failed: /* a bit hack-ish way to return error response (setup part) */ pc->connection = ngx_get_connection(0, pc->log); dd("returning NGX_AGAIN (NGX_ERROR)"); return NGX_AGAIN; #endif }
static int ngx_http_lua_ngx_exit(lua_State *L) { ngx_int_t rc; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; if (lua_gettop(L) != 1) { return luaL_error(L, "expecting one argument"); } 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 request ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER | NGX_HTTP_LUA_CONTEXT_SSL_CERT | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); rc = (ngx_int_t) luaL_checkinteger(L, 1); if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH)) { #if (NGX_HTTP_SSL) ctx->exit_code = rc; ctx->exited = 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", rc); if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE) { return 0; } return lua_yield(L, 0); #else return luaL_error(L, "no SSL support"); #endif } if (ctx->no_abort && rc != NGX_ERROR && rc != NGX_HTTP_CLOSE && rc != NGX_HTTP_REQUEST_TIME_OUT && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST) { return luaL_error(L, "attempt to abort with pending subrequests"); } if ((r->header_sent || ctx->header_sent) && rc >= NGX_HTTP_SPECIAL_RESPONSE && rc != NGX_HTTP_REQUEST_TIME_OUT && rc != NGX_HTTP_CLIENT_CLOSED_REQUEST && rc != NGX_HTTP_CLOSE) { if (rc != (ngx_int_t) r->headers_out.status) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to " "set status %i via ngx.exit after sending out the " "response status %ui", rc, r->headers_out.status); } rc = NGX_HTTP_OK; } dd("setting exit code: %d", (int) rc); ctx->exit_code = rc; ctx->exited = 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", ctx->exit_code); if (ctx->context & (NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER)) { return 0; } dd("calling yield"); return lua_yield(L, 0); }
ngx_int_t nchan_respond_msg(ngx_http_request_t *r, nchan_msg_t *msg, nchan_msg_id_t *msgid, ngx_int_t finalize, char **err) { ngx_buf_t *buffer = msg->buf; nchan_buf_and_chain_t *cb; ngx_int_t rc; ngx_chain_t *rchain = NULL; ngx_buf_t *rbuffer; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); if(ngx_buf_size(buffer) > 0) { cb = ngx_palloc(r->pool, sizeof(*cb)); if (!cb) { if(err) *err = "couldn't allocate memory for buf-and-chain while responding with msg"; return NGX_ERROR; } rchain = &cb->chain; rbuffer = &cb->buf; rchain->next = NULL; rchain->buf = rbuffer; ngx_memcpy(rbuffer, buffer, sizeof(*buffer)); nchan_msg_buf_open_fd_if_needed(rbuffer, NULL, r); r->headers_out.content_length_n=ngx_buf_size(rbuffer); } else { r->headers_out.content_length_n = 0; r->header_only = 1; } if (msg->content_type.data!=NULL) { r->headers_out.content_type.len=msg->content_type.len; r->headers_out.content_type.data = msg->content_type.data; } if(msgid == NULL) { msgid = &msg->id; } if(nchan_set_msgid_http_response_headers(r, ctx, msgid) != NGX_OK) { if(err) *err = "can't set msgid headers"; return NGX_ERROR; } r->headers_out.status=NGX_HTTP_OK; nchan_include_access_control_if_needed(r, ctx); //we know the entity length, and we're using just one buffer. so no chunking please. if((rc = ngx_http_send_header(r)) >= NGX_HTTP_SPECIAL_RESPONSE) { ERR("request %p, send_header response %i", r, rc); if(err) *err="WTF just happened to request?"; return NGX_ERROR; } if(rchain) { rc= nchan_output_filter(r, rchain); } if(finalize) { ngx_http_finalize_request(r, rc); } return rc; }
int ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, size_t *errlen) { ngx_http_lua_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { *errlen = ngx_snprintf(err, *errlen, "no request ctx found") - err; return NGX_ERROR; } if (ngx_http_lua_ffi_check_context(ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER | NGX_HTTP_LUA_CONTEXT_SSL_CERT, err, errlen) != NGX_OK) { return NGX_ERROR; } if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_CERT) { #if (NGX_HTTP_SSL) ctx->exit_code = status; ctx->exited = 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %d", status); return NGX_OK; #else return NGX_ERROR; #endif } if (ctx->no_abort && status != NGX_ERROR && status != NGX_HTTP_CLOSE && status != NGX_HTTP_REQUEST_TIME_OUT && status != NGX_HTTP_CLIENT_CLOSED_REQUEST) { *errlen = ngx_snprintf(err, *errlen, "attempt to abort with pending subrequests") - err; return NGX_ERROR; } if ((r->header_sent || ctx->header_sent) && status >= NGX_HTTP_SPECIAL_RESPONSE && status != NGX_HTTP_REQUEST_TIME_OUT && status != NGX_HTTP_CLIENT_CLOSED_REQUEST && status != NGX_HTTP_CLOSE) { if (status != (ngx_int_t) r->headers_out.status) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to " "set status %d via ngx.exit after sending out the " "response status %ui", status, r->headers_out.status); } status = NGX_HTTP_OK; } ctx->exit_code = status; ctx->exited = 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", ctx->exit_code); if (ctx->context & (NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER)) { return NGX_DONE; } return NGX_OK; }
static ngx_int_t ngx_http_image_header_filter(ngx_http_request_t *r) { off_t len; ngx_http_image_filter_ctx_t *ctx; ngx_http_image_filter_conf_t *conf; if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { return ngx_http_next_header_filter(r); } ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); if (ctx) { ngx_http_set_ctx(r, NULL, ngx_http_image_filter_module); return ngx_http_next_header_filter(r); } conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (conf->filter == NGX_HTTP_IMAGE_OFF) { return ngx_http_next_header_filter(r); } if (r->headers_out.content_type.len >= sizeof("multipart/x-mixed-replace") - 1 && ngx_strncasecmp(r->headers_out.content_type.data, (u_char *) "multipart/x-mixed-replace", sizeof("multipart/x-mixed-replace") - 1) == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image filter: multipart/x-mixed-replace response"); return NGX_ERROR; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_image_filter_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_image_filter_module); len = r->headers_out.content_length_n; if (len != -1 && len > (off_t) conf->buffer_size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image filter: too big response: %O", len); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; } if (len == -1) { ctx->length = conf->buffer_size; } else { ctx->length = (size_t) len; } 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 int ngx_http_lua_ngx_exec(lua_State *L) { int n; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_str_t uri; ngx_str_t args, user_args; ngx_uint_t flags; u_char *p; u_char *q; size_t len; const char *msg; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting one or two arguments, but got %d", n); } r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } ngx_str_null(&args); /* read the 1st argument (uri) */ p = (u_char *) luaL_checklstring(L, 1, &len); if (len == 0) { return luaL_error(L, "The uri argument is empty"); } uri.data = ngx_palloc(r->pool, len); if (uri.data == NULL) { return luaL_error(L, "no memory"); } ngx_memcpy(uri.data, p, len); uri.len = len; 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); ngx_http_lua_check_if_abortable(L, ctx); if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (n == 2) { /* read the 2nd argument (args) */ dd("args type: %s", luaL_typename(L, 2)); switch (lua_type(L, 2)) { case LUA_TNUMBER: case LUA_TSTRING: p = (u_char *) lua_tolstring(L, 2, &len); user_args.data = ngx_palloc(r->pool, len); if (user_args.data == NULL) { return luaL_error(L, "no memory"); } ngx_memcpy(user_args.data, p, len); user_args.len = len; break; case LUA_TTABLE: ngx_http_lua_process_args_option(r, L, 2, &user_args); dd("user_args: %.*s", (int) user_args.len, user_args.data); break; case LUA_TNIL: ngx_str_null(&user_args); break; default: msg = lua_pushfstring(L, "string, number, or table expected, " "but got %s", luaL_typename(L, 2)); return luaL_argerror(L, 2, msg); } } else { user_args.data = NULL; user_args.len = 0; } if (user_args.len) { if (args.len == 0) { args = user_args; } else { p = ngx_palloc(r->pool, args.len + user_args.len + 1); if (p == NULL) { return luaL_error(L, "no memory"); } q = ngx_copy(p, args.data, args.len); *q++ = '&'; ngx_memcpy(q, user_args.data, user_args.len); args.data = p; args.len += user_args.len + 1; } } if (r->header_sent || ctx->header_sent) { return luaL_error(L, "attempt to call ngx.exec after " "sending out response headers"); } ctx->exec_uri = uri; ctx->exec_args = args; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exec \"%V?%V\"", &ctx->exec_uri, &ctx->exec_args); return lua_yield(L, 0); }
static ngx_buf_t * ngx_http_image_process(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_image_filter_ctx_t *ctx; ngx_http_image_filter_conf_t *conf; r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); rc = ngx_http_image_size(r, ctx); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (conf->filter == NGX_HTTP_IMAGE_SIZE) { return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); } ctx->angle = ngx_http_image_filter_get_value(r, conf->acv, conf->angle); if (conf->filter == NGX_HTTP_IMAGE_ROTATE) { if (ctx->angle != 90 && ctx->angle != 180 && ctx->angle != 270) { return NULL; } return ngx_http_image_resize(r, ctx); } if (conf->filter == NGX_HTTP_IMAGE_WATERMARK) { if (!conf->watermark.data) { return NULL; } return ngx_http_image_resize(r, ctx); } ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width); if (ctx->max_width == 0) { return NULL; } ctx->max_height = ngx_http_image_filter_get_value(r, conf->hcv, conf->height); if (ctx->max_height == 0) { return NULL; } if (rc == NGX_OK && ctx->width <= ctx->max_width && ctx->height <= ctx->max_height && ctx->angle == 0 && !ctx->force) { return ngx_http_image_asis(r, ctx); } return ngx_http_image_resize(r, ctx); }
static ngx_inline ngx_int_t ngx_http_modsecurity_load_headers_out(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; char *data; request_rec *req; u_char *content_type; ngx_uint_t content_type_len; ngx_http_variable_value_t *vv; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_uint_t i; char *key, *value; u_char *buf = NULL; size_t size = 0; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); req = ctx->req; req->status = r->headers_out.status; req->status_line = (char *)ngx_pstrdup0(r->pool, &r->headers_out.status_line); if (r->headers_out.charset.len) { content_type_len = r->headers_out.content_type.len + r->headers_out.charset.len + ngx_strlen("; charset=") + 1; content_type = ngx_palloc(r->pool, content_type_len); if (content_type == NULL) { return NGX_ERROR; } ngx_snprintf(content_type, content_type_len, "%V; charset=%V%Z", &r->headers_out.content_type, &r->headers_out.charset); r->headers_out.content_type.data = content_type; r->headers_out.content_type.len = content_type_len; } /* deep copy */ part = &r->headers_out.headers.part; h = part->elts; for (i = 0; ; i++) { if (i >= part->nelts) { if (part->next == NULL) break; part = part->next; h = part->elts; i = 0; } size += h[i].key.len + h[i].value.len + 2; buf = ngx_palloc(r->pool, size); if (buf == NULL) { return NGX_ERROR; } key = (char *)buf; buf = ngx_cpymem(buf, h[i].key.data, h[i].key.len); *buf++ = '\0'; value = (char *)buf; buf = ngx_cpymem(buf, h[i].value.data, h[i].value.len); *buf++ = '\0'; apr_table_addn(req->headers_out, key, value); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%V: %V\"", &h[i].key, &h[i].value); } for (i = 0; special_headers_out[i].name; i++) { vv = ngx_http_get_variable(r, &special_headers_out[i].variable_name, ngx_hash_key(special_headers_out[i].variable_name.data, special_headers_out[i].variable_name.len)); if (vv && !vv->not_found) { data = ngx_palloc(r->pool, vv->len + 1); if (data == NULL) { return NGX_ERROR; } ngx_memcpy(data,vv->data, vv->len); data[vv->len] = '\0'; apr_table_setn(req->headers_out, special_headers_out[i].name, data); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%s: %s\"", special_headers_out[i].name, data); } } req->content_type = apr_table_get(ctx->req->headers_out, "Content-Type"); req->content_encoding = apr_table_get(ctx->req->headers_out, "Content-Encoding"); data = (char *)apr_table_get(ctx->req->headers_out, "Content-Languages"); if(data != NULL) { ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *)); *(const char **)apr_array_push(ctx->req->content_languages) = data; } /* req->chunked = r->chunked; may be useless */ req->clength = r->headers_out.content_length_n; req->mtime = apr_time_make(r->headers_out.last_modified_time, 0); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out done"); return NGX_OK; }