diff options
Diffstat (limited to 'src/http/modules/proxy')
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_cache.c | 123 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.c | 34 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.h | 3 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_upstream.c | 20 |
4 files changed, 146 insertions, 34 deletions
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c index b01e5871f..e8e3b5280 100644 --- a/src/http/modules/proxy/ngx_http_proxy_cache.c +++ b/src/http/modules/proxy/ngx_http_proxy_cache.c @@ -79,13 +79,15 @@ int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p) || rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) { - p->header_in->pos += c->ctx.header_size; + p->header_in->pos = p->header_in->start + c->ctx.header_size; if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } + p->header_in->pos = p->header_in->start + c->ctx.header_size; + p->header_in->last = p->header_in->pos; } else if (rc == NGX_DECLINED) { - p->header_in->pos += c->ctx.header_size; + p->header_in->pos = p->header_in->start + c->ctx.header_size; p->header_in->last = p->header_in->pos; } @@ -129,6 +131,11 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) return NGX_ERROR; } + /* reset for the possible parsing the upstream header */ + + p->status = 0; + p->status_count = 0; + ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1); ngx_log_debug(r->connection->log, "http cache status %d '%s'" _ @@ -186,6 +193,8 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) ngx_log_debug(r->connection->log, "HTTP header done"); + c->ctx.file_start = p->header_in->pos - p->header_in->start; + return NGX_OK; } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { @@ -209,9 +218,10 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) { - int rc; - ngx_hunk_t *h; - ngx_chain_t out; + int rc, len, i; + off_t rest; + ngx_hunk_t *h0, *h1; + ngx_chain_t out[2]; ngx_http_request_t *r; r = p->request; @@ -231,12 +241,29 @@ int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) /* we need to allocate all before the header would be sent */ - if (!((h = ngx_calloc_hunk(r->pool)))) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start); + + h0 = NULL; + h1 = NULL; + + if (len) { + if (!((h0 = ngx_calloc_hunk(r->pool)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } - if (!((h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (len < p->cache->ctx.length) { + if (!((h1 = ngx_calloc_hunk(r->pool)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } rc = ngx_http_send_header(r); @@ -247,20 +274,62 @@ int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) return rc; } - /* TODO: part in p->header_in */ + rest = p->cache->ctx.length; - h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST; + if (len) { + if (p->valid_header_in) { + h0->pos = p->header_in->start + p->cache->ctx.file_start; - h->file_pos = p->header_in->pos - p->header_in->start; - h->file_last = h->file_pos + p->cache->ctx.header.length; + if (len > p->cache->ctx.length) { + h0->last = h0->pos + p->cache->ctx.length; - h->file->fd = p->cache->ctx.file.fd; - h->file->log = r->connection->log; - - out.hunk = h; - out.next = NULL; + } else { + h0->last = p->header_in->end; + } + + h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; + } + + h0->type |= NGX_HUNK_FILE; + h0->file_pos = p->cache->ctx.file_start; + + h0->file->fd = p->cache->ctx.file.fd; + h0->file->log = r->connection->log; + + if (len > p->cache->ctx.length) { + h0->file_last = h0->file_pos + p->cache->ctx.length; + rest = 0; + + } else { + h0->file_last = h0->file_pos + len; + rest -= len; + } + + out[0].hunk = h0; + out[0].next = &out[1]; + i = 0; + + } else { + i = -1; + } + + if (rest) { + h1->file_pos = p->cache->ctx.file_start + len; + h1->file_last = h1->file_pos + rest; + h1->type = NGX_HUNK_FILE; + + h1->file->fd = p->cache->ctx.file.fd; + h1->file->log = r->connection->log; + + out[++i].hunk = h1; + } + + out[i].next = NULL; + if (!r->main) { + out[i].hunk->type |= NGX_HUNK_LAST; + } - return ngx_http_output_filter(r, &out); + return ngx_http_output_filter(r, out); } @@ -293,13 +362,13 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) if (date == NGX_ERROR) { date = ngx_time(); } - p->cache->ctx.header.date = date; + p->cache->ctx.date = date; last_modified = NGX_ERROR; if (h->last_modified) { last_modified = ngx_http_parse_time(h->last_modified->value.data, h->last_modified->value.len); - p->cache->ctx.header.last_modified = last_modified; + p->cache->ctx.last_modified = last_modified; } if (h->x_accel_expires) { @@ -307,7 +376,7 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) h->x_accel_expires->value.len); if (expires != NGX_ERROR) { p->state->reason = NGX_HTTP_PROXY_CACHE_XAE; - p->cache->ctx.header.expires = date + expires; + p->cache->ctx.expires = date + expires; return (expires > 0); } } @@ -321,7 +390,7 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) h->expires->value.len); if (expires != NGX_ERROR) { p->state->reason = NGX_HTTP_PROXY_CACHE_EXP; - p->cache->ctx.header.expires = expires; + p->cache->ctx.expires = expires; return (date < expires); } } @@ -329,7 +398,7 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) { p->state->reason = NGX_HTTP_PROXY_CACHE_MVD; - p->cache->ctx.header.expires = /* STUB: 1 hour */ 60 * 60; + p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60; return 1; } @@ -339,17 +408,17 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) { - /* FIXME: time_t == int_64_t */ + /* FIXME: time_t == int_64_t, we can use fpu */ p->state->reason = NGX_HTTP_PROXY_CACHE_LMF; - p->cache->ctx.header.expires = ngx_time() + p->cache->ctx.expires = ngx_time() + (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100; return 1; } if (p->lcf->default_expires > 0) { p->state->reason = NGX_HTTP_PROXY_CACHE_PDE; - p->cache->ctx.header.expires = p->lcf->default_expires; + p->cache->ctx.expires = p->lcf->default_expires; return 1; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 8aa6e6823..860ba7ac7 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -131,6 +131,14 @@ static ngx_command_t ngx_http_proxy_commands[] = { NULL }, + { ngx_string("proxy_busy_lock"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, + ngx_http_set_busy_lock_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, busy_lock), + NULL }, + + { ngx_string("proxy_pass_server"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -255,6 +263,8 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } + ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t)); + if (!p->lcf->cache) { p->state->cache = NGX_HTTP_PROXY_CACHE_PASS; @@ -280,6 +290,8 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) rc = ngx_http_proxy_get_cached_response(p); + p->valid_header_in = 1; + if (rc == NGX_OK) { return ngx_http_proxy_send_cached_response(p); } @@ -406,6 +418,8 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->cache_path = NULL; conf->temp_path = NULL; + conf->busy_lock = NULL; + */ conf->request_buffer_size = NGX_CONF_UNSET; @@ -482,6 +496,26 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, ngx_conf_merge_value(conf->cache, prev->cache, 0); + + /* conf->cache must be merged */ + + if (conf->busy_lock == NULL) { + conf->busy_lock = prev->busy_lock; + } + + if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) { + + /* 16 bytes are 128 bits of the md5 */ + + /* ngx_alloc_shared() */ + conf->busy_lock->busy = ngx_palloc(cf->pool, + 16 * conf->busy_lock->max_conn); + if (conf->busy_lock->busy == NULL) { + return NGX_CONF_ERROR; + } + } + + ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0); ngx_conf_merge_value(conf->pass_x_accel_expires, prev->pass_x_accel_expires, 0); diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h index f3334b25e..6e4b08429 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -73,6 +73,8 @@ typedef struct { ngx_path_t *cache_path; ngx_path_t *temp_path; + ngx_http_busy_lock_t *busy_lock; + ngx_http_proxy_upstream_conf_t *upstream; ngx_peers_t *peers; } ngx_http_proxy_loc_conf_t; @@ -143,6 +145,7 @@ struct ngx_http_proxy_ctx_s { unsigned cachable:1; unsigned stale:1; + unsigned valid_header_in:1; unsigned request_sent:1; unsigned header_sent:1; diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index 3c9118e7b..cee93ee65 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -300,6 +300,9 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p) p->header_in->last = p->header_in->start; } } + + p->status = 0; + p->status_count = 0; } @@ -557,6 +560,8 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev) return; } + p->valid_header_in = 0; + p->upstream->peer.cached = 0; rc = ngx_http_proxy_parse_status_line(p); @@ -811,7 +816,7 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) int rc; ngx_event_pipe_t *ep; ngx_http_request_t *r; - ngx_http_cache_file_t *header; + ngx_http_cache_header_t *header; ngx_http_core_loc_conf_t *clcf; r = p->request; @@ -836,14 +841,15 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) p->header_sent = 1; - if (p->cache) { - header = (ngx_http_cache_file_t *) p->header_in->start; + if (p->cachable) { + header = (ngx_http_cache_header_t *) p->header_in->start; - /* STUB */ - header->header.expires = 0; - header->header.last_modified = 0; + header->expires = p->cache->ctx.expires; + header->last_modified = p->cache->ctx.last_modified; + header->date = p->cache->ctx.date; + /* TODO: r->headers_out.content_length_n == -1 */ + header->length = r->headers_out.content_length_n; - header->header.length = r->headers_out.content_length_n; header->key_len = p->cache->ctx.key.len; ngx_memcpy(&header->key, p->cache->ctx.key.data, header->key_len); header->key[header->key_len] = LF; |
