nginx-0.0.1-2003-11-04-01:20:44 import
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
index 6309b39..b01e587 100644
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -56,11 +56,29 @@
rc = ngx_http_cache_get_file(r, &c->ctx);
- if (rc == NGX_STALE) {
+ switch (rc) {
+ case NGX_HTTP_CACHE_STALE:
p->stale = 1;
+ p->state->cache = NGX_HTTP_PROXY_CACHE_EXPR;
+ break;
+
+ case NGX_HTTP_CACHE_AGED:
+ p->stale = 1;
+ p->state->cache = NGX_HTTP_PROXY_CACHE_AGED;
+ break;
+
+ case NGX_OK:
+ p->state->cache = NGX_HTTP_PROXY_CACHE_HIT;
+ break;
+
+ default:
+ p->state->cache = NGX_HTTP_PROXY_CACHE_MISS;
}
- if (rc == NGX_OK || rc == NGX_STALE) {
+ if (rc == NGX_OK
+ || rc == NGX_HTTP_CACHE_STALE
+ || rc == NGX_HTTP_CACHE_AGED)
+ {
p->header_in->pos += c->ctx.header_size;
if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -246,6 +264,99 @@
}
+int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p)
+{
+ time_t date, last_modified, expires;
+ 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.header.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;
+ }
+
+ 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->cache->ctx.header.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->cache->ctx.header.expires = expires;
+ return (date < expires);
+ }
+ }
+ }
+
+ 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;
+ 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 */
+
+ p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
+ p->cache->ctx.header.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;
+ return 1;
+ }
+
+ return 0;
+}
+
+
int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p)
{
if (p->cache == NULL) {
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 7c9fa9e..8aa6e68 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -38,6 +38,12 @@
{ ngx_null_string, 0 }
};
+
+static ngx_conf_num_bounds_t ngx_http_proxy_lm_factor_bounds = {
+ ngx_conf_check_num_bounds, 0, 100
+};
+
+
static ngx_command_t ngx_http_proxy_commands[] = {
{ ngx_string("proxy_pass"),
@@ -124,6 +130,7 @@
offsetof(ngx_http_proxy_loc_conf_t, cache),
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,
@@ -131,6 +138,35 @@
offsetof(ngx_http_proxy_loc_conf_t, pass_server),
NULL },
+ { ngx_string("proxy_pass_x_accel_expires"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, pass_x_accel_expires),
+ NULL },
+
+ { ngx_string("proxy_ignore_expires"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, ignore_expires),
+ NULL },
+
+ { ngx_string("proxy_lm_factor"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, lm_factor),
+ &ngx_http_proxy_lm_factor_bounds },
+
+ { ngx_string("proxy_default_expires"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_sec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, default_expires),
+ NULL },
+
+
{ ngx_string("proxy_next_upstream"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
ngx_conf_set_bitmask_slot,
@@ -199,8 +235,6 @@
static int ngx_http_proxy_handler(ngx_http_request_t *r)
{
int rc;
- char *last;
- ngx_http_cache_ctx_t *cctx;
ngx_http_proxy_ctx_t *p;
ngx_http_create_ctx(r, p, ngx_http_proxy_module,
@@ -213,7 +247,34 @@
/* TODO: we currently support reverse proxy only */
p->accel = 1;
- if (!p->lcf->cache || r->bypass_cache) {
+ ngx_init_array(p->states, r->pool, p->lcf->peers->number,
+ sizeof(ngx_http_proxy_state_t),
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+ if (!(p->state = ngx_push_array(&p->states))) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+
+ if (!p->lcf->cache) {
+ p->state->cache = NGX_HTTP_PROXY_CACHE_PASS;
+
+ } else if (r->bypass_cache) {
+ p->state->cache = NGX_HTTP_PROXY_CACHE_BYPASS;
+
+ } else if (r->headers_in.authorization) {
+ p->state->cache = NGX_HTTP_PROXY_CACHE_AUTH;
+
+ } else if (r->no_cache) {
+ p->state->cache = NGX_HTTP_PROXY_CACHE_PGNC;
+ p->cachable = 1;
+
+ } else {
+ p->cachable = 1;
+ }
+
+
+ if (p->state->cache) {
return ngx_http_proxy_request_upstream(p);
}
@@ -227,27 +288,9 @@
return rc;
}
- if (rc == NGX_DECLINED || rc == NGX_STALE) {
- return ngx_http_proxy_request_upstream(p);
- }
+ /* rc == NGX_DECLINED || NGX_HTTP_CACHE_STALE || NGX_HTTP_CACHE_AGED */
- return NGX_DONE;
-}
-
-
-int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status)
-{
- ngx_http_proxy_state_t *state;
-
- if (!(state = ngx_push_array(&p->states))) {
- return NGX_ERROR;
- }
-
- state->status = status;
- state->peer =
- &p->upstream->peer.peers->peers[p->upstream->peer.cur_peer].addr_port_text;
-
- return NGX_OK;
+ return ngx_http_proxy_request_upstream(p);
}
@@ -386,6 +429,10 @@
conf->cache = NGX_CONF_UNSET;
conf->pass_server = NGX_CONF_UNSET;
+ conf->pass_x_accel_expires = NGX_CONF_UNSET;
+ conf->ignore_expires = NGX_CONF_UNSET;
+ conf->lm_factor = NGX_CONF_UNSET;
+ conf->default_expires = NGX_CONF_UNSET;
return conf;
}
@@ -436,6 +483,11 @@
ngx_conf_merge_value(conf->cache, prev->cache, 0);
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);
+ ngx_conf_merge_value(conf->ignore_expires, prev->ignore_expires, 0);
+ ngx_conf_merge_value(conf->lm_factor, prev->lm_factor, 0);
+ ngx_conf_merge_sec_value(conf->default_expires, prev->default_expires, 0);
return NULL;
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index f29498f..f3334b2 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -10,6 +10,29 @@
#include <ngx_http.h>
+typedef enum {
+ NGX_HTTP_PROXY_CACHE_PASS = 1,
+ NGX_HTTP_PROXY_CACHE_BYPASS,
+ NGX_HTTP_PROXY_CACHE_AUTH,
+ NGX_HTTP_PROXY_CACHE_PGNC,
+ NGX_HTTP_PROXY_CACHE_MISS,
+ NGX_HTTP_PROXY_CACHE_EXPR,
+ NGX_HTTP_PROXY_CACHE_AGED,
+ NGX_HTTP_PROXY_CACHE_HIT
+} ngx_http_proxy_state_e;
+
+
+typedef enum {
+ NGX_HTTP_PROXY_CACHE_BPS = 1,
+ NGX_HTTP_PROXY_CACHE_XAE,
+ NGX_HTTP_PROXY_CACHE_CTL,
+ NGX_HTTP_PROXY_CACHE_EXP,
+ NGX_HTTP_PROXY_CACHE_MVD,
+ NGX_HTTP_PROXY_CACHE_LMF,
+ NGX_HTTP_PROXY_CACHE_PDE
+} ngx_http_proxy_reason_e;
+
+
typedef struct {
ngx_str_t url;
ngx_str_t host;
@@ -36,7 +59,13 @@
int cyclic_temp_file;
int cache;
+
int pass_server;
+ int pass_x_accel_expires;
+
+ int ignore_expires;
+ int lm_factor;
+ int default_expires;
int next_upstream;
int use_stale;
@@ -50,6 +79,8 @@
typedef struct {
+ ngx_http_proxy_state_e cache;
+ ngx_http_proxy_reason_e reason;
int status;
ngx_str_t *peer;
} ngx_http_proxy_state_t;
@@ -122,8 +153,9 @@
char *status_start;
char *status_end;
int status_count;
- int state;
+ int parse_state;
+ ngx_http_proxy_state_t *state;
ngx_array_t states; /* of ngx_http_proxy_state_t */
char *action;
@@ -134,6 +166,7 @@
#define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
+
#define NGX_HTTP_PROXY_FT_ERROR 2
#define NGX_HTTP_PROXY_FT_TIMEOUT 4
#define NGX_HTTP_PROXY_FT_INVALID_HEADER 8
@@ -147,9 +180,9 @@
int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p);
int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p);
+int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status);
size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len);
void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
void ngx_http_proxy_close_connection(ngx_connection_t *c);
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
index 18e2797..4dda797 100644
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ b/src/http/modules/proxy/ngx_http_proxy_header.c
@@ -26,6 +26,12 @@
|| &h[i] == headers_in->accept_ranges) {
continue;
}
+
+ if (&h[i] == headers_in->x_accel_expires
+ && !p->lcf->pass_x_accel_expires)
+ {
+ continue;
+ }
if (&h[i] == headers_in->server && !p->lcf->pass_server) {
continue;
diff --git a/src/http/modules/proxy/ngx_http_proxy_parse.c b/src/http/modules/proxy/ngx_http_proxy_parse.c
index 85c406e..1729542 100644
--- a/src/http/modules/proxy/ngx_http_proxy_parse.c
+++ b/src/http/modules/proxy/ngx_http_proxy_parse.c
@@ -26,7 +26,7 @@
sw_done
} state;
- state = p->state;
+ state = p->parse_state;
pos = p->header_in->pos;
while (pos < p->header_in->last && state < sw_done) {
@@ -195,10 +195,10 @@
p->status_end = pos - 1;
}
- p->state = sw_start;
+ p->parse_state = sw_start;
return NGX_OK;
}
- p->state = state;
+ p->parse_state = state;
return NGX_AGAIN;
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index f969f33..3c9118e 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -17,7 +17,6 @@
static void ngx_http_proxy_dummy_handler(ngx_event_t *wev);
static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
-static void ngx_http_proxy_process_upstream_header(ngx_http_proxy_ctx_t *p);
static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
static void ngx_http_proxy_process_body(ngx_event_t *ev);
@@ -59,14 +58,8 @@
u->peer.peers = p->lcf->peers;
u->peer.tries = p->lcf->peers->number;
- ngx_init_array(p->states, r->pool, u->peer.tries,
- sizeof(ngx_http_proxy_state_t),
- NGX_HTTP_INTERNAL_SERVER_ERROR);
-
u->method = r->method;
- /* STUB */ p->cachable = p->lcf->cache;
-
if (r->headers_in.content_length_n > 0) {
if (!(r->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -313,7 +306,6 @@
static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
{
int rc;
- ngx_chain_t *cl;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_output_chain_ctx_t *octx;
@@ -327,6 +319,9 @@
return;
}
+ p->state->peer =
+ &p->upstream->peer.peers->peers[p->upstream->peer.cur_peer].addr_port_text;
+
if (rc == NGX_CONNECT_ERROR) {
ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
return;
@@ -367,6 +362,11 @@
p->request_sent = 0;
+ if (!(p->state = ngx_push_array(&p->states))) {
+ ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
if (rc == NGX_AGAIN) {
ngx_add_timer(c->write, p->lcf->connect_timeout);
return;
@@ -731,7 +731,12 @@
ngx_log_debug(c->log, "HTTP header done");
- ngx_http_proxy_process_upstream_header(p);
+ /* TODO: hook to process the upstream header */
+
+ if (p->cachable) {
+ p->cachable = ngx_http_proxy_is_cachable(p);
+ }
+
ngx_http_proxy_send_response(p);
return;
@@ -759,17 +764,6 @@
}
-static void ngx_http_proxy_process_upstream_header(ngx_http_proxy_ctx_t *p)
-{
- time_t expires;
-
- expires = ngx_http_parse_time(p->upstream->headers_in.expires->value.data,
- p->upstream->headers_in.expires->value.len);
-
- p->cache->ctx.header.expires = expires;
-}
-
-
static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
{
ssize_t n;
@@ -814,8 +808,7 @@
static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
{
- int rc, i;
- ngx_table_elt_t *ho, *h;
+ int rc;
ngx_event_pipe_t *ep;
ngx_http_request_t *r;
ngx_http_cache_file_t *header;
@@ -995,13 +988,13 @@
}
if (p->upstream->peer.connection) {
- if (ep->upstream_done) {
+ if (ep->upstream_done && p->cachable) {
if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
ngx_http_proxy_finalize_request(p, 0);
return;
}
- } else if (ep->upstream_eof) {
+ } else if (ep->upstream_eof && p->cachable) {
/* TODO: check length & update cache */
@@ -1086,10 +1079,7 @@
}
if (status) {
- if (ngx_http_proxy_log_state(p, status) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
+ p->state->status = status;
if (p->upstream->peer.tries == 0 || !(p->lcf->next_upstream & ft_type))
{
diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c
index b3a7e46..4e7cf0e 100644
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -80,9 +80,11 @@
ctx->buf->last += n;
if (ctx->header.expires < ngx_time()) {
- return NGX_STALE;
+ return NGX_HTTP_CACHE_STALE;
}
+ /* TODO: NGX_HTTP_CACHE_AGED */
+
return NGX_OK;
}
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index 9e491ad..f10dc99 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -9,6 +9,7 @@
typedef struct {
time_t expires;
time_t last_modified;
+ time_t date;
off_t length;
} ngx_http_cache_header_t;
@@ -44,7 +45,8 @@
} ngx_http_cache_ctx_t;
-#define NGX_STALE 1
+#define NGX_HTTP_CACHE_STALE 1
+#define NGX_HTTP_CACHE_AGED 2
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx);
diff --git a/src/http/ngx_http_headers.c b/src/http/ngx_http_headers.c
index b8773cb..a77483a 100644
--- a/src/http/ngx_http_headers.c
+++ b/src/http/ngx_http_headers.c
@@ -20,6 +20,9 @@
{ ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
#endif
+ { ngx_string("Authorization"),
+ offsetof(ngx_http_headers_in_t, authorization) },
+
{ ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
{ ngx_null_string, 0 }
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 7f05b40..8e50d59 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -79,6 +79,8 @@
ngx_table_elt_t *accept_encoding;
ngx_table_elt_t *range;
+ ngx_table_elt_t *authorization;
+
ngx_table_elt_t *keep_alive;
size_t host_name_len;
@@ -198,6 +200,7 @@
unsigned proxy:1;
unsigned bypass_cache:1;
+ unsigned no_cache:1;
#if 0
unsigned cachable:1;