/*write the in chain to a temp file*/ static ngx_int_t ngx_http_waf_write_to_file(ngx_temp_file_t *temp_file,ngx_chain_t *in) { ngx_int_t n; ngx_chain_t *cl; ngx_int_t complete = 0; n = ngx_write_chain_to_temp_file(temp_file, in); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } temp_file->offset += n; for(cl=in;cl;cl=cl->next) { if(cl->buf) { if(cl->buf->last_buf) complete = 1; //cl->buf->pos = cl->buf->start; //cl->buf->last = cl->buf->start; cl->buf->pos = cl->buf->last; } } if(complete) return NGX_OK; else return NGX_AGAIN; }
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body) { syslog(LOG_INFO, "[%s:%s:%d]", __FILE__, __func__, __LINE__); ssize_t n; ngx_temp_file_t *tf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; rb = r->request_body; if (rb->temp_file == NULL) { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_ERROR; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = clcf->client_body_temp_path; tf->pool = r->pool; tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; } rb->temp_file = tf; if (body == NULL) { /* empty body with r->request_body_in_file_only */ if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } } n = ngx_write_chain_to_temp_file(rb->temp_file, body); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } rb->temp_file->offset += n; return NGX_OK; }
static ngx_int_t ngx_http_lua_write_request_body(ngx_http_request_t *r, ngx_chain_t *body) { ssize_t n; ngx_temp_file_t *tf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; rb = r->request_body; if (rb->temp_file == NULL) { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_ERROR; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = clcf->client_body_temp_path; tf->pool = r->pool; tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = 1; tf->clean = 1; if (r->request_body_file_group_access) { tf->access = 0660; } rb->temp_file = tf; } n = ngx_write_chain_to_temp_file(rb->temp_file, body); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } rb->temp_file->offset += n; return NGX_OK; }
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r) { ssize_t n; ngx_chain_t *cl, *ln; ngx_temp_file_t *tf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; rb = r->request_body; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http write client request body, bufs %p", rb->bufs); if (rb->temp_file == NULL) { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_ERROR; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = clcf->client_body_temp_path; tf->pool = r->pool; tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; } rb->temp_file = tf; if (rb->bufs == NULL) { /* empty body with r->request_body_in_file_only */ if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } } if (rb->bufs == NULL) { return NGX_OK; } n = ngx_write_chain_to_temp_file(rb->temp_file, rb->bufs); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } rb->temp_file->offset += n; /* mark all buffers as written */ for (cl = rb->bufs; cl; /* void */) { cl->buf->pos = cl->buf->last; ln = cl; cl = cl->next; ngx_free_chain(r->pool, ln); } rb->bufs = NULL; return NGX_OK; }
static ngx_int_t ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) { ssize_t size, bsize; ngx_buf_t *b; ngx_chain_t *cl, *tl, *next, *out, **ll, **last_free, fl; if (p->buf_to_file) { fl.buf = p->buf_to_file; fl.next = p->in; out = &fl; } else { out = p->in; } if (!p->cacheable) { size = 0; cl = out; ll = NULL; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe offset: %O", p->temp_file->offset); do { bsize = cl->buf->last - cl->buf->pos; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe buf %p, pos %p, size: %z", cl->buf->start, cl->buf->pos, bsize); if ((size + bsize > p->temp_file_write_size) || (p->temp_file->offset + size + bsize > p->max_temp_file_size)) { break; } size += bsize; ll = &cl->next; cl = cl->next; } while (cl); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "size: %z", size); if (ll == NULL) { return NGX_BUSY; } if (cl) { p->in = cl; *ll = NULL; } else { p->in = NULL; p->last_in = &p->in; } } else { p->in = NULL; p->last_in = &p->in; } if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) { return NGX_ABORT; } for (last_free = &p->free_raw_bufs; *last_free != NULL; last_free = &(*last_free)->next) { /* void */ } if (p->buf_to_file) { p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos; p->buf_to_file = NULL; out = out->next; } for (cl = out; cl; cl = next) { next = cl->next; cl->next = NULL; b = cl->buf; b->file = &p->temp_file->file; b->file_pos = p->temp_file->offset; p->temp_file->offset += b->last - b->pos; b->file_last = p->temp_file->offset; b->in_file = 1; b->temp_file = 1; if (p->out) { *p->last_out = cl; } else { p->out = cl; } p->last_out = &cl->next; if (b->last_shadow) { tl = ngx_alloc_chain_link(p->pool); if (tl == NULL) { return NGX_ABORT; } tl->buf = b->shadow; tl->next = NULL; *last_free = tl; last_free = &tl->next; b->shadow->pos = b->shadow->start; b->shadow->last = b->shadow->start; ngx_event_pipe_remove_shadow_links(b->shadow); } } return NGX_OK; }
static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) { u_char *prev; size_t bsize; ngx_int_t rc; ngx_uint_t flush, flushed, prev_last_shadow; ngx_chain_t *out, **ll, *cl, file; ngx_connection_t *downstream; downstream = p->downstream; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream: %d", downstream->write->ready); flushed = 0; for ( ;; ) { if (p->downstream_error) { return ngx_event_pipe_drain_chains(p); } if (p->upstream_eof || p->upstream_error || p->upstream_done) { /* pass the p->out and p->in chains to the output filter */ for (cl = p->busy; cl; cl = cl->next) { cl->buf->recycled = 0; } if (p->out) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream flush out"); for (cl = p->out; cl; cl = cl->next) { cl->buf->recycled = 0; } rc = p->output_filter(p->output_ctx, p->out); if (rc == NGX_ERROR) { p->downstream_error = 1; return ngx_event_pipe_drain_chains(p); } p->out = NULL; } if (p->in) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream flush in"); for (cl = p->in; cl; cl = cl->next) { cl->buf->recycled = 0; } rc = p->output_filter(p->output_ctx, p->in); if (rc == NGX_ERROR) { p->downstream_error = 1; return ngx_event_pipe_drain_chains(p); } p->in = NULL; } if (p->cacheable && p->buf_to_file) { file.buf = p->buf_to_file; file.next = NULL; if (ngx_write_chain_to_temp_file(p->temp_file, &file) == NGX_ERROR) { return NGX_ABORT; } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream done"); /* TODO: free unused bufs */ p->downstream_done = 1; break; } if (downstream->data != p->output_ctx || !downstream->write->ready || downstream->write->delayed) { break; } /* bsize is the size of the busy recycled bufs */ prev = NULL; bsize = 0; for (cl = p->busy; cl; cl = cl->next) { if (cl->buf->recycled) { if (prev == cl->buf->start) { continue; } bsize += cl->buf->end - cl->buf->start; prev = cl->buf->start; } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write busy: %uz", bsize); out = NULL; if (bsize >= (size_t) p->busy_size) { flush = 1; goto flush; } flush = 0; ll = NULL; prev_last_shadow = 1; for ( ;; ) { if (p->out) { cl = p->out; if (cl->buf->recycled && bsize + cl->buf->last - cl->buf->pos > p->busy_size) { flush = 1; break; } p->out = p->out->next; ngx_event_pipe_free_shadow_raw_buf(&p->free_raw_bufs, cl->buf); } else if (!p->cacheable && p->in) { cl = p->in; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write buf ls:%d %p %z", cl->buf->last_shadow, cl->buf->pos, cl->buf->last - cl->buf->pos); if (cl->buf->recycled && cl->buf->last_shadow && bsize + cl->buf->last - cl->buf->pos > p->busy_size) { if (!prev_last_shadow) { p->in = p->in->next; cl->next = NULL; if (out) { *ll = cl; } else { out = cl; } } flush = 1; break; } prev_last_shadow = cl->buf->last_shadow; p->in = p->in->next; } else { break; } if (cl->buf->recycled) { bsize += cl->buf->last - cl->buf->pos; } cl->next = NULL; if (out) { *ll = cl; } else { out = cl; } ll = &cl->next; } flush: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write: out:%p, f:%d", out, flush); if (out == NULL) { if (!flush) { break; } /* a workaround for AIO */ if (flushed++ > 10) { return NGX_BUSY; } } rc = p->output_filter(p->output_ctx, out); if (rc == NGX_ERROR) { p->downstream_error = 1; return ngx_event_pipe_drain_chains(p); } ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag); for (cl = p->free; cl; cl = cl->next) { if (cl->buf->temp_file) { if (p->cacheable || !p->cyclic_temp_file) { continue; } /* reset p->temp_offset if all bufs had been sent */ if (cl->buf->file_last == p->temp_file->offset) { p->temp_file->offset = 0; } } /* TODO: free buf if p->free_bufs && upstream done */ /* add the free shadow raw buf to p->free_raw_bufs */ if (cl->buf->last_shadow) { if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) { return NGX_ABORT; } cl->buf->last_shadow = 0; } cl->buf->shadow = NULL; } } return NGX_OK; }
static ngx_int_t ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) { ssize_t size, bsize, n; ngx_buf_t *b; ngx_uint_t prev_last_shadow; ngx_chain_t *cl, *tl, *next, *out, **ll, **last_out, **last_free, fl; if (p->buf_to_file) { fl.buf = p->buf_to_file; fl.next = p->in; out = &fl; } else { out = p->in; } if (!p->cacheable) { size = 0; cl = out; ll = NULL; prev_last_shadow = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe offset: %O", p->temp_file->offset); do { bsize = cl->buf->last - cl->buf->pos; ngx_log_debug4(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe buf ls:%d %p, pos %p, size: %z", cl->buf->last_shadow, cl->buf->start, cl->buf->pos, bsize); if (prev_last_shadow && ((size + bsize > p->temp_file_write_size) || (p->temp_file->offset + size + bsize > p->max_temp_file_size))) { break; } prev_last_shadow = cl->buf->last_shadow; size += bsize; ll = &cl->next; cl = cl->next; } while (cl); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "size: %z", size); if (ll == NULL) { return NGX_BUSY; } if (cl) { p->in = cl; *ll = NULL; } else { p->in = NULL; p->last_in = &p->in; } } else { p->in = NULL; p->last_in = &p->in; } n = ngx_write_chain_to_temp_file(p->temp_file, out); if (n == NGX_ERROR) { return NGX_ABORT; } if (p->buf_to_file) { p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos; n -= p->buf_to_file->last - p->buf_to_file->pos; p->buf_to_file = NULL; out = out->next; } if (n > 0) { /* update previous buffer or add new buffer */ if (p->out) { for (cl = p->out; cl->next; cl = cl->next) { /* void */ } b = cl->buf; if (b->file_last == p->temp_file->offset) { p->temp_file->offset += n; b->file_last = p->temp_file->offset; goto free; } last_out = &cl->next; } else { last_out = &p->out; } cl = ngx_chain_get_free_buf(p->pool, &p->free); if (cl == NULL) { return NGX_ABORT; } b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); b->tag = p->tag; b->file = &p->temp_file->file; b->file_pos = p->temp_file->offset; p->temp_file->offset += n; b->file_last = p->temp_file->offset; b->in_file = 1; b->temp_file = 1; *last_out = cl; } free: for (last_free = &p->free_raw_bufs; *last_free != NULL; last_free = &(*last_free)->next) { /* void */ } for (cl = out; cl; cl = next) { next = cl->next; cl->next = p->free; p->free = cl; b = cl->buf; if (b->last_shadow) { tl = ngx_alloc_chain_link(p->pool); if (tl == NULL) { return NGX_ABORT; } tl->buf = b->shadow; tl->next = NULL; *last_free = tl; last_free = &tl->next; b->shadow->pos = b->shadow->start; b->shadow->last = b->shadow->start; ngx_event_pipe_remove_shadow_links(b->shadow); } } return NGX_OK; }
/* mostly an exact clone of the ngx_http_write_request_body * function in ngx_http_request_body.c of nginx 0.8.20. * copyrighted by Igor Sysoev. */ static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body, int chain_count) { ssize_t n; ngx_temp_file_t *tf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; int i; ngx_chain_t *cl, *saved_next; rb = r->request_body; if (rb->temp_file == NULL) { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_ERROR; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = clcf->client_body_temp_path; tf->pool = r->pool; if (rb->buf && rb->buf->last == rb->buf->end) { tf->warn = "a client request body is buffered to a temporary file " "(exceeding client_body_buffer_size)"; } else { tf->warn = "a client request body is buffered to a temporary file " "(exceeding chunkin_max_chunks_per_buf)"; } tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; } rb->temp_file = tf; } if (body == NULL) { return NGX_OK; } /* we need this hack to work around a bug in * ngx_write_chain_to_temp_file when the chain * link is longer than 1024, we'll receive * random alert like this: * [alert] 13493#0: *1 pread() read only 1024 * of 3603 from * "/opt/nginx/client_body_temp/0000000001" */ if (chain_count > MAX_CHUNKS_PER_DISK_WRITE) { i = 0; for (cl = body; cl; cl = cl->next) { if (i >= MAX_CHUNKS_PER_DISK_WRITE) { /* dd("wrote %d links first...", i+1); */ saved_next = cl->next; cl->next = NULL; n = ngx_write_chain_to_temp_file(rb->temp_file, body); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } rb->temp_file->offset += n; cl->next = saved_next; body = cl->next; i = 0; } else { i++; } } } if (body) { n = ngx_write_chain_to_temp_file(rb->temp_file, body); /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { return NGX_ERROR; } rb->temp_file->offset += n; } return NGX_OK; }
static ngx_int_t ngx_http_filter_cache_header_filter(ngx_http_request_t *r) { ngx_http_filter_cache_ctx_t *ctx = NULL; ngx_http_filter_cache_conf_t *conf = NULL; time_t now, valid; ngx_temp_file_t *tf; ngx_chain_t out; ssize_t offset; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_uint_t i; u_char *p; size_t len; ngx_pool_cleanup_t *cln = NULL; ngx_http_filter_cache_meta_t meta; if(r != r->main) { /*just skip as we got headers in main*/ return ngx_http_next_header_filter(r); } conf = ngx_http_get_module_loc_conf(r, ngx_http_filter_cache_module); switch (ngx_http_test_predicates(r, conf->upstream.no_cache)) { case NGX_ERROR: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, __FILE__" ngx_http_test_predicates returned an error for no_cache"); return NGX_ERROR; case NGX_DECLINED: goto nocache; default: /* NGX_OK */ break; } ctx = r->filter_cache; if(!ctx || (FILTER_DONOTCACHE == ctx->cacheable)) { goto nocache; } /* ngx_http_filter_cache_create(r); */ if (ctx->cache && ctx->cache->file.fd != NGX_INVALID_FILE) { ngx_pool_run_cleanup_file(r->pool, ctx->cache->file.fd); ctx->cache->file.fd = NGX_INVALID_FILE; } ctx->cache->valid_sec = 0; now = ngx_time(); valid = 0; valid = ngx_http_filter_cache_valid(conf->upstream.cache_valid, r->headers_out.status); if (valid) { ctx->cache->valid_sec = now + valid; } else { goto nocache; } tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_ERROR; } tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = conf->upstream.temp_path; tf->pool = r->pool; tf->persistent = 1; if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access) != NGX_OK) { return NGX_ERROR; } ctx->tf = tf; cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = filter_cache_cleanup; cln->data = ctx; ctx->buffer.pos = ctx->buffer.start = ngx_palloc(r->pool, conf->upstream.buffer_size); ctx->buffer.end = ctx->buffer.start + conf->upstream.buffer_size; ctx->buffer.temporary = 1; ctx->buffer.memory = 1; ctx->buffer.last_buf = 1; ctx->buffer.pos += ctx->cache->header_start; ctx->cache->last_modified = r->headers_out.last_modified_time; ctx->cache->date = now; /* Headers */ /* fill in the metadata*/ meta.status = r->headers_out.status; #if (NGX_HTTP_GZIP) meta.gzip_vary = r->gzip_vary; /* Note: there is still some wierdness to how gzip_vary works...*/ #endif meta.last_modified_time = r->headers_out.last_modified_time; ngx_memcpy((void *)(ctx->buffer.pos), (void *)(&meta), sizeof(ngx_http_filter_cache_meta_t) ); ctx->buffer.pos += sizeof(ngx_http_filter_cache_meta_t); /* Headers taht aren't in teh table for some reason */ /*Do we need to try to set it if it's not set???*/ /* Content Type */ if ( r->headers_out.content_type.data ) { p = memchr((void *)r->headers_out.content_type.data, ';', r->headers_out.content_type.len ); if ( p ) { len = p - r->headers_out.content_type.data; ngx_cpystrn( ctx->buffer.pos, r->headers_out.content_type.data, len + 1); ctx->buffer.pos += len + 1; } else { ngx_cpystrn( ctx->buffer.pos, r->headers_out.content_type.data, r->headers_out.content_type.len + 1 ); ctx->buffer.pos += r->headers_out.content_type.len + 1; } } else { *ctx->buffer.pos = (u_char)'\0'; ctx->buffer.pos++; } /* Charset */ if ( r->headers_out.charset.data ) { ngx_cpystrn( ctx->buffer.pos, r->headers_out.charset.data, r->headers_out.charset.len + 1 ); ctx->buffer.pos += r->headers_out.charset.len + 1; } else { *ctx->buffer.pos = (u_char)'\0'; ctx->buffer.pos++; } /* Content Encoding */ if ( r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) { ngx_cpystrn( ctx->buffer.pos, r->headers_out.content_encoding->value.data, r->headers_out.content_encoding->value.len + 1 ); ctx->buffer.pos += r->headers_out.content_encoding->value.len + 1; } else { *ctx->buffer.pos = (u_char)'\0'; ctx->buffer.pos++; } /* Last-Modified */ if(r->headers_out.last_modified_time && r->headers_out.last_modified && r->headers_out.last_modified->value.len) { ngx_cpystrn( ctx->buffer.pos, r->headers_out.last_modified->value.data, r->headers_out.last_modified->value.len + 1 ); ctx->buffer.pos += r->headers_out.last_modified->value.len + 1; } else { *ctx->buffer.pos = (u_char)'\0'; ctx->buffer.pos++; } /* XXX: is last-modified special???*/ /* Everything From the Table */ part = &r->headers_out.headers.part; h = part->elts; for (i=0; /* void */; i++) { if ( i >= part->nelts || !part->nelts ) { if ( part->next == NULL ) { ctx->cacheable = FILTER_CACHEABLE; break; } part = part->next; h = part->elts; i = 0; } /*need to be really sure this header is "valid"*/ /* if(h[i].key.len && h[i].value.len && h[i].hash && h[i].lowcase_key) {*/ /* if(!h[i].lowcase_key) { */ /* if((h[i].lowcase_key = ngx_pnalloc(r->pool, h->key.len +1)) == NULL) { */ /* continue; */ /* } */ /* ngx_strlow(h[i].lowcase_key, h[i].key.data, h[i].key.len); */ /* } */ /* if(!h[i].hash) { */ /* h[i].hash = ngx_hash_key_lc(h[i].key.data, h[i].key.len); */ /* } */ /* if (ngx_hash_find(&conf->upstream.hide_headers_hash, h[i].hash, */ /* h[i].lowcase_key, h[i].key.len)) */ /* { */ /* continue; */ /* } */ if(h[i].key.len && h[i].value.len) { if(find_string_in_array(&(h[i].key), conf->upstream.hide_headers)){ continue; } if ( (ngx_uint_t)(h[i].key.len + h[i].value.len + 4) > (ngx_uint_t)(ctx->buffer.last - ctx->buffer.pos) ) { ctx->cacheable = FILTER_DONOTCACHE; break; } ngx_cpystrn( ctx->buffer.pos, h[i].key.data, h[i].key.len + 1 ); ctx->buffer.pos += h[i].key.len + 1; ngx_cpystrn( ctx->buffer.pos, h[i].value.data, h[i].value.len + 1 ); ctx->buffer.pos += h[i].value.len + 1; } } if(FILTER_CACHEABLE != ctx->cacheable) { goto nocache; } ctx->buffer.last = ctx->buffer.pos; ctx->cache->body_start = (u_short) (ctx->buffer.pos - ctx->buffer.start); ngx_http_filter_cache_set_header(r, ctx->buffer.start); ctx->cache->date = now; /*write to temp file*/ ctx->buffer.pos = ctx->buffer.start; out.buf = &ctx->buffer; out.next = NULL; offset = ngx_write_chain_to_temp_file(tf, &out); tf->offset += offset; r->main_filter_need_in_memory = 1; return ngx_http_next_header_filter(r); nocache: if(ctx) { ctx->cacheable = FILTER_DONOTCACHE; /* if(ctx->cache) { */ /* ngx_http_filter_cache_free(ctx->cache, ctx->tf); */ /* } */ } return ngx_http_next_header_filter(r); }
static ngx_int_t ngx_http_filter_cache_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_filter_cache_ctx_t *ctx = NULL; ssize_t offset = 0; ngx_chain_t *chain_link = NULL; int done = 0; /* ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, */ /* "ngx_http_filter_cache_body_filter start"); */ if (in == NULL) { return ngx_http_next_body_filter(r, in); } ctx = r->main->filter_cache; if (!ctx || (FILTER_CACHEABLE != ctx->cacheable)) { /* ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, */ /* "ngx_http_filter_cache_body_filter not cacheable"); */ return ngx_http_next_body_filter(r, in); } if( ctx->tf->file.fd == NGX_INVALID_FILE ) { /* ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, */ /* "ngx_http_filter_cache_body_filter invalid temp file"); */ return ngx_http_next_body_filter(r, in); } else { ngx_chain_t *cl = NULL; ngx_chain_t *head = NULL; ngx_buf_t *b = NULL; for ( chain_link = in; chain_link != NULL; chain_link = chain_link->next ) { b = chain_link->buf; if(b->pos && b->last) { if(!cl) { head = cl = ngx_alloc_chain_link(r->pool); } else { cl->next = ngx_alloc_chain_link(r->pool); cl = cl->next; } if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; } } if (head) { offset = ngx_write_chain_to_temp_file(ctx->tf, head); ctx->tf->offset += offset; } } r->connection->buffered |= NGX_HTTP_FILTERCACHE_BUFFERED; for ( chain_link = in; chain_link != NULL; chain_link = chain_link->next ) { /* last_in_chain is used for sub requests? also maybe need to find out about ->sync??*/ /* if (chain_link->buf->last_buf || chain_link->buf->last_in_chain) { */ if (chain_link->buf->last_buf) { done = 1; } } if(done) { ngx_http_filter_cache_update(r, ctx->tf); ctx->cacheable = FILTER_CACHEDONE; r->connection->buffered &= ~NGX_HTTP_FILTERCACHE_BUFFERED; } return ngx_http_next_body_filter(r, in); }