// merge all static pull into ngx_live_relay_static_main_conf_t; static char * ngx_live_relay_static_init_main_dconf(ngx_conf_t *cf, void *conf) { ngx_live_relay_static_main_conf_t *rsmcf; ngx_live_relay_static_main_dconf_t *rsmdcf; ngx_core_conf_t *ccf; ngx_live_relay_t *relay; ngx_live_relay_static_relay_t *srelay, *old, *sl, *sln, **sll; ngx_live_relay_static_ctx_t *ctx; ngx_live_relay_ctx_t *rctx; ngx_map_node_t *node; unsigned used; char *rc; ngx_uint_t i, hash; rsmdcf = conf; rsmcf = ngx_rtmp_cycle_get_module_main_conf(ngx_cycle, ngx_live_relay_static_module); ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_core_module); used = rsmcf->used? 0: 1; sl = NULL; sll = &sl; relay = rsmdcf->pulls.elts; for (i = 0; i < rsmdcf->pulls.nelts; ++i, ++relay) { // should static pull in current process? if (ngx_process == NGX_PROCESS_WORKER) { hash = ngx_hash_key_lc(relay->stream.data, relay->stream.len); if (hash % ccf->worker_processes != ngx_worker) { continue; } } // check static pull duplicate node = ngx_map_find(&rsmcf->pulls[used], (intptr_t) &relay->stream); if (node) { rc = "duplicate static pull"; goto error; } srelay = ngx_live_relay_get_static_relay(rsmcf); if (srelay == NULL) { rc = "get static relay failed"; goto error; } srelay->relay = relay; srelay->node.raw_key = (intptr_t) &relay->stream; ngx_map_insert(&rsmcf->pulls[used], &srelay->node, 0); // check static pull is exist node = ngx_map_find(&rsmcf->pulls[rsmcf->used], (intptr_t) &relay->stream); if (node) { old = (ngx_live_relay_static_relay_t *) node; srelay->session = old->session; // link swap static pull *sll = old; sll = &(*sll)->next; } } // delete swap static pull from old while (sl) { sln = sl; sl = sl->next; ngx_map_delete(&rsmcf->pulls[rsmcf->used], (intptr_t) &sln->relay->stream); ngx_live_relay_put_static_relay(rsmcf, sln); } // stop deleted static pull node = ngx_map_begin(&rsmcf->pulls[rsmcf->used]); while (node) { srelay = (ngx_live_relay_static_relay_t *) node; node = ngx_map_next(node); ngx_live_relay_put_static_relay(rsmcf, srelay); rctx = ngx_rtmp_get_module_ctx(srelay->session, ngx_live_relay_module); rctx->giveup = 1; srelay->session->finalize_reason = NGX_LIVE_NORMAL_CLOSE; ngx_rtmp_finalize_session(srelay->session); ngx_map_delete(&rsmcf->pulls[rsmcf->used], (intptr_t) &srelay->relay->stream); } // new static relay node = ngx_map_begin(&rsmcf->pulls[used]); for (; node; node = ngx_map_next(node)) { srelay = (ngx_live_relay_static_relay_t *) node; if (srelay->session == NULL) { ngx_live_relay_static_relay(NULL, srelay); } else { ctx = ngx_rtmp_get_module_ctx(srelay->session, ngx_live_relay_static_module); ctx->relay = srelay; } } rsmcf->used = used; return NGX_CONF_OK; error: // recycle static relay resource node = ngx_map_begin(&rsmcf->pulls[used]); while (node) { srelay = (ngx_live_relay_static_relay_t *) node; node = ngx_map_next(node); ngx_live_relay_put_static_relay(rsmcf, srelay); ngx_map_delete(&rsmcf->pulls[used], (intptr_t) &srelay->relay->stream); } return rc; }
ngx_int_t ngx_http_srcache_store_response_header(ngx_http_request_t *r, ngx_http_srcache_ctx_t *ctx) { ngx_chain_t *cl; size_t len; ngx_buf_t *b; ngx_uint_t status; ngx_uint_t i; ngx_str_t *status_line; ngx_list_part_t *part; ngx_table_elt_t *header; u_char buf[sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1]; ngx_http_srcache_loc_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); dd("request: %p, uri: %.*s", r, (int) r->uri.len, r->uri.data); len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1 /* the end of the header */ + sizeof(CRLF) - 1; if (r->headers_out.status_line.len) { dd("status line defined"); len += r->headers_out.status_line.len; status_line = &r->headers_out.status_line; status = 0; } else { dd("status line not defined"); status = r->headers_out.status; if (status >= NGX_HTTP_OK && status < NGX_HTTP_LAST_LEVEL_200) { /* 2XX */ status -= NGX_HTTP_OK; dd("status: %d", (int) status); status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_MOVED_PERMANENTLY && status < NGX_HTTP_LAST_LEVEL_300) { /* 3XX */ if (status == NGX_HTTP_NOT_MODIFIED) { r->header_only = 1; } status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_BAD_REQUEST && status < NGX_HTTP_LAST_LEVEL_400) { /* 4XX */ status = status - NGX_HTTP_BAD_REQUEST + NGX_HTTP_LEVEL_200 + NGX_HTTP_LEVEL_300; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR && status < NGX_HTTP_LAST_LEVEL_500) { /* 5XX */ status = status - NGX_HTTP_INTERNAL_SERVER_ERROR + NGX_HTTP_LEVEL_200 + NGX_HTTP_LEVEL_300 + NGX_HTTP_LEVEL_400; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else { len += NGX_INT_T_LEN; status_line = NULL; } } if (!conf->hide_content_type && r->headers_out.content_type.len) { len += sizeof("Content-Type: ") - 1 + r->headers_out.content_type.len + 2; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { len += sizeof("; charset=") - 1 + r->headers_out.charset.len; } } if (!conf->hide_last_modified) { if (r->headers_out.last_modified_time != -1) { if (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT && r->headers_out.status != NGX_HTTP_NOT_MODIFIED && r->headers_out.status != NGX_HTTP_NO_CONTENT) { r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; } } dd("last modified time: %d", (int) r->headers_out.last_modified_time); if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { (void) ngx_http_time(buf, r->headers_out.last_modified_time); len += sizeof("Last-Modified: ") - 1 + sizeof(buf) + 2; } } if (r->allow_ranges) { len += sizeof("X-SRCache-Allow-Ranges: 1") - 1 + 2; } part = &r->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 (ngx_hash_find(&conf->hide_headers_hash, header[i].hash, header[i].lowcase_key, header[i].key.len)) { continue; } len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len + sizeof(CRLF) - 1; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } /* "HTTP/1.x " */ b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1); /* status line */ if (status_line) { b->last = ngx_copy(b->last, status_line->data, status_line->len); } else { b->last = ngx_sprintf(b->last, "%ui", status); } *b->last++ = CR; *b->last++ = LF; if (!conf->hide_content_type && r->headers_out.content_type.len) { b->last = ngx_cpymem(b->last, "Content-Type: ", sizeof("Content-Type: ") - 1); b->last = ngx_copy(b->last, r->headers_out.content_type.data, r->headers_out.content_type.len); if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { b->last = ngx_cpymem(b->last, "; charset=", sizeof("; charset=") - 1); b->last = ngx_copy(b->last, r->headers_out.charset.data, r->headers_out.charset.len); } *b->last++ = CR; *b->last++ = LF; } if (!conf->hide_last_modified && r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { b->last = ngx_cpymem(b->last, "Last-Modified: ", sizeof("Last-Modified: ") - 1); b->last = ngx_cpymem(b->last, buf, sizeof(buf)); *b->last++ = CR; *b->last++ = LF; } if (r->allow_ranges) { b->last = ngx_cpymem(b->last, "X-SRCache-Allow-Ranges: 1\r\n", sizeof("X-SRCache-Allow-Ranges: 1\r\n") - 1); } part = &r->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; } dd("header hash: %lu, hash lc: %lu", (unsigned long) header[i].hash, (unsigned long) ngx_hash_key_lc(header[i].key.data, header[i].key.len)); if (ngx_hash_find(&conf->hide_headers_hash, header[i].hash, header[i].lowcase_key, header[i].key.len)) { dd("skipped header key: %.*s", (int) header[i].key.len, header[i].key.data); continue; } dd("header not skipped"); b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); *b->last++ = ':'; *b->last++ = ' '; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = CR; *b->last++ = LF; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache store header %*s", (size_t) (b->last - b->pos), b->pos); /* the end of HTTP header */ *b->last++ = CR; *b->last++ = LF; if (b->last != b->end) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_fetch: buffer error when serializing the " "response header: %O left", (off_t) (b->last - b->end)); return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; ctx->body_to_cache = cl; ctx->response_length += len; return NGX_OK; }
static ngx_int_t ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf) { ngx_hash_init_t calls_hash; ngx_rtmp_handler_pt *eh; ngx_rtmp_amf_handler_t *h; ngx_hash_key_t *ha; size_t n, m; static size_t pm_events[] = { NGX_RTMP_MSG_CHUNK_SIZE, NGX_RTMP_MSG_ABORT, NGX_RTMP_MSG_ACK, NGX_RTMP_MSG_ACK_SIZE, NGX_RTMP_MSG_BANDWIDTH }; static size_t amf_events[] = { NGX_RTMP_MSG_AMF_CMD, NGX_RTMP_MSG_AMF_META, NGX_RTMP_MSG_AMF_SHARED, NGX_RTMP_MSG_AMF3_CMD, NGX_RTMP_MSG_AMF3_META, NGX_RTMP_MSG_AMF3_SHARED }; /* init standard protocol events */ for(n = 0; n < sizeof(pm_events) / sizeof(pm_events[0]); ++n) { eh = ngx_array_push(&cmcf->events[pm_events[n]]); *eh = ngx_rtmp_protocol_message_handler; } /* init amf events */ for(n = 0; n < sizeof(amf_events) / sizeof(amf_events[0]); ++n) { eh = ngx_array_push(&cmcf->events[amf_events[n]]); *eh = ngx_rtmp_amf_message_handler; } /* init user protocol events */ eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_USER]); *eh = ngx_rtmp_user_message_handler; /* aggregate to audio/video map */ eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AGGREGATE]); *eh = ngx_rtmp_aggregate_message_handler; /* init amf callbacks */ ngx_array_init(&cmcf->amf_arrays, cf->pool, 1, sizeof(ngx_hash_key_t)); h = cmcf->amf.elts; for(n = 0; n < cmcf->amf.nelts; ++n, ++h) { ha = cmcf->amf_arrays.elts; for(m = 0; m < cmcf->amf_arrays.nelts; ++m, ++ha) { if (h->name.len == ha->key.len && !ngx_strncmp(h->name.data, ha->key.data, ha->key.len)) { break; } } if (m == cmcf->amf_arrays.nelts) { ha = ngx_array_push(&cmcf->amf_arrays); ha->key = h->name; ha->key_hash = ngx_hash_key_lc(ha->key.data, ha->key.len); ha->value = ngx_array_create(cf->pool, 1, sizeof(ngx_rtmp_handler_pt)); if (ha->value == NULL) { return NGX_ERROR; } } eh = ngx_array_push((ngx_array_t*)ha->value); *eh = h->handler; } calls_hash.hash = &cmcf->amf_hash; calls_hash.key = ngx_hash_key_lc; calls_hash.max_size = 512; calls_hash.bucket_size = ngx_cacheline_size; calls_hash.name = "amf_hash"; calls_hash.pool = cf->pool; calls_hash.temp_pool = NULL; if (ngx_hash_init(&calls_hash, cmcf->amf_arrays.elts, cmcf->amf_arrays.nelts) != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
return ngx_http_set_builtin_header(r, hv, value); } ngx_int_t ngx_http_lua_set_output_header(ngx_http_request_t *r, ngx_str_t key, ngx_str_t value, unsigned override) { ngx_http_lua_header_val_t hv; ngx_http_lua_set_header_t *handlers = ngx_http_lua_set_handlers; ngx_uint_t i; dd("set header value: %.*s", (int) value.len, value.data); hv.hash = ngx_hash_key_lc(key.data, key.len); hv.key = key; hv.offset = 0; hv.no_override = !override; hv.handler = NULL; for (i = 0; handlers[i].name.len; i++) { if (hv.key.len != handlers[i].name.len || ngx_strncasecmp(hv.key.data, handlers[i].name.data, handlers[i].name.len) != 0) { dd("hv key comparison: %s <> %s", handlers[i].name.data, hv.key.data); continue;
ngx_int_t ngx_http_srcache_hide_headers_hash(ngx_conf_t *cf, ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_loc_conf_t *prev, ngx_str_t *default_hide_headers, ngx_hash_init_t *hash) { ngx_str_t *h; ngx_uint_t i, j; ngx_array_t hide_headers; ngx_hash_key_t *hk; if (conf->hide_headers == NGX_CONF_UNSET_PTR && conf->pass_headers == NGX_CONF_UNSET_PTR) { conf->hide_headers_hash = prev->hide_headers_hash; if (conf->hide_headers_hash.buckets) { return NGX_OK; } conf->hide_headers = prev->hide_headers; conf->pass_headers = prev->pass_headers; conf->hide_content_type = prev->hide_content_type; conf->hide_last_modified = prev->hide_last_modified; } else { if (conf->hide_headers == NGX_CONF_UNSET_PTR) { conf->hide_headers = prev->hide_headers; } if (conf->pass_headers == NGX_CONF_UNSET_PTR) { conf->pass_headers = prev->pass_headers; } } dd("init hide headers"); if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { return NGX_ERROR; } for (h = default_hide_headers; h->len; h++) { hk = ngx_array_push(&hide_headers); if (hk == NULL) { return NGX_ERROR; } hk->key = *h; hk->key_hash = ngx_hash_key_lc(h->data, h->len); hk->value = (void *) 1; } if (conf->hide_headers != NGX_CONF_UNSET_PTR) { dd("hide headers not empty"); h = conf->hide_headers->elts; for (i = 0; i < conf->hide_headers->nelts; i++) { hk = hide_headers.elts; for (j = 0; j < hide_headers.nelts; j++) { if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) { goto exist; } } hk = ngx_array_push(&hide_headers); if (hk == NULL) { return NGX_ERROR; } hk->key = h[i]; hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len); hk->value = (void *) 1; if (h[i].len == sizeof("Last-Modified") - 1 && ngx_strncasecmp(h[i].data, (u_char *) "Last-Modified", sizeof("Last-Modified") - 1) == 0) { conf->hide_last_modified = 1; } if (h[i].len == sizeof("Content-Type") - 1 && ngx_strncasecmp(h[i].data, (u_char *) "Content-Type", sizeof("Content-Type") - 1) == 0) { conf->hide_content_type = 1; } dd("adding header to hide headers: %.*s", (int) h[i].len, h[i].data); exist: continue; } } if (conf->pass_headers != NGX_CONF_UNSET_PTR) { h = conf->pass_headers->elts; hk = hide_headers.elts; for (i = 0; i < conf->pass_headers->nelts; i++) { for (j = 0; j < hide_headers.nelts; j++) { if (hk[j].key.data == NULL) { continue; } if (h[i].len == sizeof("Content-Type") - 1 && ngx_strncasecmp(h[i].data, (u_char *) "Content-Type", sizeof("Content-Type") - 1) == 0) { conf->hide_content_type = 0; } if (h[i].len == sizeof("Last-Modified") - 1 && ngx_strncasecmp(h[i].data, (u_char *) "Last-Modified", sizeof("Last-Modified") - 1) == 0) { conf->hide_last_modified = 0; } if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) { hk[j].key.data = NULL; break; } } } } hash->hash = &conf->hide_headers_hash; hash->key = ngx_hash_key_lc; hash->pool = cf->pool; hash->temp_pool = NULL; return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts); }
static ngx_int_t ngx_http_wlr_finalize_hashtables(ngx_conf_t *cf, ngx_http_dummy_loc_conf_t *dlc) { int get_sz = 0, headers_sz = 0, body_sz = 0, uri_sz = 0; ngx_array_t *get_ar = NULL, *headers_ar = NULL, *body_ar = NULL, *uri_ar = NULL; ngx_hash_key_t *arr_node; ngx_hash_init_t hash_init; uint i; NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "finalizing hashtables"); for (i = 0; i < dlc->tmp_wlr->nelts; i++) { switch (((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone) { case FILE_EXT: case BODY: body_sz++; break; case HEADERS: headers_sz++; break; case URL: uri_sz++; break; case ARGS: get_sz++; break; case UNKNOWN: default: return (NGX_ERROR); } } NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "nb items : body:%d headers:%d uri:%d get:%d", body_sz, headers_sz, uri_sz, get_sz); if (get_sz) get_ar = ngx_array_create(cf->pool, get_sz, sizeof(ngx_hash_key_t)); if (headers_sz) headers_ar = ngx_array_create(cf->pool, headers_sz, sizeof(ngx_hash_key_t)); if (body_sz) body_ar = ngx_array_create(cf->pool, body_sz, sizeof(ngx_hash_key_t)); if (uri_sz) uri_ar = ngx_array_create(cf->pool, uri_sz, sizeof(ngx_hash_key_t)); for (i = 0; i < dlc->tmp_wlr->nelts; i++) { switch (((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone) { case FILE_EXT: case BODY: arr_node = (ngx_hash_key_t*) ngx_array_push(body_ar); break; case HEADERS: arr_node = (ngx_hash_key_t*) ngx_array_push(headers_ar); break; case URL: arr_node = (ngx_hash_key_t*) ngx_array_push(uri_ar); break; case ARGS: arr_node = (ngx_hash_key_t*) ngx_array_push(get_ar); break; default: return (NGX_ERROR); } if (!arr_node) return (NGX_ERROR); ngx_memset(arr_node, 0, sizeof(ngx_hash_key_t)); arr_node->key = *(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name); arr_node->key_hash = ngx_hash_key_lc(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name->data, ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name->len); arr_node->value = (void *) &(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i]); #ifdef SPECIAL__debug_whitelist_heavy ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing new WL, zone:%d, target:%V, %d IDs", ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone , ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name, ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->nelts); unsigned int z; for (z = 0; z < ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->nelts; z++) ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "id:%d", ((int *)((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->elts)[z]); #endif } hash_init.key = &ngx_hash_key_lc; hash_init.pool = cf->pool; hash_init.temp_pool = NULL; hash_init.max_size = 1024; hash_init.bucket_size = 512; if (body_ar) { dlc->wlr_body_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_body_hash; hash_init.name = "wlr_body_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) body_ar->elts, body_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$BODY hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$BODY hashtable init successed !"); } if (uri_ar) { dlc->wlr_url_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_url_hash; hash_init.name = "wlr_url_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) uri_ar->elts, uri_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$URL hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$URL hashtable init successed !"); } if (get_ar) { dlc->wlr_args_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_args_hash; hash_init.name = "wlr_args_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) get_ar->elts, get_ar->nelts) != NGX_OK) { /* LCOV_EXCL_LINE */ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$ARGS hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$ARGS hashtable init successed %d !", dlc->wlr_args_hash->size); } if (headers_ar) { dlc->wlr_headers_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_headers_hash; hash_init.name = "wlr_headers_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) headers_ar->elts, headers_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$HEADERS hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$HEADERS hashtable init successed %d !", dlc->wlr_headers_hash->size); } return (NGX_OK); }
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; } 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) { 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); r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return luaL_error(L, "no memory"); } r->headers_out.location->hash = ngx_http_lua_location_hash; #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); }
ngx_int_t ngx_http_accounting_handler(ngx_http_request_t *r) { ngx_str_t *accounting_id; ngx_uint_t key; ngx_uint_t status; ngx_uint_t *status_array; ngx_http_accounting_stats_t *stats; ngx_time_t * time = ngx_timeofday(); accounting_id = get_accounting_id(r); ngx_uint_t req_latency_ms = (time->sec * 1000 + time->msec) - (r->start_sec * 1000 + r->start_msec); // following magic airlifted from ngx_http_upstream.c:4416-4423 ngx_uint_t upstream_req_latency_ms = 0; ngx_http_upstream_state_t *state; if (r->upstream_states != NULL && r->upstream_states->nelts != 0) { state = r->upstream_states->elts; if (state[0].status) { // not even checking the status here... #if (nginx_version < 1009000) upstream_req_latency_ms = (state[0].response_sec * 1000 + state[0].response_msec); #else upstream_req_latency_ms = state[0].response_time; #endif } } // TODO: key should be cached to save CPU time key = ngx_hash_key_lc(accounting_id->data, accounting_id->len); stats = ngx_http_accounting_hash_find(&stats_hash, key, accounting_id->data, accounting_id->len); if (stats == NULL) { stats = ngx_pcalloc(stats_hash.pool, sizeof(ngx_http_accounting_stats_t)); status_array = ngx_pcalloc(stats_hash.pool, sizeof(ngx_uint_t) * http_status_code_count); if (stats == NULL || status_array == NULL) return NGX_ERROR; stats->http_status_code = status_array; ngx_http_accounting_hash_add(&stats_hash, key, accounting_id->data, accounting_id->len, stats); } if (r->err_status) { status = r->err_status; } else if (r->headers_out.status) { status = r->headers_out.status; } else { status = NGX_HTTP_DEFAULT; } stats->nr_requests += 1; stats->bytes_in += r->request_length; stats->bytes_out += r->connection->sent; stats->total_latency_ms += req_latency_ms; stats->total_upstream_latency_ms += upstream_req_latency_ms; stats->http_status_code[http_status_code_to_index_map[status]] += 1; return NGX_OK; }
static ngx_int_t ngx_http_google_request_parser(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx) { // parse arg u_char * last = r->unparsed_uri.data + r->unparsed_uri.len; ctx->arg->data = ngx_strlchr(ctx->uri->data, last, '?'); // parse uri if (ctx->arg->data) { ctx->arg->len = last - ++ctx->arg->data; ctx->uri->len -= ctx->arg->len + 1; } // parse args if (ctx->arg->len) { ctx->args = ngx_http_google_explode_kv(r, ctx->arg, "&"); } else { ctx->args = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t)); } if (!ctx->args) return NGX_ERROR; // parse cookies if (r->headers_in.cookies.nelts) { ngx_table_elt_t ** ck = r->headers_in.cookies.elts; ctx->cookies = ngx_http_google_explode_kv(r, &(*ck)->value, ";"); } else { ctx->cookies = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t)); } if (!ctx->cookies) return NGX_ERROR; // parse host if (ngx_http_google_request_parse_host(r, ctx)) return NGX_ERROR; // traverse headers ngx_uint_t i, acl = 0; ngx_list_part_t * pt = &r->headers_in.headers.part; ngx_table_elt_t * hd = pt->elts, * tb; for (i = 0; /* void */; i++) { if (i >= pt->nelts) { if (pt->next == NULL) break; pt = pt->next; hd = pt->elts; i = 0; } tb = hd + i; if (!ngx_strncasecmp(tb->key.data, (u_char *)"Accept-Language", 15)) { acl = 1; tb->value = *ctx->lang; } } if (!acl) { tb = ngx_list_push(&r->headers_in.headers); if (!tb) return NGX_ERROR; ngx_str_set(&tb->key, "Accept-Language"); tb->value = *ctx->lang; tb->hash = ngx_hash_key_lc(tb->key.data, tb->key.len); } return NGX_OK; }
static char * ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_scgi_loc_conf_t *prev = parent; ngx_http_scgi_loc_conf_t *conf = child; u_char *p; size_t size; uintptr_t *code; ngx_uint_t i; ngx_array_t headers_names; ngx_keyval_t *src; ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { conf->upstream.store_lengths = prev->upstream.store_lengths; conf->upstream.store_values = prev->upstream.store_values; } } ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); ngx_conf_merge_value(conf->upstream.ignore_client_abort, prev->upstream.ignore_client_abort, 0); ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); ngx_conf_merge_msec_value(conf->upstream.send_timeout, prev->upstream.send_timeout, 60000); ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); ngx_conf_merge_size_value(conf->upstream.buffer_size, prev->upstream.buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, 8, ngx_pagesize); if (conf->upstream.bufs.num < 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "there must be at least 2 \"scgi_buffers\""); return NGX_CONF_ERROR; } size = conf->upstream.buffer_size; if (size < conf->upstream.bufs.size) { size = conf->upstream.bufs.size; } ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, prev->upstream.busy_buffers_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.busy_buffers_size = 2 * size; } else { conf->upstream.busy_buffers_size = conf->upstream.busy_buffers_size_conf; } if (conf->upstream.busy_buffers_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_busy_buffers_size\" must be equal or bigger " "than maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } if (conf->upstream.busy_buffers_size > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_busy_buffers_size\" must be less than " "the size of all \"scgi_buffers\" minus one buffer"); return NGX_CONF_ERROR; } ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf, prev->upstream.temp_file_write_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.temp_file_write_size = 2 * size; } else { conf->upstream.temp_file_write_size = conf->upstream.temp_file_write_size_conf; } if (conf->upstream.temp_file_write_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_temp_file_write_size\" must be equal or bigger than " "maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf, prev->upstream.max_temp_file_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; } else { conf->upstream.max_temp_file_size = conf->upstream.max_temp_file_size_conf; } if (conf->upstream.max_temp_file_size != 0 && conf->upstream.max_temp_file_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_max_temp_file_size\" must be equal to zero to disable " "the temporary files usage or must be equal or bigger than " "maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers, prev->upstream.ignore_headers, NGX_CONF_BITMASK_SET); ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, prev->upstream.next_upstream, (NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { conf->upstream.next_upstream = NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_OFF; } if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path, prev->upstream.temp_path, &ngx_http_scgi_temp_path) != NGX_OK) { return NGX_CONF_ERROR; } #if (NGX_HTTP_CACHE) ngx_conf_merge_ptr_value(conf->upstream.cache, prev->upstream.cache, NULL); if (conf->upstream.cache && conf->upstream.cache->data == NULL) { ngx_shm_zone_t *shm_zone; shm_zone = conf->upstream.cache; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_cache\" zone \"%V\" is unknown", &shm_zone->shm.name); return NGX_CONF_ERROR; } ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, prev->upstream.cache_min_uses, 1); ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, prev->upstream.cache_use_stale, (NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_OFF)); if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) { conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_OFF; } if (conf->upstream.cache_methods == 0) { conf->upstream.cache_methods = prev->upstream.cache_methods; } conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; ngx_conf_merge_ptr_value(conf->upstream.cache_bypass, prev->upstream.cache_bypass, NULL); ngx_conf_merge_ptr_value(conf->upstream.no_cache, prev->upstream.no_cache, NULL); ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); if (conf->cache_key.value.data == NULL) { conf->cache_key = prev->cache_key; } #endif ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, prev->upstream.pass_request_body, 1); ngx_conf_merge_value(conf->upstream.intercept_errors, prev->upstream.intercept_errors, 0); hash.max_size = 512; hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "scgi_hide_headers_hash"; if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, &prev->upstream, ngx_http_scgi_hide_headers, &hash) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->upstream.upstream == NULL) { conf->upstream.upstream = prev->upstream.upstream; } if (conf->scgi_lengths == NULL) { conf->scgi_lengths = prev->scgi_lengths; conf->scgi_values = prev->scgi_values; } if (conf->upstream.upstream || conf->scgi_lengths) { clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); if (clcf->handler == NULL && clcf->lmt_excpt) { clcf->handler = ngx_http_scgi_handler; } } if (conf->params_source == NULL) { conf->flushes = prev->flushes; conf->params_len = prev->params_len; conf->params = prev->params; conf->params_source = prev->params_source; conf->headers_hash = prev->headers_hash; #if (NGX_HTTP_CACHE) if (conf->params_source == NULL) { if ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) { return NGX_CONF_OK; } /* 6 is a number of ngx_http_scgi_cache_headers entries */ conf->params_source = ngx_array_create(cf->pool, 6, sizeof(ngx_keyval_t)); if (conf->params_source == NULL) { return NGX_CONF_ERROR; } } #else if (conf->params_source == NULL) { return NGX_CONF_OK; } #endif } conf->params_len = ngx_array_create(cf->pool, 64, 1); if (conf->params_len == NULL) { return NGX_CONF_ERROR; } conf->params = ngx_array_create(cf->pool, 512, 1); if (conf->params == NULL) { return NGX_CONF_ERROR; } if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { return NGX_CONF_ERROR; } src = conf->params_source->elts; #if (NGX_HTTP_CACHE) if (conf->upstream.cache) { ngx_keyval_t *h, *s; for (h = ngx_http_scgi_cache_headers; h->key.len; h++) { for (i = 0; i < conf->params_source->nelts; i++) { if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { goto next; } } s = ngx_array_push(conf->params_source); if (s == NULL) { return NGX_CONF_ERROR; } *s = *h; src = conf->params_source->elts; next: h++; } } #endif for (i = 0; i < conf->params_source->nelts; i++) { if (src[i].key.len > sizeof("HTTP_") - 1 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) { hk = ngx_array_push(&headers_names); if (hk == NULL) { return NGX_CONF_ERROR; } hk->key.len = src[i].key.len - 5; hk->key.data = src[i].key.data + 5; hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); hk->value = (void *) 1; if (src[i].value.len == 0) { continue; } } copy = ngx_array_push_n(conf->params_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].key.len + 1; size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + 1 + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->params, size); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = src[i].key.len + 1; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); (void) ngx_cpystrn(p, src[i].key.data, src[i].key.len + 1); ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); sc.cf = cf; sc.source = &src[i].value; sc.flushes = &conf->flushes; sc.lengths = &conf->params_len; sc.values = &conf->params; if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_CONF_ERROR; } code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; } code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; conf->header_params = headers_names.nelts; hash.hash = &conf->headers_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; hash.bucket_size = 64; hash.name = "scgi_params_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
char * passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { passenger_loc_conf_t *prev = parent; passenger_loc_conf_t *conf = child; u_char *p; size_t size; uintptr_t *code; ngx_str_t *header; ngx_uint_t i, j; ngx_array_t hide_headers; ngx_str_t *prev_base_uris, *base_uri; ngx_keyval_t *src; ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; #if NGINX_VERSION_NUM < 7000 u_char *temp_path; #endif ngx_conf_merge_value(conf->enabled, prev->enabled, 0); ngx_conf_merge_value(conf->use_global_queue, prev->use_global_queue, 0); ngx_conf_merge_str_value(conf->environment, prev->environment, "production"); ngx_conf_merge_str_value(conf->spawn_method, prev->spawn_method, "smart-lv2"); if (conf->framework_spawner_idle_time == -1 && prev->framework_spawner_idle_time != -1) { conf->framework_spawner_idle_time = prev->framework_spawner_idle_time; } if (conf->app_spawner_idle_time == -1 && prev->app_spawner_idle_time != -1) { conf->app_spawner_idle_time = prev->app_spawner_idle_time; } if (prev->base_uris != NGX_CONF_UNSET_PTR) { if (conf->base_uris == NGX_CONF_UNSET_PTR) { conf->base_uris = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); if (conf->base_uris == NULL) { return NGX_CONF_ERROR; } } prev_base_uris = (ngx_str_t *) prev->base_uris->elts; for (i = 0; i < prev->base_uris->nelts; i++) { base_uri = (ngx_str_t *) ngx_array_push(conf->base_uris); if (base_uri == NULL) { return NGX_CONF_ERROR; } *base_uri = prev_base_uris[i]; } } if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { conf->upstream.store_lengths = prev->upstream.store_lengths; conf->upstream.store_values = prev->upstream.store_values; } } ngx_conf_merge_uint_value(conf->upstream.store_access, prev->upstream.store_access, 0600); ngx_conf_merge_value(conf->upstream.buffering, prev->upstream.buffering, 1); ngx_conf_merge_value(conf->upstream.ignore_client_abort, prev->upstream.ignore_client_abort, 0); ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); ngx_conf_merge_msec_value(conf->upstream.send_timeout, prev->upstream.send_timeout, 60000); ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); ngx_conf_merge_size_value(conf->upstream.send_lowat, prev->upstream.send_lowat, 0); ngx_conf_merge_size_value(conf->upstream.buffer_size, prev->upstream.buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, 8, ngx_pagesize); if (conf->upstream.bufs.num < 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "there must be at least 2 \"scgi_buffers\""); return NGX_CONF_ERROR; } size = conf->upstream.buffer_size; if (size < conf->upstream.bufs.size) { size = conf->upstream.bufs.size; } ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, prev->upstream.busy_buffers_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.busy_buffers_size = 2 * size; } else { conf->upstream.busy_buffers_size = conf->upstream.busy_buffers_size_conf; } if (conf->upstream.busy_buffers_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_busy_buffers_size\" must be equal or bigger than " "maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } if (conf->upstream.busy_buffers_size > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_busy_buffers_size\" must be less than " "the size of all \"scgi_buffers\" minus one buffer"); return NGX_CONF_ERROR; } ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf, prev->upstream.temp_file_write_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.temp_file_write_size = 2 * size; } else { conf->upstream.temp_file_write_size = conf->upstream.temp_file_write_size_conf; } if (conf->upstream.temp_file_write_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_temp_file_write_size\" must be equal or bigger than " "maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf, prev->upstream.max_temp_file_size_conf, NGX_CONF_UNSET_SIZE); if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; } else { conf->upstream.max_temp_file_size = conf->upstream.max_temp_file_size_conf; } if (conf->upstream.max_temp_file_size != 0 && conf->upstream.max_temp_file_size < size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_max_temp_file_size\" must be equal to zero to disable " "the temporary files usage or must be equal or bigger than " "maximum of the value of \"scgi_buffer_size\" and " "one of the \"scgi_buffers\""); return NGX_CONF_ERROR; } ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, prev->upstream.next_upstream, (NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { conf->upstream.next_upstream = NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_OFF; } #if NGINX_VERSION_NUM < 7000 temp_path = ngx_palloc(cf->pool, NGX_MAX_PATH); ngx_memzero(temp_path, NGX_MAX_PATH); ngx_snprintf(temp_path, NGX_MAX_PATH, "%s/webserver_private", passenger_temp_dir); ngx_conf_merge_path_value(conf->upstream.temp_path, prev->upstream.temp_path, temp_path, 1, 2, 0, ngx_garbage_collector_temp_handler, cf); conf->upstream.temp_path->name.len = ngx_strlen(conf->upstream.temp_path->name.data); #else ngx_conf_merge_path_value(cf, &conf->upstream.temp_path, prev->upstream.temp_path, &ngx_http_proxy_temp_path); #endif ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, prev->upstream.pass_request_body, 1); ngx_conf_merge_value(conf->upstream.intercept_errors, prev->upstream.intercept_errors, 0); ngx_conf_merge_str_value(conf->index, prev->index, ""); if (conf->upstream.hide_headers == NULL && conf->upstream.pass_headers == NULL) { conf->upstream.hide_headers = prev->upstream.hide_headers; conf->upstream.pass_headers = prev->upstream.pass_headers; conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash; if (conf->upstream.hide_headers_hash.buckets) { goto peers; } } else { if (conf->upstream.hide_headers == NULL) { conf->upstream.hide_headers = prev->upstream.hide_headers; } if (conf->upstream.pass_headers == NULL) { conf->upstream.pass_headers = prev->upstream.pass_headers; } } if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { return NGX_CONF_ERROR; } for (header = headers_to_hide; header->len; header++) { hk = ngx_array_push(&hide_headers); if (hk == NULL) { return NGX_CONF_ERROR; } hk->key = *header; hk->key_hash = ngx_hash_key_lc(header->data, header->len); hk->value = (void *) 1; } if (conf->upstream.hide_headers) { header = conf->upstream.hide_headers->elts; for (i = 0; i < conf->upstream.hide_headers->nelts; i++) { hk = hide_headers.elts; for (j = 0; j < hide_headers.nelts; j++) { if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) { goto exist; } } hk = ngx_array_push(&hide_headers); if (hk == NULL) { return NGX_CONF_ERROR; } hk->key = header[i]; hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len); hk->value = (void *) 1; exist: continue; } } if (conf->upstream.pass_headers) { hk = hide_headers.elts; header = conf->upstream.pass_headers->elts; for (i = 0; i < conf->upstream.pass_headers->nelts; i++) { for (j = 0; j < hide_headers.nelts; j++) { if (hk[j].key.data == NULL) { continue; } if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) { hk[j].key.data = NULL; break; } } } } hash.hash = &conf->upstream.hide_headers_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "passenger_hide_headers_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) { return NGX_CONF_ERROR; } peers: if (conf->upstream.upstream == NULL) { conf->upstream.upstream = prev->upstream.upstream; #if NGINX_VERSION_NUM < 7000 conf->upstream.schema = prev->upstream.schema; #endif } if (conf->vars_source == NULL) { conf->flushes = prev->flushes; conf->vars_len = prev->vars_len; conf->vars = prev->vars; conf->vars_source = prev->vars_source; if (conf->vars_source == NULL) { return NGX_CONF_OK; } } conf->vars_len = ngx_array_create(cf->pool, 64, 1); if (conf->vars_len == NULL) { return NGX_CONF_ERROR; } conf->vars = ngx_array_create(cf->pool, 512, 1); if (conf->vars == NULL) { return NGX_CONF_ERROR; } src = conf->vars_source->elts; for (i = 0; i < conf->vars_source->nelts; i++) { if (ngx_http_script_variables_count(&src[i].value) == 0) { copy = ngx_array_push_n(conf->vars_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].key.len; copy = ngx_array_push_n(conf->vars_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].value.len; size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + src[i].value.len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->vars, size); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = src[i].key.len + src[i].value.len; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); p = ngx_cpymem(p, src[i].key.data, src[i].key.len); ngx_memcpy(p, src[i].value.data, src[i].value.len); } else { copy = ngx_array_push_n(conf->vars_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].key.len; size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->vars, size); if (copy == NULL) { return NGX_CONF_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = src[i].key.len; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); ngx_memcpy(p, src[i].key.data, src[i].key.len); ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); sc.cf = cf; sc.source = &src[i].value; sc.flushes = &conf->flushes; sc.lengths = &conf->vars_len; sc.values = &conf->vars; if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_CONF_ERROR; } } code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; code = ngx_array_push_n(conf->vars, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; } code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_CONF_ERROR; } *code = (uintptr_t) NULL; return NGX_CONF_OK; }
static ngx_int_t filter_cache_send(ngx_http_request_t *r) { ngx_http_cache_t *c = NULL; u_char *raw,*p,*hs; int flag = 0; ngx_table_elt_t *h = NULL; ngx_str_t key,value; ngx_http_filter_cache_meta_t *meta; ngx_http_filter_cache_ctx_t *ctx = r->filter_cache; r->cached = 1; c = ctx->cache; if (c->header_start == c->body_start) { r->http_version = NGX_HTTP_VERSION_9; return ngx_http_filter_cache_send(r); } r->headers_out.content_length_n = c->length - c->body_start; /* Headers */ /* Headers that arent' in the table */ /*initialize ptrs*/ hs = raw = (u_char *)(c->buf->start + c->header_start); /* Meta data */ meta = (ngx_http_filter_cache_meta_t *)raw; raw += sizeof(ngx_http_filter_cache_meta_t); r->headers_out.status = meta->status; #if (NGX_HTTP_GZIP) r->gzip_vary = meta->gzip_vary; #endif r->headers_out.last_modified_time = meta->last_modified_time; /* ngx_memcpy((void *)(&r->headers_out.status), (void *)raw, sizeof(ngx_int_t)); */ /* raw += sizeof(ngx_int_t); */ /* Content Type */ key.data = raw; p = memchr((void *)raw, '\0', c->length - c->header_start); if ( !p ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } key.len = p - raw; raw = p + 1; r->headers_out.content_type.data = key.data; r->headers_out.content_type.len = key.len; r->headers_out.content_type_len = key.len; r->headers_out.content_type_lowcase = ngx_pnalloc(r->pool, key.len); if (r->headers_out.content_type_lowcase == NULL ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(r->headers_out.content_type_lowcase, key.data, key.len); r->headers_out.content_type_hash = ngx_hash_key_lc(key.data, key.len); /* Charset */ key.data = raw; p = memchr( (void *)raw, '\0', c->length - c->header_start - ( raw - hs )); key.len = p - raw; raw = p + 1; r->headers_out.charset.data = key.data; r->headers_out.charset.len = key.len; /* content encoding */ key.data = raw; p = memchr( (void *)raw, '\0', c->length - c->header_start - ( raw - hs )); key.len = p - raw; if(key.len) { /*copied from ngx_http_gzip_static_module.c */ h = ngx_list_push(&r->headers_out.headers); if ( h == NULL ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_str_set(&h->key, "Content-Encoding"); h->hash = 1; h->value.len = key.len; h->value.data = key.data; r->headers_out.content_encoding = h; r->ignore_content_encoding = 1; } raw = p + 1; /* last-modified*/ key.data = raw; p = memchr( (void *)raw, '\0', c->length - c->header_start - ( raw - hs )); key.len = p - raw; if(key.len) { /*copied from ngx_http_gzip_static_module.c */ h = ngx_list_push(&r->headers_out.headers); if ( h == NULL ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_str_set(&h->key, "Last-Modified"); h->hash = 1; h->value.len = key.len; h->value.data = key.data; r->headers_out.last_modified = h; } raw = p + 1; /* Stuff from the Table */ key.data = raw; key.len = 0; value.data = NULL; value.len = 0; while( raw < c->buf->start + c->body_start ) { if ( *raw == '\0' ) { if ( flag == 0 ) { flag = 1; key.len = raw - key.data; value.data = raw + 1; } else { flag = 0; value.len = raw - value.data; /* all this crap pushes a header */ h = ngx_list_push(&r->headers_out.headers); if ( h == NULL ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->key.len = key.len; h->key.data = key.data; h->hash = ngx_hash_key_lc(key.data, key.len); h->value.len = value.len; h->value.data = value.data; if((h->lowcase_key = ngx_pnalloc(r->pool, h->key.len +1)) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); key.data = raw + 1; } } raw++; } return ngx_http_filter_cache_send(r); }
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; }
/* ** This function sets up handlers for ACCESS_PHASE, ** and will call the hashtable creation function ** (whitelist aggregation) */ static ngx_int_t ngx_http_dummy_init(ngx_conf_t *cf) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf; ngx_http_dummy_main_conf_t *main_cf; ngx_http_dummy_loc_conf_t **loc_cf; unsigned int i; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (cmcf == NULL || main_cf == NULL) return (NGX_ERROR); /*LCOV_EXCL_LINE*/ /* Register for access phase */ h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); if (h == NULL) return (NGX_ERROR); /*LCOV_EXCL_LINE*/ *h = ngx_http_dummy_access_handler; /* Go with each locations registred in the srv_conf. */ loc_cf = main_cf->locations->elts; for (i = 0; i < main_cf->locations->nelts; i++) { if (loc_cf[i]->enabled && (!loc_cf[i]->denied_url || loc_cf[i]->denied_url->len <= 0)) { /* LCOV_EXCL_START */ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Missing DeniedURL, abort."); return (NGX_ERROR); /* LCOV_EXCL_STOP */ } loc_cf[i]->flag_enable_h = ngx_hash_key_lc((u_char *)RT_ENABLE, strlen(RT_ENABLE)); loc_cf[i]->flag_learning_h = ngx_hash_key_lc((u_char *)RT_LEARNING, strlen(RT_LEARNING)); loc_cf[i]->flag_post_action_h = ngx_hash_key_lc((u_char *)RT_POST_ACTION, strlen(RT_POST_ACTION)); loc_cf[i]->flag_extensive_log_h = ngx_hash_key_lc((u_char *)RT_EXTENSIVE_LOG, strlen(RT_EXTENSIVE_LOG)); loc_cf[i]->flag_libinjection_xss_h = ngx_hash_key_lc((u_char *)RT_LIBINJECTION_XSS, strlen(RT_LIBINJECTION_XSS)); loc_cf[i]->flag_libinjection_sql_h = ngx_hash_key_lc((u_char *)RT_LIBINJECTION_SQL, strlen(RT_LIBINJECTION_SQL)); if(ngx_http_dummy_create_hashtables_n(loc_cf[i], cf) != NGX_OK) { /* LCOV_EXCL_START */ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "WhiteList Hash building failed"); return (NGX_ERROR); /* LCOV_EXCL_STOP */ } } /* initialize prng (used for fragmented logs) */ srandom(time(0) * getpid()); /* ** initalise internal rules for libinjection sqli/xss ** (needs proper special scores) */ nx_int__libinject_sql = ngx_pcalloc(cf->pool, sizeof(ngx_http_rule_t)); nx_int__libinject_xss = ngx_pcalloc(cf->pool, sizeof(ngx_http_rule_t)); if (!nx_int__libinject_xss || !nx_int__libinject_sql) return (NGX_ERROR); nx_int__libinject_sql->sscores = ngx_array_create(cf->pool, 2, sizeof(ngx_http_special_score_t)); nx_int__libinject_xss->sscores = ngx_array_create(cf->pool, 2, sizeof(ngx_http_special_score_t)); if (!nx_int__libinject_sql->sscores || !nx_int__libinject_xss->sscores ) return (NGX_ERROR); /* LCOV_EXCL_LINE */ /* internal ID sqli - 17*/ nx_int__libinject_sql->rule_id = 17; /* internal ID xss - 18*/ nx_int__libinject_xss->rule_id = 18; /* libinjection sqli/xss - special score init */ ngx_http_special_score_t *libjct_sql = ngx_array_push(nx_int__libinject_sql->sscores); ngx_http_special_score_t *libjct_xss = ngx_array_push(nx_int__libinject_xss->sscores); if (!libjct_sql || !libjct_xss) return (NGX_ERROR); /* LCOV_EXCL_LINE */ libjct_sql->sc_tag = ngx_pcalloc(cf->pool, sizeof(ngx_str_t)); libjct_xss->sc_tag = ngx_pcalloc(cf->pool, sizeof(ngx_str_t)); if (!libjct_sql->sc_tag || !libjct_xss->sc_tag) return (NGX_ERROR); /* LCOV_EXCL_LINE */ libjct_sql->sc_tag->data = ngx_pcalloc(cf->pool, 18 /* LIBINJECTION_SQL */); libjct_xss->sc_tag->data = ngx_pcalloc(cf->pool, 18 /* LIBINJECTION_XSS */); if (!libjct_sql->sc_tag->data || !libjct_xss->sc_tag->data) return (NGX_ERROR); /* LCOV_EXCL_LINE */ strncpy((char *)libjct_sql->sc_tag->data, (char *)"$LIBINJECTION_SQL", 17); strncpy((char *)libjct_xss->sc_tag->data, (char *)"$LIBINJECTION_XSS", 17); libjct_xss->sc_tag->len = 17; libjct_sql->sc_tag->len = 17; libjct_sql->sc_score = 8; libjct_xss->sc_score = 8; return (NGX_OK); }
static ngx_int_t merge_headers(ngx_conf_t *cf, passenger_loc_conf_t *conf, passenger_loc_conf_t *prev) { u_char *p; size_t size; uintptr_t *code; ngx_uint_t i; ngx_array_t headers_names, headers_merged; ngx_keyval_t *src, *s; ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_script_compile_t sc; ngx_http_script_copy_code_t *copy; if (conf->headers_source == NULL) { conf->flushes = prev->flushes; conf->headers_set_len = prev->headers_set_len; conf->headers_set = prev->headers_set; conf->headers_set_hash = prev->headers_set_hash; conf->headers_source = prev->headers_source; } if (conf->headers_set_hash.buckets #if (NGX_HTTP_CACHE) #if NGINX_VERSION_NUM >= 1007009 && ((conf->upstream_config.cache == NGX_CONF_UNSET) == (prev->upstream_config.cache == NGX_CONF_UNSET)) #else && ((conf->upstream_config.cache == NGX_CONF_UNSET_PTR) == (prev->upstream_config.cache == NGX_CONF_UNSET_PTR)) #endif #endif ) { return NGX_OK; } if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { return NGX_ERROR; } if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) != NGX_OK) { return NGX_ERROR; } if (conf->headers_source == NULL) { conf->headers_source = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t)); if (conf->headers_source == NULL) { return NGX_ERROR; } } conf->headers_set_len = ngx_array_create(cf->pool, 64, 1); if (conf->headers_set_len == NULL) { return NGX_ERROR; } conf->headers_set = ngx_array_create(cf->pool, 512, 1); if (conf->headers_set == NULL) { return NGX_ERROR; } src = conf->headers_source->elts; for (i = 0; i < conf->headers_source->nelts; i++) { s = ngx_array_push(&headers_merged); if (s == NULL) { return NGX_ERROR; } *s = src[i]; } src = headers_merged.elts; for (i = 0; i < headers_merged.nelts; i++) { hk = ngx_array_push(&headers_names); if (hk == NULL) { return NGX_ERROR; } hk->key = src[i].key; hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len); hk->value = (void *) 1; if (src[i].value.len == 0) { continue; } if (ngx_http_script_variables_count(&src[i].value) == 0) { copy = ngx_array_push_n(conf->headers_set_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].key.len + sizeof(": ") - 1 + src[i].value.len + sizeof(CRLF) - 1; size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + sizeof(": ") - 1 + src[i].value.len + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->headers_set, size); if (copy == NULL) { return NGX_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = src[i].key.len + sizeof(": ") - 1 + src[i].value.len + sizeof(CRLF) - 1; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); p = ngx_cpymem(p, src[i].key.data, src[i].key.len); *p++ = ':'; *p++ = ' '; p = ngx_cpymem(p, src[i].value.data, src[i].value.len); *p++ = CR; *p = LF; } else { copy = ngx_array_push_n(conf->headers_set_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = src[i].key.len + sizeof(": ") - 1; size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->headers_set, size); if (copy == NULL) { return NGX_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = src[i].key.len + sizeof(": ") - 1; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); p = ngx_cpymem(p, src[i].key.data, src[i].key.len); *p++ = ':'; *p = ' '; ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); sc.cf = cf; sc.source = &src[i].value; sc.flushes = &conf->flushes; sc.lengths = &conf->headers_set_len; sc.values = &conf->headers_set; if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_ERROR; } copy = ngx_array_push_n(conf->headers_set_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; copy->len = sizeof(CRLF) - 1; size = (sizeof(ngx_http_script_copy_code_t) + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->headers_set, size); if (copy == NULL) { return NGX_ERROR; } copy->code = ngx_http_script_copy_code; copy->len = sizeof(CRLF) - 1; p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); *p++ = CR; *p = LF; } code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_ERROR; } *code = (uintptr_t) NULL; code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t)); if (code == NULL) { return NGX_ERROR; } *code = (uintptr_t) NULL; } code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); if (code == NULL) { return NGX_ERROR; } *code = (uintptr_t) NULL; hash.hash = &conf->headers_set_hash; hash.key = ngx_hash_key_lc; hash.max_size = conf->headers_hash_max_size; hash.bucket_size = conf->headers_hash_bucket_size; hash.name = "passenger_headers_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); }
ngx_int_t ngx_http_set_misc_set_hashed_upstream(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v, void *data) { ngx_str_t **u; ndk_upstream_list_t *ul = data; ngx_str_t ulname; ngx_uint_t hash, index; ngx_http_variable_value_t *key; if (ul == NULL) { ulname.data = v->data; ulname.len = v->len; dd("ulname: %.*s", (int) ulname.len, ulname.data); ul = ndk_get_upstream_list(ndk_http_get_main_conf(r), ulname.data, ulname.len); if (ul == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "set_hashed_upstream: upstream list \"%V\" " "not defined yet", &ulname); return NGX_ERROR; } key = v + 1; } else { key = v; } if (ul->nelts == 0) { res->data = NULL; res->len = 0; return NGX_OK; } u = ul->elts; dd("upstream list: %d upstreams found", (int) ul->nelts); if (ul->nelts == 1) { dd("only one upstream found in the list"); res->data = u[0]->data; res->len = u[0]->len; return NGX_OK; } dd("key: \"%.*s\"", key->len, key->data); hash = ngx_hash_key_lc(key->data, key->len); index = ngx_http_set_misc_apply_distribution(r->connection->log, hash, ul, ngx_http_set_misc_distribution_modula); res->data = u[index]->data; res->len = u[index]->len; return NGX_OK; }