diff options
author | Igor Sysoev <igor@sysoev.ru> | 2006-04-05 13:40:54 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2006-04-05 13:40:54 +0000 |
commit | 6d16e1e1df3e9a68b3dabd583ea2361867b9aa83 (patch) | |
tree | 1375fdd9994ce3915280665135ea29d531e284c8 /src/http/modules/proxy/ngx_http_proxy_cache.c | |
parent | 0d20332bb895aa144d976b5deceef95df7572c6b (diff) | |
download | nginx-6d16e1e1df3e9a68b3dabd583ea2361867b9aa83.tar.gz nginx-6d16e1e1df3e9a68b3dabd583ea2361867b9aa83.zip |
nginx-0.3.36-RELEASE importrelease-0.3.36
*) Feature: the ngx_http_addition_filter_module.
*) Feature: the "proxy_pass" and "fastcgi_pass" directives may be used
inside the "if" block.
*) Feature: the "proxy_ignore_client_abort" and
"fastcgi_ignore_client_abort" directives.
*) Feature: the "$request_completion" variable.
*) Feature: the ngx_http_perl_module supports the $r->request_method
and $r->remote_addr.
*) Feature: the ngx_http_ssi_module supports the "elif" command.
*) Bugfix: the "\/" string in the expression of the "if" command of the
ngx_http_ssi_module was treated incorrectly.
*) Bugfix: in the regular expressions in the "if" command of the
ngx_http_ssi_module.
*) Bugfix: if the relative path was specified in the
"client_body_temp_path", "proxy_temp_path", "fastcgi_temp_path", and
"perl_modules" directives, then the directory was used relatively to
a current path but not to a server prefix.
Diffstat (limited to 'src/http/modules/proxy/ngx_http_proxy_cache.c')
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_cache.c | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c deleted file mode 100644 index 86b8424c6..000000000 --- a/src/http/modules/proxy/ngx_http_proxy_cache.c +++ /dev/null @@ -1,628 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - */ - - -#include <ngx_config.h> -#include <ngx_core.h> -#include <ngx_http.h> -#include <ngx_http_proxy_handler.h> - - -static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p, - int rc); -static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p); -static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p); - - -int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p) -{ - char *last; - ngx_http_request_t *r; - ngx_http_proxy_cache_t *c; - ngx_http_proxy_upstream_conf_t *u; - - r = p->request; - - if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - p->cache = c; - - c->ctx.file.fd = NGX_INVALID_FILE; - c->ctx.file.log = r->connection->log; - c->ctx.path = p->lcf->cache_path; - - u = p->lcf->upstream; - - c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len; - if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len); - - last = ngx_cpymem(last, r->uri.data + u->location->len, - r->uri.len - u->location->len); - - if (r->args.len > 0) { - *(last++) = '?'; - last = ngx_cpymem(last, r->args.data, r->args.len); - } - *last = '\0'; - - p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size); - if (p->header_in == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; - - c->ctx.buf = p->header_in; - c->ctx.log = r->connection->log; - - return ngx_http_proxy_process_cached_response(p, - ngx_http_cache_get_file(r, &c->ctx)); -} - - -static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p, - int rc) -{ - if (rc == NGX_OK) { - p->state->cache_state = NGX_HTTP_PROXY_CACHE_HIT; - p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; - - if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - p->valid_header_in = 1; - - return ngx_http_proxy_send_cached_response(p); - } - - if (rc == NGX_HTTP_CACHE_STALE) { - p->state->cache_state = NGX_HTTP_PROXY_CACHE_EXPR; - - } else if (rc == NGX_HTTP_CACHE_AGED) { - p->state->cache_state = NGX_HTTP_PROXY_CACHE_AGED; - } - - if (rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) { - p->state->expired = ngx_time() - p->cache->ctx.expires; - p->header_in->pos = p->header_in->start + p->cache->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 + p->cache->ctx.header_size; - p->header_in->last = p->header_in->pos; - - p->stale = 1; - p->valid_header_in = 1; - - } else if (rc == NGX_DECLINED) { - p->state->cache_state = NGX_HTTP_PROXY_CACHE_MISS; - p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; - p->header_in->last = p->header_in->pos; - } - - if (p->lcf->busy_lock) { - p->try_busy_lock = 1; - - p->header_in->pos = p->header_in->start; - p->header_in->last = p->header_in->start; - - p->busy_lock.time = 0; - p->busy_lock.event = p->request->connection->read; - p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler; - p->busy_lock.md5 = p->cache->ctx.md5; - - ngx_http_proxy_cache_busy_lock(p); - return NGX_DONE; - } - - return ngx_http_proxy_request_upstream(p); -} - - -static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) -{ - int rc, i; - ngx_table_elt_t *h; - ngx_http_request_t *r; - ngx_http_proxy_cache_t *c; - - rc = ngx_http_proxy_parse_status_line(p); - - c = p->cache; - r = p->request; - - if (rc == NGX_AGAIN) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "\"proxy_header_buffer_size\" " - "is too small to read header from \"%s\"", - c->ctx.file.name.data); - return NGX_ERROR; - } - - if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no valid HTTP/1.0 header in \"%s\"", - c->ctx.file.name.data); - return NGX_ERROR; - } - - /* rc == NGX_OK */ - - c->status = p->status; - c->status_line.len = p->status_end - p->status_start; - c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1); - if (c->status_line.data == NULL) { - 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_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http cache status %ui \"%V\"", - c->status, &c->status_line); - - /* TODO: ngx_init_table */ - c->headers_in.headers = ngx_create_table(r->pool, 20); - - for ( ;; ) { - rc = ngx_http_parse_header_line(r, p->header_in); - - if (rc == NGX_OK) { - - /* a header line has been parsed successfully */ - - h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in); - if (h == NULL) { - return NGX_ERROR; - } - - h->key.len = r->header_name_end - r->header_name_start; - h->value.len = r->header_end - r->header_start; - - h->key.data = ngx_palloc(r->pool, - h->key.len + 1 + h->value.len + 1); - if (h->key.data == NULL) { - return NGX_ERROR; - } - - h->value.data = h->key.data + h->key.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); - - for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) { - if (ngx_http_proxy_headers_in[i].name.len != h->key.len) { - continue; - } - - if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data, - h->key.data) == 0) - { - *((ngx_table_elt_t **) ((char *) &c->headers_in - + ngx_http_proxy_headers_in[i].offset)) = h; - break; - } - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http cache header: \"%V: %V\"", &h->key, &h->value); - - continue; - - } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { - - /* a whole header has been parsed successfully */ - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http cache 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) { - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "invalid header in \"%s\"", - c->ctx.file.name.data); - return NGX_ERROR; - } - - /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */ - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "\"proxy_header_buffer_size\" " - "is too small to read header from \"%s\"", - c->ctx.file.name.data); - return NGX_ERROR; - } -} - - -void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p) -{ - int rc, ft_type; - - rc = ngx_http_busy_lock_cachable(p->lcf->busy_lock, &p->busy_lock, - p->try_busy_lock); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, - "http cache busy lock cachable: %d", rc); - - if (rc == NGX_OK) { - if (p->try_busy_lock) { - p->busy_locked = 1; - p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; - p->header_in->last = p->header_in->pos; - - ngx_http_proxy_request_upstream(p); - return; - } - - ngx_http_proxy_cache_look_complete_request(p); - return; - } - - p->try_busy_lock = 0; - - if (p->cache->ctx.file.fd != NGX_INVALID_FILE - && !p->cache->ctx.file.info_valid) - { - if (ngx_fd_info(p->cache->ctx.file.fd, &p->cache->ctx.file.info) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_CRIT, p->request->connection->log, ngx_errno, - ngx_fd_info_n " \"%s\" failed", - p->cache->ctx.file.name.data); - ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - p->cache->ctx.file.info_valid = 1; - } - - if (rc == NGX_AGAIN) { - - if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_USE_KQUEUE_EVENT)) - && !p->request->connection->write->active) - { - /* - * kqueue allows to detect when client closes prematurely - * connection - */ - - p->request->connection->write->event_handler = - ngx_http_proxy_check_broken_connection; - - if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT, - NGX_CLEAR_EVENT) == NGX_ERROR) - { - ngx_http_proxy_finalize_request(p, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - } - - return; - } - - ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock); - - if (rc == NGX_DONE) { - ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK; - - } else { - /* rc == NGX_ERROR */ - ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING; - } - - if (p->stale && (p->lcf->use_stale & ft_type)) { - ngx_http_proxy_finalize_request(p, - ngx_http_proxy_send_cached_response(p)); - return; - } - - p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE; - ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE); -} - - -static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p) -{ - int rc; - ngx_http_cache_ctx_t *ctx; - - if (!(ctx = ngx_pcalloc(p->request->pool, sizeof(ngx_http_cache_ctx_t)))) { - ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - *ctx = p->cache->ctx; - - rc = ngx_http_cache_open_file(ctx, ngx_file_uniq(&p->cache->ctx.file.info)); - - if (rc == NGX_DECLINED || rc == NGX_HTTP_CACHE_THE_SAME) { - p->try_busy_lock = 1; - p->busy_lock.time = 0; - ngx_http_proxy_cache_busy_lock(p); - return; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, - "http cache old fd:%d, new fd:%d", - p->cache->ctx.file.fd, ctx->file.fd); - - if (p->cache->ctx.file.fd != NGX_INVALID_FILE) { - if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, p->request->connection->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - p->cache->ctx.file.name.data); - } - } - - p->cache->ctx = *ctx; - - p->status = 0; - p->status_count = 0; - - ngx_http_proxy_finalize_request(p, - ngx_http_proxy_process_cached_response(p, rc)); -} - - -int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) -{ - 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; - - r->headers_out.status = p->cache->status; - -#if 0 - r->headers_out.content_length_n = -1; - r->headers_out.content_length = NULL; -#endif - - /* copy an cached header to r->headers_out */ - - if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - /* we need to allocate all before the header would be sent */ - - 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 (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); - - /* NEEDED ??? */ p->header_sent = 1; - - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - return rc; - } - - rest = p->cache->ctx.length; - - if (len) { - if (p->valid_header_in) { - h0->pos = p->header_in->start + p->cache->ctx.file_start; - - if (len > p->cache->ctx.length) { - h0->last = h0->pos + p->cache->ctx.length; - - } 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; - } - - r->file.fd = p->cache->ctx.file.fd; - - return ngx_http_output_filter(r, out); -} - - -int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) -{ - time_t date, last_modified, expires, t; - ngx_http_proxy_headers_in_t *h; - - switch (p->upstream->status) { - case NGX_HTTP_OK: - case NGX_HTTP_MOVED_PERMANENTLY: - case NGX_HTTP_MOVED_TEMPORARILY: - break; - -#if 0 - case NGX_HTTP_NOT_MODIFIED: - return 1; -#endif - - default: - return 0; - } - - h = &p->upstream->headers_in; - - date = NGX_ERROR; - if (h->date) { - date = ngx_http_parse_time(h->date->value.data, h->date->value.len); - } - if (date == NGX_ERROR) { - date = ngx_time(); - } - 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.last_modified = last_modified; - } - - if (h->x_accel_expires) { - expires = ngx_atoi(h->x_accel_expires->value.data, - h->x_accel_expires->value.len); - if (expires != NGX_ERROR) { - p->state->reason = NGX_HTTP_PROXY_CACHE_XAE; - p->state->expires = expires; - p->cache->ctx.expires = date + expires; - return (expires > 0); - } - } - - if (!p->lcf->ignore_expires) { - - /* TODO: Cache-Control: no-cache, max-age= */ - - if (h->expires) { - expires = ngx_http_parse_time(h->expires->value.data, - h->expires->value.len); - if (expires != NGX_ERROR) { - p->state->reason = NGX_HTTP_PROXY_CACHE_EXP; - p->state->expires = expires - date; - p->cache->ctx.expires = expires; - return (date < expires); - } - } - } - - if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) { - p->state->reason = NGX_HTTP_PROXY_CACHE_MVD; - p->state->expires = /* STUB: 1 hour */ 60 * 60; - p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60; - return 1; - } - - if (p->upstream->status == NGX_HTTP_MOVED_TEMPORARILY) { - return 1; - } - - if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) { - - /* FIXME: time_t == int_64_t, we can use fpu */ - - p->state->reason = NGX_HTTP_PROXY_CACHE_LMF; - t = (time_t) - ((((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100); - p->state->expires = t; - p->cache->ctx.expires = ngx_time() + t; - return 1; - } - - if (p->lcf->default_expires > 0) { - p->state->reason = NGX_HTTP_PROXY_CACHE_PDE; - p->state->expires = p->lcf->default_expires; - p->cache->ctx.expires = ngx_time() + p->lcf->default_expires; - return 1; - } - - return 0; -} - - -int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) -{ - ngx_event_pipe_t *ep; - - if (p->cache == NULL) { - return NGX_OK; - } - - ep = p->upstream->event_pipe; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, - "http cache update len: %O:%O", - p->cache->ctx.length, ep->read_length); - - if (p->cache->ctx.length == -1) { - /* TODO: test rc */ - ngx_write_file(&ep->temp_file->file, - (char *) &ep->read_length, sizeof(off_t), - offsetof(ngx_http_cache_header_t, length)); - } - - return ngx_http_cache_update_file(p->request, &p->cache->ctx, - &ep->temp_file->file.name); -} |