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; }
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; if (r != r->main) { return NGX_DECLINED; } /* being the 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_HTTP_INTERNAL_SERVER_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_HTTP_INTERNAL_SERVER_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->request_done) { dd("request done"); if ( #if defined(nginx_version) && nginx_version >= 8012 ngx_http_post_request(r, NULL) #else ngx_http_post_request(r) #endif != NGX_OK) { return NGX_ERROR; } if (!ctx->from_cache) { return NGX_DECLINED; } dd("sending header"); if (ctx->body_from_cache && !(r->method & NGX_HTTP_HEAD)) { len = 0; for (cl = ctx->body_from_cache; cl->next; cl = cl->next) { len += ngx_buf_size(cl->buf); } len += ngx_buf_size(cl->buf); cl->buf->last_buf = 1; r->headers_out.content_length_n = len; rc = ngx_http_srcache_next_header_filter(r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } rc = ngx_http_srcache_next_body_filter(r, ctx->body_from_cache); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } dd("sent body from cache: %d", (int) rc); } else { r->headers_out.content_length_n = 0; rc = ngx_http_srcache_next_header_filter(r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } dd("sent header from cache: %d", (int) rc); dd("send last buf for the main request"); cl = ngx_alloc_chain_link(r->pool); cl->buf = ngx_calloc_buf(r->pool); cl->buf->last_buf = 1; rc = ngx_http_srcache_next_body_filter(r, cl); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } dd("sent last buf from cache: %d", (int) rc); } dd("finalize from here..."); ngx_http_finalize_request(r, NGX_OK); /* dd("r->main->count (post): %d", (int) r->main->count); */ return NGX_DONE; } } else { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_srcache_filter_module)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_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]; last_ph = &ph[cur_ph->next - 1]; 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..."); /* 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; }