ngx_int_t ngx_lua_content_by_file_handler(ngx_http_request_t* r) { ngx_lua_main_conf_t* pmainconf; ngx_lua_loc_conf_t* plocconf; ngx_int_t rc; int top; ngx_str_t src_path; u_char new_path[PATH_MAX]; dbg("ngx_lua_content_by_file_handler\n"); pmainconf = ngx_http_get_module_main_conf(r, ngx_lua_module); plocconf = ngx_http_get_module_loc_conf(r, ngx_lua_module); // complex path if (ngx_http_complex_value(r, &plocconf->lua_content_file, &src_path) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "ngx_lua_content_handler: ngx_http_complex_value error"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } // new path with\0 memcpy(new_path, src_path.data, src_path.len); new_path[src_path.len] = 0; src_path.data = new_path; // register ngx.req.args top = lua_gettop(pmainconf->lua); ngx_lua_module_set_req_obj(pmainconf->lua, r); ngx_lua_module_parse_args(r->pool, r->args.data, r->args.len, pmainconf->lua); if (src_path.len) { code_cache_node_t* ptr; char path[PATH_MAX]; ngx_str_t strPath; ngx_str_t code; ngx_str_null(&strPath); // file exists if (access((const char*)src_path.data, 0) == -1) { lua_pushfstring(pmainconf->lua, "%s doesn't exist", src_path.data); faild(NGX_HTTP_NOT_FOUND); } // get realpath if (realpath((const char*)src_path.data, path) == NULL) { lua_pushfstring(pmainconf->lua, "can't get realpath with %s", src_path.data); faild(NGX_HTTP_INTERNAL_SERVER_ERROR); } ngx_pfree(r->pool, src_path.data); // register ngx.scp.path ngx_lua_module_get_scp(pmainconf->lua); lua_pushstring(pmainconf->lua, "path"); lua_pushstring(pmainconf->lua, path); lua_settable(pmainconf->lua, -3); lua_pop(pmainconf->lua, 2); // lookup cache strPath.data = (u_char*)path; strPath.len = strlen(path); ptr = ngx_lua_code_cache_key_exists(pmainconf->cache_table, strPath); ngx_lua_module_replace_global(pmainconf->lua); if (ptr == NULL) // doesn't exist { code = ngx_lua_code_cache_load(strPath); if (code.data == NULL) { lua_pushstring(pmainconf->lua, "out of memory"); faild(NGX_HTTP_INTERNAL_SERVER_ERROR); } if (pmainconf->enable_code_cache) { ngx_str_t cache; dbg("code uncached\n"); if (ngx_lua_module_code_to_chunk(pmainconf->lua, code.data, code.len, &cache)) { faild(NGX_HTTP_INTERNAL_SERVER_ERROR); } ptr = ngx_lua_code_cache_node_new(strPath, cache); if (ptr == NULL) { lua_pushstring(pmainconf->lua, "out of memory"); faild(NGX_HTTP_INTERNAL_SERVER_ERROR); } ngx_pfree(ngx_cycle->pool, code.data); code = ptr->code; ngx_lua_core_hash_table_insert_notfind(pmainconf->cache_table, ptr); rc = ngx_lua_content_call_chunk(r, pmainconf->lua, &code); } else rc = ngx_lua_content_call_code(r, pmainconf->lua, code.data, code.len); } else { dbg("code cached\n"); code = ptr->code; rc = ngx_lua_content_call_chunk(r, pmainconf->lua, &code); } ngx_pfree(ngx_cycle->pool, code.data); if (rc != NGX_OK) return rc; rc = ngx_lua_content_send(r, pmainconf->lua); if (rc != NGX_OK) return rc; } if (top != lua_gettop(pmainconf->lua)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "ngx_lua_content_by_file_handler: error lua stack"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } return NGX_OK; }
//expires配置解析,会触发创建设置r->headers_out.expires r->headers_out.cache_control static ngx_int_t //expires xx配置存储函数为ngx_http_headers_expires,真正组包生效函数为ngx_http_set_expires ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { char *err; size_t len; time_t now, expires_time, max_age; ngx_str_t value; ngx_int_t rc; ngx_uint_t i; ngx_table_elt_t *e, *cc, **ccp; ngx_http_expires_t expires; expires = conf->expires; expires_time = conf->expires_time; if (conf->expires_value != NULL) { //说明expires配置的是变量类型 if (ngx_http_complex_value(r, conf->expires_value, &value) != NGX_OK) { return NGX_ERROR; } rc = ngx_http_parse_expires(&value, &expires, &expires_time, &err); if (rc != NGX_OK) { return NGX_OK; } if (expires == NGX_HTTP_EXPIRES_OFF) { return NGX_OK; } } e = r->headers_out.expires; if (e == NULL) { e = ngx_list_push(&r->headers_out.headers); if (e == NULL) { return NGX_ERROR; } r->headers_out.expires = e; e->hash = 1; ngx_str_set(&e->key, "Expires"); } len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT"); e->value.len = len - 1; ccp = r->headers_out.cache_control.elts; if (ccp == NULL) { if (ngx_array_init(&r->headers_out.cache_control, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK) { return NGX_ERROR; } ccp = ngx_array_push(&r->headers_out.cache_control); if (ccp == NULL) { return NGX_ERROR; } cc = ngx_list_push(&r->headers_out.headers); if (cc == NULL) { return NGX_ERROR; } cc->hash = 1; ngx_str_set(&cc->key, "Cache-Control"); *ccp = cc; } else { for (i = 1; i < r->headers_out.cache_control.nelts; i++) { ccp[i]->hash = 0; } cc = ccp[0]; } if (expires == NGX_HTTP_EXPIRES_EPOCH) { e->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT"; ngx_str_set(&cc->value, "no-cache");//设置r->headers_out.cache_control return NGX_OK; } if (expires == NGX_HTTP_EXPIRES_MAX) { e->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT"; /* 10 years */ ngx_str_set(&cc->value, "max-age=315360000");//设置r->headers_out.cache_control return NGX_OK; } e->value.data = ngx_pnalloc(r->pool, len); if (e->value.data == NULL) { return NGX_ERROR; } if (expires_time == 0 && expires != NGX_HTTP_EXPIRES_DAILY) { ngx_memcpy(e->value.data, ngx_cached_http_time.data, ngx_cached_http_time.len + 1); ngx_str_set(&cc->value, "max-age=0");//设置r->headers_out.cache_control return NGX_OK; } now = ngx_time(); if (expires == NGX_HTTP_EXPIRES_DAILY) { expires_time = ngx_next_time(expires_time); max_age = expires_time - now; } else if (expires == NGX_HTTP_EXPIRES_ACCESS || r->headers_out.last_modified_time == -1) { max_age = expires_time; expires_time += now; } else { expires_time += r->headers_out.last_modified_time; max_age = expires_time - now; } ngx_http_time(e->value.data, expires_time); if (conf->expires_time < 0 || max_age < 0) { ngx_str_set(&cc->value, "no-cache");//设置r->headers_out.cache_control return NGX_OK; } //设置r->headers_out.cache_control cc->value.data = ngx_pnalloc(r->pool, sizeof("max-age=") + NGX_TIME_T_LEN + 1); if (cc->value.data == NULL) { return NGX_ERROR; } cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", max_age) - cc->value.data; return NGX_OK; }
static ngx_int_t ngx_http_vod_hls_handle_index_playlist( ngx_http_vod_submodule_context_t* submodule_context, ngx_str_t* response, ngx_str_t* content_type) { ngx_http_vod_loc_conf_t* conf = submodule_context->conf; hls_encryption_params_t encryption_params; ngx_str_t segments_base_url = ngx_null_string; ngx_str_t base_url = ngx_null_string; vod_status_t rc; u_char iv[AES_BLOCK_SIZE]; if (conf->hls.absolute_index_urls) { rc = ngx_http_vod_get_base_url(submodule_context->r, conf->base_url, &submodule_context->r->uri, &base_url); if (rc != NGX_OK) { return rc; } if (conf->segments_base_url != NULL) { rc = ngx_http_vod_get_base_url( submodule_context->r, conf->segments_base_url, &submodule_context->r->uri, &segments_base_url); if (rc != NGX_OK) { return rc; } } else { segments_base_url = base_url; } } ngx_http_vod_hls_init_encryption_params(&encryption_params, submodule_context, iv); if (encryption_params.type != HLS_ENC_NONE) { if (conf->hls.encryption_key_uri != NULL) { if (ngx_http_complex_value( submodule_context->r, conf->hls.encryption_key_uri, &encryption_params.key_uri) != NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0, "ngx_http_vod_hls_handle_index_playlist: ngx_http_complex_value failed"); return NGX_ERROR; } } else { encryption_params.key_uri.len = 0; } } rc = m3u8_builder_build_index_playlist( &submodule_context->request_context, &conf->hls.m3u8_config, &base_url, &segments_base_url, &submodule_context->request_params, &encryption_params, &submodule_context->media_set, response); if (rc != VOD_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0, "ngx_http_vod_hls_handle_index_playlist: m3u8_builder_build_index_playlist failed %i", rc); return ngx_http_vod_status_to_ngx_error(rc); } content_type->data = m3u8_content_type; content_type->len = sizeof(m3u8_content_type) - 1; return NGX_OK; }
static ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r) { off_t offset; ssize_t n; ngx_fd_t fd; ngx_int_t rc; ngx_err_t err; ngx_str_t pwd, realm, user_file; ngx_uint_t i, level, login, left, passwd; ngx_file_t file; ngx_http_auth_basic_ctx_t *ctx; ngx_http_auth_basic_loc_conf_t *alcf; u_char buf[NGX_HTTP_AUTH_BUF_SIZE]; enum { sw_login, sw_passwd, sw_skip } state; alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module); if (alcf->realm == NULL || alcf->user_file.value.data == NULL) { return NGX_DECLINED; } if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) { return NGX_ERROR; } if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module); if (ctx) { return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd, &realm); } rc = ngx_http_auth_basic_user(r); if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "no user/password was provided for basic authentication"); return ngx_http_auth_basic_set_realm(r, &realm); } if (rc == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) { return NGX_ERROR; } fd = ngx_open_file(user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { err = ngx_errno; if (err == NGX_ENOENT) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, r->connection->log, err, ngx_open_file_n " \"%s\" failed", user_file.data); return rc; } ngx_memzero(&file, sizeof(ngx_file_t)); file.fd = fd; file.name = user_file; file.log = r->connection->log; state = sw_login; passwd = 0; login = 0; left = 0; offset = 0; for ( ;; ) { i = left; n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left, offset); if (n == NGX_ERROR) { ngx_http_auth_basic_close(&file); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (n == 0) { break; } for (i = left; i < left + n; i++) { switch (state) { case sw_login: if (login == 0) { if (buf[i] == '#' || buf[i] == CR) { state = sw_skip; break; } if (buf[i] == LF) { break; } } if (buf[i] != r->headers_in.user.data[login]) { state = sw_skip; break; } if (login == r->headers_in.user.len) { state = sw_passwd; passwd = i + 1; } login++; break; case sw_passwd: if (buf[i] == LF || buf[i] == CR || buf[i] == ':') { buf[i] = '\0'; ngx_http_auth_basic_close(&file); pwd.len = i - passwd; pwd.data = &buf[passwd]; return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm); } break; case sw_skip: if (buf[i] == LF) { state = sw_login; login = 0; } break; } } if (state == sw_passwd) { left = left + n - passwd; ngx_memmove(buf, &buf[passwd], left); passwd = 0; } else { left = 0; } offset += n; } ngx_http_auth_basic_close(&file); if (state == sw_passwd) { pwd.len = i - passwd; pwd.data = ngx_pnalloc(r->pool, pwd.len + 1); if (pwd.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1); return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm); } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "user \"%V\" was not found in \"%V\"", &r->headers_in.user, &user_file); return ngx_http_auth_basic_set_realm(r, &realm); }
static ngx_int_t ngx_http_srcache_fetch_subrequest(ngx_http_request_t *r, ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_ctx_t *ctx) { ngx_http_srcache_ctx_t *sr_ctx; ngx_http_post_subrequest_t *psr; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_request_t *sr; ngx_int_t rc; ngx_http_srcache_parsed_request_t *parsed_sr; dd_enter(); parsed_sr = ngx_palloc(r->pool, sizeof(ngx_http_srcache_parsed_request_t)); if (parsed_sr == NULL) { return NGX_ERROR; } if (conf->fetch == NULL) { return NGX_ERROR; } parsed_sr->method = conf->fetch->method; parsed_sr->method_name = conf->fetch->method_name; parsed_sr->request_body = NULL; parsed_sr->content_length_n = -1; if (ngx_http_complex_value(r, &conf->fetch->location, &parsed_sr->location) != NGX_OK) { return NGX_ERROR; } if (parsed_sr->location.len == 0) { return NGX_ERROR; } if (ngx_http_complex_value(r, &conf->fetch->args, &parsed_sr->args) != NGX_OK) { return NGX_ERROR; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &parsed_sr->location, &args, &flags) != NGX_OK) { return NGX_ERROR; } if (args.len > 0 && parsed_sr->args.len == 0) { parsed_sr->args = args; } sr_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_ctx_t)); if (sr_ctx == NULL) { return NGX_ERROR; } sr_ctx->in_fetch_subrequest = 1; psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } psr->handler = ngx_http_srcache_fetch_post_subrequest; psr->data = sr_ctx; dd("firing the fetch subrequest"); dd("fetch location: %.*s", (int) parsed_sr->location.len, parsed_sr->location.data); dd("fetch args: %.*s", (int) parsed_sr->args.len, parsed_sr->args.data); rc = ngx_http_subrequest(r, &parsed_sr->location, &parsed_sr->args, &sr, psr, flags); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_srcache_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return NGX_ERROR; } ngx_http_set_ctx(sr, sr_ctx, ngx_http_srcache_filter_module); ctx->issued_fetch_subrequest = 1; return NGX_OK; }
static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) { ngx_int_t overwrite; ngx_str_t uri, args; ngx_table_elt_t *location; ngx_http_core_loc_conf_t *clcf; overwrite = err_page->overwrite; if (overwrite && overwrite != NGX_HTTP_OK) { r->expect_tested = 1; } if (overwrite >= 0) { r->err_status = overwrite; } if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) { return NGX_ERROR; } if (uri.len && uri.data[0] == '/') { if (err_page->value.lengths) { ngx_http_split_args(r, &uri, &args); } else { args = err_page->args; } if (r->method != NGX_HTTP_HEAD) { r->method = NGX_HTTP_GET; r->method_name = ngx_http_get_name; } return ngx_http_internal_redirect(r, &uri, &args); } if (uri.len && uri.data[0] == '@') { return ngx_http_named_location(r, &uri); } location = ngx_list_push(&r->headers_out.headers); if (location == NULL) { return NGX_ERROR; } if (overwrite != NGX_HTTP_MOVED_PERMANENTLY && overwrite != NGX_HTTP_MOVED_TEMPORARILY && overwrite != NGX_HTTP_SEE_OTHER && overwrite != NGX_HTTP_TEMPORARY_REDIRECT) { r->err_status = NGX_HTTP_MOVED_TEMPORARILY; } location->hash = 1; ngx_str_set(&location->key, "Location"); location->value = uri; ngx_http_clear_location(r); r->headers_out.location = location; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->msie_refresh && r->headers_in.msie) { return ngx_http_send_refresh(r); } return ngx_http_send_special_response(r, clcf, r->err_status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX); }
static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_buf_t *buf) { static ngx_str_t nopublishing = ngx_string("Publishing not allowed."); static ngx_str_t POST_REQUEST_STRING = {4, (u_char *)"POST "}; if(!fsub->sub.cf->pub.websocket) { return websocket_send_close_frame(fsub, CLOSE_POLICY_VIOLATION, &nopublishing); } #if (NGX_DEBUG_POOL) ERR("ws request pool size: %V", ngx_http_debug_pool_str(fsub->sub.request->pool)); #endif ngx_http_complex_value_t *publisher_upstream_request_url_ccv; publisher_upstream_request_url_ccv = fsub->sub.cf->publisher_upstream_request_url; if(publisher_upstream_request_url_ccv == NULL) { websocket_publish_continue(fsub, buf); } else { nchan_pub_upstream_stuff_t *psr_stuff; ngx_http_post_subrequest_t *psr; nchan_pub_upstream_data_t *psrd; ngx_http_request_t *r = fsub->sub.request; ngx_http_request_t *sr; ngx_http_request_body_t *fakebody; ngx_chain_t *fakebody_chain; ngx_buf_t *fakebody_buf; size_t sz; if(!fsub->upstream_stuff) { if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) { ERR("can't allocate memory for publisher auth subrequest"); websocket_respond_status(&fsub->sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL); return NGX_ERROR; } fsub->upstream_stuff = psr_stuff; psr = &psr_stuff->psr; psr->data = &psr_stuff->psr_data; psr->handler = websocket_publisher_upstream_handler; psr_stuff->psr_data.fsub = fsub; psr_stuff->psr_data.tmp_pool = NULL; ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &psr_stuff->psr_data.upstream_request_url); } psrd = &fsub->upstream_stuff->psr_data; psr = &fsub->upstream_stuff->psr; if(psrd->tmp_pool) { //previous upstream request's pool ngx_destroy_pool(psrd->tmp_pool); psrd->tmp_pool = NULL; } psrd->buf = *buf; psrd->original_pool = r->pool; psrd->original_cleanup = r->cleanup; r->cleanup = NULL; psrd->tmp_pool = ngx_create_pool(NCHAN_WS_UPSTREAM_TMP_POOL_SIZE, r->connection->log); r->pool = psrd->tmp_pool; //ERR("request %p tmp pool %p", r, r->pool); fakebody = ngx_pcalloc(r->pool, sizeof(*fakebody)); if(ngx_buf_size(buf) > 0) { fakebody_chain = ngx_palloc(r->pool, sizeof(*fakebody_chain)); fakebody_buf = ngx_palloc(r->pool, sizeof(*fakebody_buf)); fakebody->bufs = fakebody_chain; fakebody_chain->next = NULL; fakebody_chain->buf = fakebody_buf; init_msg_buf(fakebody_buf); //just copy the buffer contents. it's inefficient but I don't care at the moment. //this can and should be optimized later sz = ngx_buf_size(buf); fakebody_buf->start = ngx_palloc(r->pool, sz); //huuh? ngx_memcpy(fakebody_buf->start, buf->start, sz); fakebody_buf->end = fakebody_buf->start + sz; fakebody_buf->pos = fakebody_buf->start; fakebody_buf->last = fakebody_buf->end; } else { sz = 0; } ngx_http_subrequest(r, &psrd->upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY); nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, fakebody, sz, NULL); /* //http request sudden close cleanup if((psrd->cln = ngx_http_cleanup_add(sr, 0)) == NULL) { ERR("Unable to add request cleanup for websocket upstream request"); return NGX_ERROR; } psrd->cln->data = fsub; psrd->cln->handler = (ngx_http_cleanup_pt )sudden_upstream_request_abort_handler; */ } return NGX_OK; }
//获取secure_link配置的值,同时与secure_link_md5运算的值进行比较,相同则置$secure_link变量为1,不同则置0 static ngx_int_t ngx_http_secure_link_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *p, *last; ngx_str_t val, hash; time_t expires; ngx_md5_t md5; ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; u_char hash_buf[16], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); if (conf->secret.data) { return ngx_http_secure_link_old_variable(r, conf, v, data); } if (conf->variable == NULL || conf->md5 == NULL) { goto not_found; } if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link: \"%V\"", &val); last = val.data + val.len; p = ngx_strlchr(val.data, last, ','); ////secure_link md5_str, 120配置, expires = 0; if (p) { val.len = p++ - val.data; //这时候,val.len=md5_str的字符串长度了,不包括后面的,120字符串 expires = ngx_atotm(p, last - p); //获取//secure_link md5_str, 120配置中的120 if (expires <= 0) { goto not_found; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module); ctx->expires.len = last - p; ctx->expires.data = p; } //这时候,val.len=md5_str的字符串长度了,不包括后面的,120字符串 if (val.len > 24) {//secure_link配置解析出的字符串不能超过24个字符 ?????? 为什么呢 goto not_found; } hash.len = 16; hash.data = hash_buf; //把secure_link md5_str, 120配置中的md5_str字符串进行base64解密decode运算后的值存到这里面 if (ngx_decode_base64url(&hash, &val) != NGX_OK) { goto not_found; } if (hash.len != 16) { goto not_found; } //解析secure_link_md5 $the_uri_you_want_to_hashed_by_md5配置的字符串 if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link md5: \"%V\"", &val); //echo -n 'ttlsa.com/download/nginx-1.9.2.rar1452130593' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = ngx_md5_init(&md5); ngx_md5_update(&md5, val.data, val.len); ngx_md5_final(md5_buf, &md5); if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) { //比较判断是否一致 goto not_found; } //设置v变量对应的值为0或者1 v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1"); v->len = 1; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }
static ngx_int_t ngx_http_trailers_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_str_t value; ngx_uint_t i, safe_status; ngx_chain_t *cl; ngx_table_elt_t *t; ngx_http_header_val_t *h; ngx_http_headers_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module); if (in == NULL || conf->trailers == NULL || !r->expect_trailers || r->header_only) { return ngx_http_next_body_filter(r, in); } for (cl = in; cl; cl = cl->next) { if (cl->buf->last_buf) { break; } } if (cl == NULL) { return ngx_http_next_body_filter(r, in); } switch (r->headers_out.status) { case NGX_HTTP_OK: case NGX_HTTP_CREATED: case NGX_HTTP_NO_CONTENT: case NGX_HTTP_PARTIAL_CONTENT: case NGX_HTTP_MOVED_PERMANENTLY: case NGX_HTTP_MOVED_TEMPORARILY: case NGX_HTTP_SEE_OTHER: case NGX_HTTP_NOT_MODIFIED: case NGX_HTTP_TEMPORARY_REDIRECT: case NGX_HTTP_PERMANENT_REDIRECT: safe_status = 1; break; default: safe_status = 0; break; } h = conf->trailers->elts; for (i = 0; i < conf->trailers->nelts; i++) { if (!safe_status && !h[i].always) { continue; } if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) { return NGX_ERROR; } if (value.len) { t = ngx_list_push(&r->headers_out.trailers); if (t == NULL) { return NGX_ERROR; } t->key = h[i].key; t->value = value; t->hash = 1; } } return ngx_http_next_body_filter(r, in); }
/** * Content handler. * * @param r * Request structure pointer * @return * Response status */ static ngx_int_t ngx_http_unzip_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_chain_t out; ngx_str_t unzip_filename; ngx_str_t unzip_extract; struct zip *zip_source; struct zip_stat zip_st; struct zip_file *file_in_zip; int err = 0; char *unzipfile_path; char *unzipextract_path; unsigned char *zip_content; unsigned int zip_read_bytes; ngx_http_unzip_loc_conf_t *unzip_config; unzip_config = ngx_http_get_module_loc_conf(r, ngx_http_unzip_module); /* let's try to get file_in_unzip_archivefile and file_in_unzip_extract from nginx configuration */ if (ngx_http_complex_value(r, unzip_config->file_in_unzip_archivefile, &unzip_filename) != NGX_OK || ngx_http_complex_value(r, unzip_config->file_in_unzip_extract, &unzip_extract) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to read unzip module configuration settings."); return NGX_ERROR; } /* we're supporting just GET and HEAD requests */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Only GET and HEAD requests are supported by the unzip module."); return NGX_HTTP_NOT_ALLOWED; } /* fill path variables with 0 as ngx_string_t doesn't terminate string with 0 */ unzipfile_path = malloc(unzip_filename.len+1); if (unzipfile_path == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate buffer."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } unzipextract_path = malloc(unzip_extract.len+1); if (unzipextract_path == NULL) { free(unzipfile_path); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate buffer."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } memset(unzipfile_path, 0, unzip_filename.len+1); memset(unzipextract_path, 0, unzip_extract.len+1); /* get path variables terminated with 0 */ strncpy(unzipfile_path, (char *)unzip_filename.data, unzip_filename.len); strncpy(unzipextract_path, (char *)unzip_extract.data, unzip_extract.len); /* try to open archive (zip) file */ if (!(zip_source = zip_open(unzipfile_path, 0, &err))) { free(unzipfile_path); free(unzipextract_path); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s : no such archive file.", unzipfile_path); return NGX_HTTP_NOT_FOUND; } /* initialize structure */ zip_stat_init(&zip_st); /* let's check what's the size of a file. return 404 if we can't stat file inside archive */ if (0 != zip_stat(zip_source, unzipextract_path, 0, &zip_st)) { free(unzipfile_path); free(unzipextract_path); zip_close(zip_source); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no file %s inside %s archive.", unzipextract_path, unzipfile_path); return NGX_HTTP_NOT_FOUND; } /* allocate buffer for the file content */ if (!(zip_content = ngx_palloc(r->pool, zip_st.size))) { free(unzipfile_path); free(unzipextract_path); zip_close(zip_source); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer memory."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* * try to open a file that we want - if not return 500 as we know that the file is there (making zip_stat before) * so let's return 500. */ if (!(file_in_zip = zip_fopen(zip_source, unzipextract_path, 0))) { free(unzipfile_path); free(unzipextract_path); zip_close(zip_source); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open %s from %s archive (corrupted?).", unzipextract_path, unzipfile_path); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* * let's get file content and check if we got all * we're expecting to get zip_st.size bytes so return 500 if we get something else. */ if (!(zip_read_bytes = zip_fread(file_in_zip, zip_content, zip_st.size)) || zip_read_bytes != zip_st.size) { free(unzipfile_path); free(unzipextract_path); zip_fclose(file_in_zip); zip_close(zip_source); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't get %d bytes of %s from %s archive (corrupted?).", zip_st.size, unzipextract_path, unzipfile_path); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* close both files */ zip_fclose(file_in_zip); zip_close(zip_source); /* let's clean */ free(unzipfile_path); free(unzipextract_path); /* set the content-type header. */ if (ngx_http_set_content_type(r) != NGX_OK) { r->headers_out.content_type.len = sizeof("text/plain") - 1; r->headers_out.content_type.data = (u_char *) "text/plain"; } /* allocate a new buffer for sending out the reply. */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* insertion in the buffer chain. */ out.buf = b; out.next = NULL; /* just one buffer */ b->pos = zip_content; b->last = zip_content + zip_read_bytes; b->memory = 1; b->last_buf = 1; /* sending the headers for the reply. */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = zip_read_bytes; ngx_http_send_header(r); return ngx_http_output_filter(r, &out); } /* ngx_http_unzip_handler */
ngx_int_t ngx_http_lua_content_handler_file(ngx_http_request_t *r) { lua_State *L; ngx_int_t rc; u_char *script_path; ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_loc_conf_t *llcf; char *err; ngx_str_t eval_src; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (ngx_http_complex_value(r, &llcf->content_src, &eval_src) != NGX_OK) { return NGX_ERROR; } script_path = ngx_http_lua_rebase_path(r->pool, eval_src.data, eval_src.len); if (script_path == NULL) { return NGX_ERROR; } lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); L = lmcf->lua; /* load Lua script file (w/ cache) sp = 1 */ rc = ngx_http_lua_cache_loadfile(L, script_path, llcf->content_src_key, &err, llcf->enable_code_cache ? 1 : 0); if (rc != NGX_OK) { if (err == NULL) { err = "unknown error"; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to load Lua inlined code: %s", err); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* make sure we have a valid code chunk */ assert(lua_isfunction(L, -1)); rc = ngx_http_lua_content_by_chunk(L, r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_DONE) { return NGX_DONE; } if (rc == NGX_AGAIN) { #if defined(nginx_version) && nginx_version >= 8011 r->main->count++; #endif return NGX_DONE; } return NGX_OK; }
ngx_int_t ngx_http_redis2_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis2_ctx_t *ctx; ngx_http_redis2_loc_conf_t *rlcf; ngx_str_t target; ngx_url_t url; rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis2_module); if (rlcf->complex_target) { /* variables used in the redis2_pass directive */ if (ngx_http_complex_value(r, rlcf->complex_target, &target) != NGX_OK) { return NGX_ERROR; } if (target.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "handler: empty \"redis2_pass\" target"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } url.host = target; url.port = 0; url.no_resolve = 1; rlcf->upstream.upstream = ngx_http_redis2_upstream_add(r, &url); if (rlcf->upstream.upstream == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "redis2: upstream \"%V\" not found", &target); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } ngx_str_set(&u->schema, "redis2://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_redis2_module; u->conf = &rlcf->upstream; u->create_request = ngx_http_redis2_create_request; u->reinit_request = ngx_http_redis2_reinit_request; u->process_header = ngx_http_redis2_process_header; u->abort_request = ngx_http_redis2_abort_request; u->finalize_request = ngx_http_redis2_finalize_request; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_redis2_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; ctx->state = NGX_ERROR; ngx_http_set_ctx(r, ctx, ngx_http_redis2_module); u->input_filter_init = ngx_http_redis2_filter_init; u->input_filter = ngx_http_redis2_filter; u->input_filter_ctx = ctx; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
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_poller_create_request(ngx_http_request_t *r) { ngx_http_poller_t *poller; ngx_http_poller_header_t *header; ngx_str_t *value; ngx_buf_t *b; ngx_chain_t *cl; ngx_uint_t i; size_t len; ngx_str_t uri; ngx_str_t body; ngx_array_t headers; poller = ngx_http_get_module_ctx(r, ngx_http_poller_module); if (ngx_http_complex_value(r, &poller->uri, &uri) != NGX_OK) { return NGX_ERROR; } body.len = 0; body.data = NULL; if (poller->body_ok) { if (ngx_http_complex_value(r, &poller->body, &body) != NGX_OK) { return NGX_ERROR; } } len = poller->method.len; len += sizeof(" ") - 1; len += uri.len; len += sizeof(" HTTP/1.0") - 1; len += sizeof(CRLF) - 1; if (poller->headers.nelts > 0) { if (ngx_array_init(&headers, r->pool, poller->headers.nelts, sizeof(ngx_str_t)) != NGX_OK) { return NGX_ERROR; } header = poller->headers.elts; for (i = 0; i < poller->headers.nelts; ++i) { value = ngx_array_push(&headers); if (value == NULL) { return NGX_ERROR; } if (ngx_http_complex_value(r, &header[i].value, value) != NGX_OK) { return NGX_ERROR; } len += header[i].name.len; len += sizeof(": ") - 1; len += value->len; len += sizeof(CRLF) - 1; } } if (poller->body_ok) { len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2; } len += sizeof(CRLF) - 1; b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } #define DO_CPYMEM(x, y) x = ngx_cpymem(x, y, sizeof(y) - 1) #define DO_CPYSTR(x, y) x = ngx_cpymem(x, y.data, y.len) DO_CPYSTR(b->last, poller->method); DO_CPYMEM(b->last, " "); DO_CPYSTR(b->last, uri); DO_CPYMEM(b->last, " HTTP/1.0"); DO_CPYMEM(b->last, CRLF); if (poller->headers.nelts > 0) { header = poller->headers.elts; value = headers.elts; for (i = 0; i < poller->headers.nelts; ++i) { DO_CPYSTR(b->last, header[i].name); DO_CPYMEM(b->last, ": "); DO_CPYSTR(b->last, value[i]); DO_CPYMEM(b->last, CRLF); } } if (poller->body_ok) { b->last = ngx_sprintf(b->last, "Content-Length: %O", (off_t)body.len); DO_CPYMEM(b->last, CRLF); } DO_CPYMEM(b->last, CRLF); if (poller->body_ok && body.len > 0) { DO_CPYSTR(b->last, body); } #undef DO_CPYMEM #undef DO_CPYSTR cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; r->subrequest_in_memory = 1; b->last_buf = 1; return NGX_OK; }
ngx_int_t ngx_http_rds_json_output_props(ngx_http_request_t *r, ngx_http_rds_json_ctx_t *ctx, ngx_http_rds_json_loc_conf_t *conf) { size_t size; u_char *pos, *last; ngx_uint_t i; ngx_str_t *values = NULL; uintptr_t *escapes = NULL; ngx_http_rds_json_property_t *prop = NULL; size = sizeof("{:") - 1 + conf->root.len; if (conf->success.len) { size += sizeof(",:true") - 1 + conf->success.len; } if (conf->user_props) { values = ngx_pnalloc(r->pool, conf->user_props->nelts * (sizeof(ngx_str_t) + sizeof(uintptr_t))); if (values == NULL) { return NGX_ERROR; } escapes = (uintptr_t *) ((u_char *) values + conf->user_props->nelts * sizeof(ngx_str_t)); prop = conf->user_props->elts; for (i = 0; i < conf->user_props->nelts; i++) { if (ngx_http_complex_value(r, &prop[i].value, &values[i]) != NGX_OK) { return NGX_ERROR; } escapes[i] = ngx_http_rds_json_escape_json_str(NULL, values[i].data, values[i].len); size += sizeof(":\"\",") - 1 + prop[i].key.len + values[i].len + escapes[i]; } } pos = ngx_http_rds_json_request_mem(r, ctx, size); if (pos == NULL) { return NGX_ERROR; } last = pos; *last++ = '{'; if (conf->success.len) { last = ngx_copy(last, conf->success.data, conf->success.len); last = ngx_copy_literal(last, ":true,"); } if (conf->user_props) { for (i = 0; i < conf->user_props->nelts; i++) { last = ngx_copy(last, prop[i].key.data, prop[i].key.len); *last++ = ':'; *last++ = '"'; if (escapes[i] == 0) { last = ngx_copy(last, values[i].data, values[i].len); } else { last = (u_char *) ngx_http_rds_json_escape_json_str(last, values[i].data, values[i].len); } *last++ = '"'; *last++ = ','; } } last = ngx_copy(last, conf->root.data, conf->root.len); *last++ = ':'; if (last - pos != (ssize_t) size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rds_json: output props begin: buffer error: %O != %uz", (off_t) (last - pos), size); return NGX_ERROR; } return ngx_http_rds_json_submit_mem(r, ctx, size, 0); }
ngx_int_t nchan_maybe_send_channel_event_message(ngx_http_request_t *r, channel_event_type_t event_type) { static nchan_loc_conf_t evcf_data; static nchan_loc_conf_t *evcf = NULL; static ngx_str_t group = ngx_string("meta"); static ngx_str_t evt_sub_enqueue = ngx_string("subscriber_enqueue"); static ngx_str_t evt_sub_dequeue = ngx_string("subscriber_dequeue"); static ngx_str_t evt_sub_recvmsg = ngx_string("subscriber_receive_message"); static ngx_str_t evt_sub_recvsts = ngx_string("subscriber_receive_status"); static ngx_str_t evt_chan_publish= ngx_string("channel_publish"); static ngx_str_t evt_chan_delete = ngx_string("channel_delete"); nchan_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_nchan_module); ngx_http_complex_value_t *cv = cf->channel_events_channel_id; if(cv==NULL) { //nothing to send return NGX_OK; } nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); ngx_str_t tmpid; size_t sz; ngx_str_t *id; u_char *cur; ngx_str_t evstr; nchan_msg_t msg; switch(event_type) { case SUB_ENQUEUE: ctx->channel_event_name = &evt_sub_enqueue; break; case SUB_DEQUEUE: ctx->channel_event_name = &evt_sub_dequeue; break; case SUB_RECEIVE_MESSAGE: ctx->channel_event_name = &evt_sub_recvmsg; break; case SUB_RECEIVE_STATUS: ctx->channel_event_name = &evt_sub_recvsts; break; case CHAN_PUBLISH: ctx->channel_event_name = &evt_chan_publish; break; case CHAN_DELETE: ctx->channel_event_name = &evt_chan_delete; break; } //the id ngx_http_complex_value(r, cv, &tmpid); sz = group.len + 1 + tmpid.len; if((id = ngx_palloc(r->pool, sizeof(*id) + sz)) == NULL) { nchan_log_request_error(r, "can't allocate space for legacy channel id"); return NGX_ERROR; } id->len = sz; id->data = (u_char *)&id[1]; cur = id->data; ngx_memcpy(cur, group.data, group.len); cur += group.len; cur[0]='/'; cur++; ngx_memcpy(cur, tmpid.data, tmpid.len); //the event message ngx_http_complex_value(r, cf->channel_event_string, &evstr); ngx_memzero(&msg, sizeof(msg)); msg.buf.temporary = 1; msg.buf.memory = 1; msg.buf.last_buf = 1; msg.buf.pos = evstr.data; msg.buf.last = evstr.data + evstr.len; msg.buf.start = msg.buf.pos; msg.buf.end = msg.buf.last; msg.id.time = 0; msg.id.tag.fixed[0] = 0; msg.id.tagactive = 0; msg.id.tagcount = 1; if(evcf == NULL) { evcf = &evcf_data; ngx_memzero(evcf, sizeof(*evcf)); evcf->message_timeout = NCHAN_META_CHANNEL_MESSAGE_TTL; evcf->max_messages = NCHAN_META_CHANNEL_MAX_MESSAGES; evcf->complex_max_messages = NULL; evcf->complex_message_timeout = NULL; evcf->subscriber_first_message = 0; evcf->channel_timeout = NCHAN_META_CHANNEL_TIMEOUT; } evcf->storage_engine = cf->storage_engine; evcf->redis = cf->redis; evcf->storage_engine->publish(id, &msg, evcf, NULL, NULL); return NGX_OK; }
static ngx_int_t ngx_http_replace_header_filter(ngx_http_request_t *r) { size_t size; ngx_str_t skip; ngx_pool_cleanup_t *cln; ngx_http_replace_ctx_t *ctx; ngx_http_replace_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_replace_filter_module); dd("replace header filter"); if (rlcf->regexes.nelts == 0 || r->headers_out.content_length_n == 0 || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || ngx_http_test_content_type(r, &rlcf->types) == NULL) { return ngx_http_next_header_filter(r); } dd("skip: %p", rlcf->skip); if (rlcf->skip != NULL) { if (ngx_http_complex_value(r, rlcf->skip, &skip) != NGX_OK) { return NGX_ERROR; } if (skip.len && (skip.len != 1 || skip.data[0] != '0')) { return ngx_http_next_header_filter(r); } } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_replace_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->last_special = &ctx->special; ctx->last_pending = &ctx->pending; ctx->last_pending2 = &ctx->pending2; ctx->last_captured = &ctx->captured; ctx->sub = ngx_pcalloc(r->pool, rlcf->multi_replace.nelts * sizeof(ngx_str_t)); if (ctx->sub == NULL) { return NGX_ERROR; } ctx->ovector = ngx_palloc(r->pool, rlcf->ovecsize); if (ctx->ovector == NULL) { return NGX_ERROR; } size = ngx_align(rlcf->regexes.nelts, 8) / 8; ctx->disabled = ngx_pcalloc(r->pool, size); if (ctx->disabled == NULL) { return NGX_ERROR; } ctx->vm_pool = sre_create_pool(1024); if (ctx->vm_pool == NULL) { return NGX_ERROR; } dd("created vm pool %p", ctx->vm_pool); cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { sre_destroy_pool(ctx->vm_pool); return NGX_ERROR; } cln->data = ctx->vm_pool; cln->handler = ngx_http_replace_cleanup_pool; ctx->vm_ctx = sre_vm_pike_create_ctx(ctx->vm_pool, rlcf->program, ctx->ovector, rlcf->ovecsize); if (ctx->vm_ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_replace_filter_module); ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; if (r == r->main) { ngx_http_clear_content_length(r); if (rlcf->last_modified == NGX_HTTP_REPLACE_CLEAR_LAST_MODIFIED) { ngx_http_clear_last_modified(r); } } return ngx_http_next_header_filter(r); }
static void nchan_publisher_body_handler_continued(ngx_http_request_t *r, ngx_str_t *channel_id, nchan_loc_conf_t *cf) { ngx_http_complex_value_t *publisher_upstream_request_url_ccv; static ngx_str_t POST_REQUEST_STRING = {4, (u_char *)"POST "}; safe_request_ptr_t *pd; switch(r->method) { case NGX_HTTP_GET: if((pd = nchan_set_safe_request_ptr(r)) == NULL){ return; } cf->storage_engine->find_channel(channel_id, cf, (callback_pt) &channel_info_callback, pd); break; case NGX_HTTP_PUT: case NGX_HTTP_POST: publisher_upstream_request_url_ccv = cf->publisher_upstream_request_url; if(publisher_upstream_request_url_ccv == NULL) { ngx_str_t *content_type = (r->headers_in.content_type ? &r->headers_in.content_type->value : NULL); ngx_int_t content_length = r->headers_in.content_length_n > 0 ? r->headers_in.content_length_n : 0; // no need to check for chunked transfer-encoding, nginx automatically sets the // content-length either way. nchan_publisher_post_request(r, content_type, content_length, r->request_body->bufs, channel_id, cf); } else { nchan_pub_upstream_stuff_t *psr_stuff; if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) { nchan_log_request_error(r, "can't allocate memory for publisher auth subrequest"); nchan_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_http_post_subrequest_t *psr = &psr_stuff->psr; nchan_pub_upstream_data_t *psrd = &psr_stuff->psr_data; ngx_http_request_t *sr; ngx_str_t publisher_upstream_request_url; ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &publisher_upstream_request_url); psr->handler = nchan_publisher_upstream_handler; psr->data = psrd; psrd->ch_id = channel_id; ngx_http_subrequest(r, &publisher_upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY); nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, r->request_body, r->headers_in.content_length_n, NULL); sr->args = r->args; } break; case NGX_HTTP_DELETE: if((pd = nchan_set_safe_request_ptr(r)) == NULL){ return; } cf->storage_engine->delete_channel(channel_id, cf, (callback_pt) &channel_info_callback, pd); nchan_maybe_send_channel_event_message(r, CHAN_DELETE); break; default: nchan_respond_status(r, NGX_HTTP_FORBIDDEN, NULL, 0); } }
ngx_int_t ngx_http_redis2_build_query(ngx_http_request_t *r, ngx_array_t *queries, ngx_buf_t **b) { ngx_uint_t i, j; ngx_uint_t n; ngx_str_t *arg; ngx_array_t *args; size_t len; ngx_array_t **query_args; ngx_http_complex_value_t **complex_arg; u_char *p; ngx_http_redis2_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis2_module); query_args = rlcf->queries->elts; n = 0; for (i = 0; i < rlcf->queries->nelts; i++) { for (j = 0; j < query_args[i]->nelts; j++) { n++; } } args = ngx_array_create(r->pool, n, sizeof(ngx_str_t)); if (args == NULL) { return NGX_ERROR; } len = 0; n = 0; for (i = 0; i < rlcf->queries->nelts; i++) { complex_arg = query_args[i]->elts; len += sizeof("*") - 1 + ngx_get_num_size(query_args[i]->nelts) + sizeof("\r\n") - 1 ; for (j = 0; j < query_args[i]->nelts; j++) { n++; arg = ngx_array_push(args); if (arg == NULL) { return NGX_ERROR; } if (ngx_http_complex_value(r, complex_arg[j], arg) != NGX_OK) { return NGX_ERROR; } len += sizeof("$") - 1 + ngx_get_num_size(arg->len) + sizeof("\r\n") - 1 + arg->len + sizeof("\r\n") - 1 ; } } *b = ngx_create_temp_buf(r->pool, len); if (*b == NULL) { return NGX_ERROR; } p = (*b)->last; arg = args->elts; n = 0; for (i = 0; i < rlcf->queries->nelts; i++) { *p++ = '*'; p = ngx_sprintf(p, "%uz", query_args[i]->nelts); *p++ = '\r'; *p++ = '\n'; for (j = 0; j < query_args[i]->nelts; j++) { *p++ = '$'; p = ngx_sprintf(p, "%uz", arg[n].len); *p++ = '\r'; *p++ = '\n'; p = ngx_copy(p, arg[n].data, arg[n].len); *p++ = '\r'; *p++ = '\n'; n++; } } dd("query: %.*s", (int) (p - (*b)->pos), (*b)->pos); if (p - (*b)->pos != (ssize_t) len) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "redis2: redis2_query buffer error %uz != %uz", (size_t) (p - (*b)->pos), len); return NGX_ERROR; } (*b)->last = p; return NGX_OK; }
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_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; ngx_http_sub_loc_conf_t *slcf; ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } if ((in == NULL && ctx->buf == NULL && ctx->in == NULL && ctx->busy == NULL)) { return ngx_http_next_body_filter(r, in); } if (ctx->once && (ctx->buf == NULL || ctx->in == NULL)) { if (ctx->busy) { if (ngx_http_sub_output(r, ctx) == NGX_ERROR) { return NGX_ERROR; } } return ngx_http_next_body_filter(r, in); } /* add the incoming chain to the chain ctx->in */ if (in) { if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) { return NGX_ERROR; } } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http sub filter \"%V\"", &r->uri); while (ctx->in || ctx->buf) { if (ctx->buf == NULL) { ctx->buf = ctx->in->buf; ctx->in = ctx->in->next; ctx->pos = ctx->buf->pos; } if (ctx->state == sub_start_state) { ctx->copy_start = ctx->pos; ctx->copy_end = ctx->pos; } b = NULL; while (ctx->pos < ctx->buf->last) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "saved: \"%V\" state: %d", &ctx->saved, ctx->state); rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "parse: %d, looked: \"%V\" %p-%p", rc, &ctx->looked, ctx->copy_start, ctx->copy_end); if (rc == NGX_ERROR) { return rc; } if (ctx->saved.len) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "saved: \"%V\"", &ctx->saved); cl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (cl == NULL) { return NGX_ERROR; } b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); b->pos = ngx_pnalloc(r->pool, ctx->saved.len); if (b->pos == NULL) { return NGX_ERROR; } ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); b->last = b->pos + ctx->saved.len; b->memory = 1; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->saved.len = 0; } if (ctx->copy_start != ctx->copy_end) { cl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (cl == NULL) { return NGX_ERROR; } b = cl->buf; ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t)); b->pos = ctx->copy_start; b->last = ctx->copy_end; b->shadow = NULL; b->last_buf = 0; b->last_in_chain = 0; b->recycled = 0; if (b->in_file) { b->file_last = b->file_pos + (b->last - ctx->buf->pos); b->file_pos += b->pos - ctx->buf->pos; } *ctx->last_out = cl; ctx->last_out = &cl->next; } if (ctx->state == sub_start_state) { ctx->copy_start = ctx->pos; ctx->copy_end = ctx->pos; } else { ctx->copy_start = NULL; ctx->copy_end = NULL; } if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) { ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos); ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); } if (rc == NGX_AGAIN) { continue; } /* rc == NGX_OK */ cl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (cl == NULL) { return NGX_ERROR; } b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); if (ctx->sub.data == NULL) { if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) != NGX_OK) { return NGX_ERROR; } } if (ctx->sub.len) { b->memory = 1; b->pos = ctx->sub.data; b->last = ctx->sub.data + ctx->sub.len; } else { b->sync = 1; } *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->once = slcf->once; continue; } if (ctx->looked.len && (ctx->buf->last_buf || ctx->buf->last_in_chain)) { cl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (cl == NULL) { return NGX_ERROR; } b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); b->pos = ctx->looked.data; b->last = b->pos + ctx->looked.len; b->memory = 1; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->looked.len = 0; } if (ctx->buf->last_buf || ctx->buf->flush || ctx->buf->sync || ngx_buf_in_memory(ctx->buf)) { if (b == NULL) { cl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (cl == NULL) { return NGX_ERROR; } b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); b->sync = 1; *ctx->last_out = cl; ctx->last_out = &cl->next; } b->last_buf = ctx->buf->last_buf; b->last_in_chain = ctx->buf->last_in_chain; b->flush = ctx->buf->flush; b->shadow = ctx->buf; b->recycled = ctx->buf->recycled; } ctx->buf = NULL; ctx->saved.len = ctx->looked.len; ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); } if (ctx->out == NULL && ctx->busy == NULL) { return NGX_OK; } return ngx_http_sub_output(r, ctx); }
ngx_http_request_t *subscriber_cv_subrequest(subscriber_t *sub, ngx_http_complex_value_t *url_ccv, ngx_buf_t *body, subrequest_callback_pt cb, void *cb_data) { ngx_str_t request_url; ngx_http_complex_value(sub->request, url_ccv, &request_url); return subscriber_subrequest(sub, &request_url, body, cb, cb_data); }
ngx_int_t ngx_http_srcache_access_handler(ngx_http_request_t *r) { ngx_str_t skip; ngx_int_t rc; ngx_http_srcache_loc_conf_t *conf; ngx_http_srcache_main_conf_t *smcf; ngx_http_srcache_ctx_t *ctx; ngx_chain_t *cl; size_t len; unsigned no_store; /* access phase handlers are skipped in subrequests, * so the current request must be a main request */ conf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (conf->fetch == NULL && conf->store == NULL) { dd("bypass: %.*s", (int) r->uri.len, r->uri.data); return NGX_DECLINED; } dd("store defined? %p", conf->store); dd("req method: %lu", (unsigned long) r->method); dd("cache methods: %lu", (unsigned long) conf->cache_methods); if (!(r->method & conf->cache_methods)) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch and srcache_store skipped due to request " "method %V", &r->method_name); return NGX_DECLINED; } if (conf->req_cache_control && ngx_http_srcache_request_no_cache(r, &no_store) == NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch skipped due to request headers " "\"Cache-Control: no-cache\" or \"Pragma: no-cache\""); if (!no_store) { /* register a ctx to give a chance to srcache_store to run */ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_store skipped due to request header " "\"Cache-Control: no-store\""); } return NGX_DECLINED; } if (conf->fetch_skip != NULL && ngx_http_complex_value(r, conf->fetch_skip, &skip) == NGX_OK && skip.len && (skip.len != 1 || skip.data[0] != '0')) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch skipped due to the true value fed into " "srcache_fetch_skip: \"%V\"", &skip); /* register a ctx to give a chance to srcache_store to run */ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); if (ctx != NULL) { /* if (ctx->fetch_error) { return NGX_DECLINED; } */ if (ctx->waiting_subrequest) { dd("waiting subrequest"); return NGX_AGAIN; } if (ctx->waiting_request_body) { return NGX_AGAIN; } if (ctx->request_body_done == 1) { ctx->request_body_done = 0; goto do_fetch_subrequest; } if (ctx->request_done) { dd("request done"); if (ngx_http_post_request(r, NULL) != NGX_OK) { return NGX_ERROR; } if (!ctx->from_cache) { return NGX_DECLINED; } dd("sending header"); if (ctx->body_from_cache) { len = 0; for (cl = ctx->body_from_cache; cl->next; cl = cl->next) { len += ngx_buf_size(cl->buf); } len += ngx_buf_size(cl->buf); cl->buf->last_buf = 1; r->headers_out.content_length_n = len; rc = ngx_http_send_header(r); dd("srcache fetch header returned %d", (int) rc); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } #if 1 if (r->header_only) { return NGX_HTTP_OK; } #endif if (!r->filter_finalize) { rc = ngx_http_output_filter(r, ctx->body_from_cache); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } } dd("sent body from cache: %d", (int) rc); dd("finalize from here..."); ngx_http_finalize_request(r, rc); /* dd("r->main->count (post): %d", (int) r->main->count); */ return NGX_DONE; } return NGX_DECLINED; } } else { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_srcache_filter_module); } smcf = ngx_http_get_module_main_conf(r, ngx_http_srcache_filter_module); if (!smcf->postponed_to_access_phase_end) { ngx_http_core_main_conf_t *cmcf; ngx_http_phase_handler_t tmp; ngx_http_phase_handler_t *ph; ngx_http_phase_handler_t *cur_ph; ngx_http_phase_handler_t *last_ph; smcf->postponed_to_access_phase_end = 1; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; cur_ph = &ph[r->phase_handler]; /* we should skip the post_access phase handler here too */ last_ph = &ph[cur_ph->next - 2]; if (cur_ph < last_ph) { dd("swaping the contents of cur_ph and last_ph..."); tmp = *cur_ph; memmove(cur_ph, cur_ph + 1, (last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t)); *last_ph = tmp; r->phase_handler--; /* redo the current ph */ return NGX_DECLINED; } } if (conf->fetch == NULL) { dd("fetch is not defined"); return NGX_DECLINED; } dd("running phase handler..."); if (!r->request_body) { dd("reading request body: ctx = %p", ctx); rc = ngx_http_read_client_request_body(r, ngx_http_srcache_post_read_body); if (rc == NGX_ERROR || rc > NGX_OK) { #if (nginx_version < 1002006) \ || (nginx_version >= 1003000 && nginx_version < 1003009) r->main->count--; #endif return rc; } if (rc == NGX_AGAIN) { ctx->waiting_request_body = 1; return NGX_AGAIN; } /* rc == NGX_OK */ } do_fetch_subrequest: /* issue a subrequest to fetch cached stuff (if any) */ rc = ngx_http_srcache_fetch_subrequest(r, conf, ctx); if (rc != NGX_OK) { return rc; } ctx->waiting_subrequest = 1; dd("quit"); return NGX_AGAIN; }
static ngx_int_t ngx_http_req_status_handler(ngx_http_request_t *r) { size_t len; uint32_t hash; ngx_str_t key; ngx_uint_t i; ngx_shm_zone_t **pzone; ngx_pool_cleanup_t *cln; ngx_http_req_status_ctx_t *r_ctx; ngx_http_req_status_zone_t *ctx; ngx_http_req_status_node_t *ssn; ngx_http_req_status_loc_conf_t *rlcf; ngx_http_req_status_zone_node_t *pzn; r_ctx = ngx_http_get_module_ctx(r, ngx_http_req_status_module); rlcf = ngx_http_get_module_loc_conf(r, ngx_http_req_status_module); do { pzone = rlcf->req_zones.elts; for (i = 0; i < rlcf->req_zones.nelts; i++) { ctx = pzone[i]->data; if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { continue; } if (key.len == 0) { continue; } if (key.len > 65535) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "req-status, the value of the \"%V\" variable " "is more than 65535 bytes: \"%v\"", &ctx->key.value, &key); continue; } if (r_ctx == NULL) { r_ctx = ngx_palloc(r->pool, sizeof(ngx_http_req_status_ctx_t)); if (r_ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_array_init(&r_ctx->req_zones, r->pool, 2, sizeof(ngx_http_req_status_zone_node_t)) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_req_status_cleanup; cln->data = r_ctx; ngx_http_set_ctx(r, r_ctx, ngx_http_req_status_module); } hash = ngx_crc32_short(key.data, key.len); ngx_shmtx_lock(&ctx->shpool->mutex); ssn = ngx_http_req_status_lookup(ctx, hash, &key); if (ssn == NULL) { len = sizeof(ngx_http_req_status_node_t) + key.len + 1; ssn = ngx_slab_alloc_locked(ctx->shpool, len); if (ssn == NULL) { ngx_http_req_status_expire(ctx); ssn = ngx_slab_alloc_locked(ctx->shpool, len); if (ssn == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "req-status, slab alloc fail, zone = \"%V\", " "key = \"%V\", size = %uz", &ctx->shm_zone->shm.name, &key, len); ngx_shmtx_unlock(&ctx->shpool->mutex); continue; } } ssn->node.key = hash; ssn->len = key.len; ssn->count = 1; ngx_memzero(&ssn->data, sizeof(ssn->data)); ngx_memcpy(ssn->key, key.data, key.len); ssn->key[key.len] = '\0'; ssn->last_traffic_update = 0; ngx_rbtree_insert(&ctx->sh->rbtree, &ssn->node); } ssn->data.requests ++; ssn->active ++; if (ssn->active > ssn->data.max_active) { ssn->data.max_active = ssn->active; } ngx_queue_insert_head(&ctx->sh->queue, &ssn->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); pzn = ngx_array_push(&r_ctx->req_zones); if (pzn == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } pzn->node = ssn; pzn->zone = ctx; } rlcf = rlcf->parent; } while (rlcf); return NGX_DECLINED; }
static ngx_int_t ngx_http_headers_filter(ngx_http_request_t *r) { ngx_str_t value; ngx_uint_t i, safe_status; ngx_http_header_val_t *h; ngx_http_headers_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module); if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL) || r != r->main) //expires off并且没有配置add_header,或者为子请求 { return ngx_http_next_header_filter(r); } switch (r->headers_out.status) { case NGX_HTTP_OK: case NGX_HTTP_CREATED: case NGX_HTTP_NO_CONTENT: case NGX_HTTP_PARTIAL_CONTENT: case NGX_HTTP_MOVED_PERMANENTLY: case NGX_HTTP_MOVED_TEMPORARILY: case NGX_HTTP_SEE_OTHER: case NGX_HTTP_NOT_MODIFIED: case NGX_HTTP_TEMPORARY_REDIRECT: safe_status = 1; break; default: safe_status = 0; break; } if (conf->expires != NGX_HTTP_EXPIRES_OFF && safe_status) { if (ngx_http_set_expires(r, conf) != NGX_OK) { return NGX_ERROR; } } if (conf->headers) { h = conf->headers->elts; for (i = 0; i < conf->headers->nelts; i++) { if (!safe_status && !h[i].always) { continue; } if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) { return NGX_ERROR; } if (h[i].handler(r, &h[i], &value) != NGX_OK) { return NGX_ERROR; } } } return ngx_http_next_header_filter(r); }
static ngx_http_reqstat_store_t * ngx_http_reqstat_create_store(ngx_http_request_t *r, ngx_http_reqstat_conf_t *rlcf) { ngx_str_t val; ngx_uint_t i; ngx_shm_zone_t **shm_zone, *z; ngx_http_reqstat_ctx_t *ctx; ngx_http_reqstat_store_t *store; ngx_http_reqstat_rbnode_t *fnode, **fnode_store; store = ngx_pcalloc(r->pool, sizeof(ngx_http_reqstat_store_t)); if (store == NULL) { return NULL; } if (rlcf->monitor == NULL) { store->bypass = 1; return store; } store->conf = rlcf; switch (ngx_http_test_predicates(r, rlcf->bypass)) { case NGX_ERROR: return NULL; case NGX_DECLINED: store->bypass = 1; return store; default: /* NGX_OK */ break; } if (ngx_array_init(&store->monitor_index, r->pool, rlcf->monitor->nelts, sizeof(ngx_http_reqstat_rbnode_t *)) == NGX_ERROR) { return NULL; } shm_zone = rlcf->monitor->elts; for (i = 0; i < rlcf->monitor->nelts; i++) { z = shm_zone[i]; ctx = z->data; if (ngx_http_complex_value(r, &ctx->value, &val) != NGX_OK) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "failed to reap the key \"%V\"", ctx->val); continue; } fnode = ngx_http_reqstat_rbtree_lookup(shm_zone[i], &val); if (fnode == NULL) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "failed to alloc node in zone \"%V\", " "enlarge it please", &z->shm.name); } else { fnode_store = ngx_array_push(&store->monitor_index); *fnode_store = fnode; } } return store; }
ngx_int_t nchan_maybe_send_channel_event_message(ngx_http_request_t *r, channel_event_type_t event_type) { static nchan_loc_conf_t evcf_data; static nchan_loc_conf_t *evcf = NULL; static ngx_str_t group = ngx_string("meta"); static ngx_str_t evt_sub_enqueue = ngx_string("subscriber_enqueue"); static ngx_str_t evt_sub_dequeue = ngx_string("subscriber_dequeue"); static ngx_str_t evt_sub_recvmsg = ngx_string("subscriber_receive_message"); static ngx_str_t evt_sub_recvsts = ngx_string("subscriber_receive_status"); static ngx_str_t evt_chan_publish= ngx_string("channel_publish"); static ngx_str_t evt_chan_delete = ngx_string("channel_delete"); struct timeval tv; nchan_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, nchan_module); ngx_http_complex_value_t *cv = cf->channel_events_channel_id; if(cv==NULL) { //nothing to send return NGX_OK; } nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); ngx_str_t tmpid; size_t sz; ngx_str_t *id; u_char *cur; ngx_str_t evstr; ngx_buf_t buf; nchan_msg_t msg; switch(event_type) { case SUB_ENQUEUE: ctx->channel_event_name = &evt_sub_enqueue; break; case SUB_DEQUEUE: ctx->channel_event_name = &evt_sub_dequeue; break; case SUB_RECEIVE_MESSAGE: ctx->channel_event_name = &evt_sub_recvmsg; break; case SUB_RECEIVE_STATUS: ctx->channel_event_name = &evt_sub_recvsts; break; case CHAN_PUBLISH: ctx->channel_event_name = &evt_chan_publish; break; case CHAN_DELETE: ctx->channel_event_name = &evt_chan_delete; break; } //the id ngx_http_complex_value(r, cv, &tmpid); sz = group.len + 1 + tmpid.len; if((id = ngx_palloc(r->pool, sizeof(*id) + sz)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: can't allocate space for legacy channel id"); return NGX_ERROR; } id->len = sz; id->data = (u_char *)&id[1]; cur = id->data; ngx_memcpy(cur, group.data, group.len); cur += group.len; cur[0]='/'; cur++; ngx_memcpy(cur, tmpid.data, tmpid.len); //the event message ngx_http_complex_value(r, cf->channel_event_string, &evstr); ngx_memzero(&buf, sizeof(buf)); //do we really need this?... buf.temporary = 1; buf.memory = 1; buf.last_buf = 1; buf.pos = evstr.data; buf.last = evstr.data + evstr.len; buf.start = buf.pos; buf.end = buf.last; ngx_memzero(&msg, sizeof(msg)); ngx_gettimeofday(&tv); msg.id.time = tv.tv_sec; msg.id.tagcount = 1; msg.buf = &buf; if(evcf == NULL) { evcf = &evcf_data; ngx_memzero(evcf, sizeof(*evcf)); evcf->buffer_timeout = 10; evcf->max_messages = NGX_MAX_INT_T_VALUE; evcf->subscriber_start_at_oldest_message = 0; evcf->channel_timeout = 30; } evcf->storage_engine = cf->storage_engine; evcf->use_redis = cf->use_redis; evcf->storage_engine->publish(id, &msg, evcf, NULL, NULL); return NGX_OK; }
ngx_int_t ngx_http_rds_json_output_header(ngx_http_request_t *r, ngx_http_rds_json_ctx_t *ctx, ngx_http_rds_header_t *header) { u_char *pos, *last; size_t size; uintptr_t escape; unsigned last_buf = 0; ngx_uint_t i; ngx_str_t *values = NULL; uintptr_t *escapes = NULL; ngx_http_rds_json_property_t *prop = NULL; ngx_http_rds_json_loc_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module); /* calculate the buffer size */ size = sizeof("{") - 1 + conf->errcode_key.len + sizeof(":") - 1 + ngx_get_num_size(header->std_errcode) + sizeof("}") - 1; if (conf->success.len) { size += conf->success.len + sizeof(":,") - 1; if (header->std_errcode == 0) { size += sizeof("true") - 1; } else { size += sizeof("false") - 1; } } if (conf->user_props) { values = ngx_pnalloc(r->pool, conf->user_props->nelts * (sizeof(ngx_str_t) + sizeof(uintptr_t))); if (values == NULL) { return NGX_ERROR; } escapes = (uintptr_t *) ((u_char *) values + conf->user_props->nelts * sizeof(ngx_str_t)); prop = conf->user_props->elts; for (i = 0; i < conf->user_props->nelts; i++) { if (ngx_http_complex_value(r, &prop[i].value, &values[i]) != NGX_OK) { return NGX_ERROR; } escapes[i] = ngx_http_rds_json_escape_json_str(NULL, values[i].data, values[i].len); size += sizeof(":\"\",") - 1 + prop[i].key.len + values[i].len + escapes[i]; } } if (header->errstr.len) { escape = ngx_http_rds_json_escape_json_str(NULL, header->errstr.data, header->errstr.len); size += sizeof(",") - 1 + conf->errstr_key.len + sizeof(":") - 1 + sizeof("\"") - 1 + header->errstr.len + escape + sizeof("\"") - 1; } else { escape = (uintptr_t) 0; } if (header->insert_id) { size += sizeof(",\"insert_id\":") - 1 + ngx_get_num_size(header->insert_id); } if (header->affected_rows) { size += sizeof(",\"affected_rows\":") - 1 + ngx_get_num_size(header->affected_rows); } /* create the buffer */ pos = ngx_http_rds_json_request_mem(r, ctx, size); if (pos == NULL) { return NGX_ERROR; } last = pos; /* fill up the buffer */ *last++ = '{'; if (conf->success.len) { last = ngx_copy(last, conf->success.data, conf->success.len); if (header->std_errcode == 0) { last = ngx_copy_literal(last, ":true,"); } else { last = ngx_copy_literal(last, ":false,"); } } if (conf->user_props) { for (i = 0; i < conf->user_props->nelts; i++) { last = ngx_copy(last, prop[i].key.data, prop[i].key.len); *last++ = ':'; *last++ = '"'; if (escapes[i] == 0) { last = ngx_copy(last, values[i].data, values[i].len); } else { last = (u_char *) ngx_http_rds_json_escape_json_str(last, values[i].data, values[i].len); } *last++ = '"'; *last++ = ','; } } last = ngx_copy(last, conf->errcode_key.data, conf->errcode_key.len); *last++ = ':'; last = ngx_snprintf(last, NGX_UINT16_LEN, "%uD", (uint32_t) header->std_errcode); if (header->errstr.len) { *last++ = ','; last = ngx_copy(last, conf->errstr_key.data, conf->errstr_key.len); *last++ = ':'; *last++ = '"'; if (escape == 0) { last = ngx_copy(last, header->errstr.data, header->errstr.len); } else { last = (u_char *) ngx_http_rds_json_escape_json_str(last, header->errstr.data, header->errstr.len); } *last++ = '"'; } if (header->insert_id) { last = ngx_copy_literal(last, ",\"insert_id\":"); last = ngx_snprintf(last, NGX_UINT64_LEN, "%uL", header->insert_id); } if (header->affected_rows) { last = ngx_copy_literal(last, ",\"affected_rows\":"); last = ngx_snprintf(last, NGX_UINT64_LEN, "%uL", header->affected_rows); } *last++ = '}'; if ((size_t) (last - pos) != size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rds_json: output header buffer error: %O != %uz", (off_t) (last - pos), size); return NGX_ERROR; } if (r == r->main) { last_buf = 1; } ctx->seen_stream_end = 1; return ngx_http_rds_json_submit_mem(r, ctx, size, (unsigned) last_buf); }
static ngx_int_t ngx_http_limit_req_handler(ngx_http_request_t *r) { uint32_t hash; ngx_str_t key; ngx_int_t rc; ngx_uint_t n, excess; ngx_msec_t delay; ngx_http_limit_req_ctx_t *ctx; ngx_http_limit_req_conf_t *lrcf; ngx_http_limit_req_limit_t *limit, *limits; if (r->main->limit_req_set) { return NGX_DECLINED; } lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); limits = lrcf->limits.elts; excess = 0; rc = NGX_DECLINED; #if (NGX_SUPPRESS_WARN) limit = NULL; #endif for (n = 0; n < lrcf->limits.nelts; n++) { limit = &limits[n]; ctx = limit->shm_zone->data; if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (key.len == 0) { continue; } if (key.len > 65535) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the value of the \"%V\" key " "is more than 65535 bytes: \"%V\"", &ctx->key.value, &key); continue; } hash = ngx_crc32_short(key.data, key.len); ngx_shmtx_lock(&ctx->shpool->mutex); rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess, (n == lrcf->limits.nelts - 1)); ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit_req[%ui]: %i %ui.%03ui", n, rc, excess / 1000, excess % 1000); if (rc != NGX_AGAIN) { break; } } if (rc == NGX_DECLINED) { return NGX_DECLINED; } r->main->limit_req_set = 1; if (rc == NGX_BUSY || rc == NGX_ERROR) { if (rc == NGX_BUSY) { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, excess: %ui.%03ui by zone \"%V\"", excess / 1000, excess % 1000, &limit->shm_zone->shm.name); } while (n--) { ctx = limits[n].shm_zone->data; if (ctx->node == NULL) { continue; } ngx_shmtx_lock(&ctx->shpool->mutex); ctx->node->count--; ngx_shmtx_unlock(&ctx->shpool->mutex); ctx->node = NULL; } return lrcf->status_code; } /* rc == NGX_AGAIN || rc == NGX_OK */ if (rc == NGX_AGAIN) { excess = 0; } delay = ngx_http_limit_req_account(limits, n, &excess, &limit); if (!delay) { return NGX_DECLINED; } ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, "delaying request, excess: %ui.%03ui, by zone \"%V\"", excess / 1000, excess % 1000, &limit->shm_zone->shm.name); if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_limit_req_delay; r->connection->write->delayed = 1; ngx_add_timer(r->connection->write, delay); return NGX_AGAIN; }
static ngx_int_t ngx_http_srcache_store_subrequest(ngx_http_request_t *r, ngx_http_srcache_ctx_t *ctx) { ngx_http_srcache_ctx_t *sr_ctx; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_request_t *sr; ngx_int_t rc; ngx_http_request_body_t *rb = NULL; ngx_http_srcache_loc_conf_t *conf; ngx_http_post_subrequest_t *psr; ngx_http_srcache_parsed_request_t *parsed_sr; dd("store subrequest"); conf = ngx_http_get_module_loc_conf(r, ngx_http_srcache_filter_module); if (conf->store == NULL) { dd("conf store is NULL"); return NGX_ERROR; } parsed_sr = ngx_palloc(r->pool, sizeof(ngx_http_srcache_parsed_request_t)); if (parsed_sr == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } parsed_sr->method = conf->store->method; parsed_sr->method_name = conf->store->method_name; if (ctx->body_to_cache) { dd("found body to cache (len %d)", (int) ctx->response_length); rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_ERROR; } rb->bufs = ctx->body_to_cache; rb->buf = ctx->body_to_cache->buf; parsed_sr->request_body = rb; } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_store: no request body for the subrequest"); return NGX_ERROR; } parsed_sr->content_length_n = ctx->response_length; if (ngx_http_complex_value(r, &conf->store->location, &parsed_sr->location) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (parsed_sr->location.len == 0) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_complex_value(r, &conf->store->args, &parsed_sr->args) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &parsed_sr->location, &args, &flags) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (args.len > 0 && parsed_sr->args.len == 0) { parsed_sr->args = args; } dd("firing the store subrequest"); dd("store location: %.*s", (int) parsed_sr->location.len, parsed_sr->location.data); dd("store args: %.*s", (int) parsed_sr->args.len, parsed_sr->args.data); sr_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_ctx_t)); if (sr_ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } sr_ctx->in_store_subrequest = 1; psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } psr->handler = ngx_http_srcache_store_post_subrequest; psr->data = sr_ctx; rc = ngx_http_subrequest(r, &parsed_sr->location, &parsed_sr->args, &sr, psr, flags); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_srcache_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return NGX_ERROR; } ngx_http_set_ctx(sr, sr_ctx, ngx_http_srcache_filter_module); return NGX_OK; }