mirror of
https://github.com/nginx/nginx.git
synced 2024-12-27 17:31:35 -06:00
nginx-0.0.1-2003-11-03-01:56:18 import
This commit is contained in:
parent
fe0f5cc6e1
commit
659774979f
@ -150,6 +150,8 @@ typedef struct {
|
||||
} ngx_conf_num_bounds_t;
|
||||
|
||||
|
||||
#define NGX_CONF_BITMASK_SET 1
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
int mask;
|
||||
|
@ -12,7 +12,7 @@ int ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain)
|
||||
int rc;
|
||||
|
||||
if (tf->file.fd == NGX_INVALID_FILE) {
|
||||
rc = ngx_create_temp_file(&tf->file, &tf->path, tf->pool,
|
||||
rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool,
|
||||
tf->persistent);
|
||||
|
||||
if (rc == NGX_ERROR || rc == NGX_AGAIN) {
|
||||
@ -24,7 +24,7 @@ int ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain)
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_write_chain_to_file(&tf->file, chain, tf->file.offset, tf->pool);
|
||||
return ngx_write_chain_to_file(&tf->file, chain, tf->offset, tf->pool);
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
ngx_file_t file;
|
||||
ngx_path_t path;
|
||||
off_t offset;
|
||||
ngx_path_t *path;
|
||||
ngx_pool_t *pool;
|
||||
char *warn;
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define NGX_HUNK_RECYCLED 0x0010
|
||||
|
||||
/* the hunk is in file */
|
||||
#define NGX_HUNK_FILE 0x0100
|
||||
#define NGX_HUNK_FILE 0x0020
|
||||
|
||||
#define NGX_HUNK_STORAGE (NGX_HUNK_IN_MEMORY \
|
||||
|NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP \
|
||||
@ -30,9 +30,12 @@
|
||||
|
||||
/* in thread state flush means to write the hunk completely before return */
|
||||
/* in event state flush means to start to write the hunk */
|
||||
#define NGX_HUNK_FLUSH 0x1000
|
||||
#define NGX_HUNK_FLUSH 0x0100
|
||||
/* last hunk */
|
||||
#define NGX_HUNK_LAST 0x2000
|
||||
#define NGX_HUNK_LAST 0x0200
|
||||
|
||||
|
||||
#define NGX_HUNK_PREREAD 0x2000
|
||||
#define NGX_HUNK_LAST_SHADOW 0x4000
|
||||
#define NGX_HUNK_TEMP_FILE 0x8000
|
||||
|
||||
|
@ -169,8 +169,12 @@ ngx_inline static int ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->sendfile && (!(hunk->type & NGX_HUNK_IN_MEMORY))) {
|
||||
return 1;
|
||||
if (!ctx->sendfile) {
|
||||
if (!(hunk->type & NGX_HUNK_IN_MEMORY)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
hunk->type &= ~NGX_HUNK_FILE;
|
||||
}
|
||||
|
||||
if (ctx->need_in_memory && (!(hunk->type & NGX_HUNK_IN_MEMORY))) {
|
||||
|
@ -380,7 +380,9 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
|
||||
for (i = 0; i < events; i++) {
|
||||
|
||||
#if (NGX_DEBUG_EVENT)
|
||||
if (event_list[i].ident > 0x8000000) {
|
||||
if (event_list[i].ident > 0x8000000
|
||||
&& event_list[i].ident != (unsigned) -1)
|
||||
{
|
||||
ngx_log_debug(log,
|
||||
"kevent: %08x: ft:%d fl:%08x ff:%08x d:%d ud:%08x" _
|
||||
event_list[i].ident _ event_list[i].filter _
|
||||
|
@ -22,6 +22,7 @@ typedef struct {
|
||||
|
||||
struct ngx_event_s {
|
||||
void *data;
|
||||
/* TODO rename to handler, move flags to struct start */
|
||||
void (*event_handler)(ngx_event_t *ev);
|
||||
|
||||
void *context;
|
||||
|
@ -42,24 +42,28 @@ int ngx_event_pipe(ngx_event_pipe_t *p, int do_write)
|
||||
do_write = 1;
|
||||
}
|
||||
|
||||
rev = p->upstream->read;
|
||||
if (p->upstream->fd != -1) {
|
||||
rev = p->upstream->read;
|
||||
|
||||
if (ngx_handle_read_event(rev, (rev->eof || rev->error)) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
if (ngx_handle_read_event(rev, (rev->eof || rev->error)) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
if (rev->active) {
|
||||
ngx_add_timer(rev, p->read_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
if (rev->active) {
|
||||
ngx_add_timer(rev, p->read_timeout);
|
||||
}
|
||||
if (p->downstream->fd != -1) {
|
||||
wev = p->downstream->write;
|
||||
|
||||
wev = p->downstream->write;
|
||||
if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
if (wev->active) {
|
||||
ngx_add_timer(wev, p->send_timeout);
|
||||
if (wev->active) {
|
||||
ngx_add_timer(wev, p->send_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
@ -166,7 +170,9 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
|
||||
|
||||
break;
|
||||
|
||||
} else if (p->cachable || p->temp_offset < p->max_temp_file_size) {
|
||||
} else if (p->cachable
|
||||
|| p->temp_file->offset < p->max_temp_file_size)
|
||||
{
|
||||
|
||||
/*
|
||||
* if it's allowed then save some hunks from r->in
|
||||
@ -175,7 +181,7 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
|
||||
|
||||
rc = ngx_event_pipe_write_chain_to_temp_file(p);
|
||||
|
||||
ngx_log_debug(p->log, "temp offset: %d" _ p->temp_offset);
|
||||
ngx_log_debug(p->log, "temp offset: %d" _ p->temp_file->offset);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
if (ngx_event_flags & NGX_USE_LEVEL_EVENT
|
||||
@ -414,8 +420,8 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
|
||||
|
||||
/* reset p->temp_offset if all hunks had been sent */
|
||||
|
||||
if (cl->hunk->file_last == p->temp_offset) {
|
||||
p->temp_offset = 0;
|
||||
if (cl->hunk->file_last == p->temp_file->offset) {
|
||||
p->temp_file->offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,37 +434,29 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
|
||||
static int ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
|
||||
{
|
||||
int rc, size, hsize;
|
||||
char *save_pos;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *cl, *tl, *next, *out, **ll, **last_free;
|
||||
|
||||
ngx_log_debug(p->log, "write to file");
|
||||
|
||||
if (p->temp_file->fd == NGX_INVALID_FILE) {
|
||||
rc = ngx_create_temp_file(p->temp_file, p->temp_path, p->pool,
|
||||
p->cachable);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (!p->cachable && p->temp_file_warn) {
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0, p->temp_file_warn);
|
||||
}
|
||||
}
|
||||
|
||||
out = p->in;
|
||||
|
||||
if (out->hunk->type & NGX_HUNK_PREREAD) {
|
||||
save_pos = out->hunk->pos;
|
||||
out->hunk->pos = out->hunk->start;
|
||||
|
||||
} else {
|
||||
save_pos = NULL;
|
||||
}
|
||||
|
||||
if (!p->cachable) {
|
||||
|
||||
size = 0;
|
||||
cl = p->in;
|
||||
ll = NULL;
|
||||
|
||||
ngx_log_debug(p->log, "offset: %d" _ p->temp_offset);
|
||||
ngx_log_debug(p->log, "offset: %d" _ p->temp_file->offset);
|
||||
|
||||
do {
|
||||
hsize = cl->hunk->last - cl->hunk->pos;
|
||||
@ -466,7 +464,7 @@ ngx_log_debug(p->log, "offset: %d" _ p->temp_offset);
|
||||
ngx_log_debug(p->log, "hunk size: %d" _ hsize);
|
||||
|
||||
if ((size + hsize > p->temp_file_write_size)
|
||||
|| (p->temp_offset + size + hsize > p->max_temp_file_size))
|
||||
|| (p->temp_file->offset + size + hsize > p->max_temp_file_size))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -493,8 +491,7 @@ ngx_log_debug(p->log, "size: %d" _ size);
|
||||
p->last_in = &p->in;
|
||||
}
|
||||
|
||||
if (ngx_write_chain_to_file(p->temp_file, out, p->temp_offset,
|
||||
p->pool) == NGX_ERROR) {
|
||||
if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
@ -505,15 +502,21 @@ ngx_log_debug(p->log, "size: %d" _ size);
|
||||
/* void */
|
||||
}
|
||||
|
||||
if (out->hunk->type & NGX_HUNK_PREREAD) {
|
||||
p->temp_file->offset += save_pos - out->hunk->pos;
|
||||
out->hunk->pos = save_pos;
|
||||
out->hunk->type &= ~NGX_HUNK_PREREAD;
|
||||
}
|
||||
|
||||
for (cl = out; cl; cl = next) {
|
||||
next = cl->next;
|
||||
cl->next = NULL;
|
||||
|
||||
h = cl->hunk;
|
||||
h->file = p->temp_file;
|
||||
h->file_pos = p->temp_offset;
|
||||
p->temp_offset += h->last - h->pos;
|
||||
h->file_last = p->temp_offset;
|
||||
h->file = &p->temp_file->file;
|
||||
h->file_pos = p->temp_file->offset;
|
||||
p->temp_file->offset += h->last - h->pos;
|
||||
h->file_last = p->temp_file->offset;
|
||||
|
||||
if (p->cachable) {
|
||||
h->type |= NGX_HUNK_FILE;
|
||||
|
@ -54,7 +54,6 @@ struct ngx_event_pipe_s {
|
||||
|
||||
size_t busy_size;
|
||||
|
||||
off_t temp_offset;
|
||||
off_t max_temp_file_size;
|
||||
int temp_file_write_size;
|
||||
|
||||
@ -71,9 +70,8 @@ struct ngx_event_pipe_s {
|
||||
ngx_chain_t *preread_hunks;
|
||||
int preread_size;
|
||||
|
||||
ngx_file_t *temp_file;
|
||||
ngx_path_t *temp_path;
|
||||
char *temp_file_warn;
|
||||
ngx_temp_file_t *temp_file;
|
||||
|
||||
/* STUB */ int num;
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,7 @@ ngx_module_t ngx_http_static_module = {
|
||||
|
||||
int ngx_http_static_translate_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int rc, level;
|
||||
char *location, *last;
|
||||
ngx_err_t err;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
@ -116,18 +117,24 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
|
||||
|
||||
if (r->file.fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
|
||||
ngx_open_file_n " \"%s\" failed", r->file.name.data);
|
||||
|
||||
if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
|
||||
return NGX_HTTP_NOT_FOUND;
|
||||
level = NGX_LOG_ERR;
|
||||
rc = NGX_HTTP_NOT_FOUND;
|
||||
|
||||
} else if (err == NGX_EACCES) {
|
||||
return NGX_HTTP_FORBIDDEN;
|
||||
level = NGX_LOG_ERR;
|
||||
rc = NGX_HTTP_FORBIDDEN;
|
||||
|
||||
} else {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
level = NGX_LOG_CRIT;
|
||||
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_error(level, r->connection->log, ngx_errno,
|
||||
ngx_open_file_n " \"%s\" failed", r->file.name.data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd);
|
||||
|
235
src/http/modules/proxy/ngx_http_proxy_cache.c
Normal file
235
src/http/modules/proxy/ngx_http_proxy_cache.c
Normal file
@ -0,0 +1,235 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_proxy_handler.h>
|
||||
|
||||
|
||||
int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
int rc;
|
||||
char *last;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_proxy_cache_t *c;
|
||||
ngx_http_proxy_upstream_t *u;
|
||||
|
||||
r = p->request;
|
||||
|
||||
if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
p->cache = c;
|
||||
|
||||
rc = ngx_http_cache_get_file(r, &c->ctx);
|
||||
|
||||
if (rc == NGX_OK || rc == NGX_STALE) {
|
||||
p->header_in->pos += c->ctx.header.size;
|
||||
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
p->header_in->pos += c->ctx.header.size;
|
||||
p->header_in->last = p->header_in->pos;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int ngx_http_proxy_process_cached_response(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_HTTP_INTERNAL_SERVER_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_HTTP_INTERNAL_SERVER_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_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
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'" _
|
||||
c->status _ c->status_line.data);
|
||||
|
||||
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_HTTP_INTERNAL_SERVER_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_HTTP_INTERNAL_SERVER_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_debug(r->connection->log, "HTTP cache header: '%s: %s'" _
|
||||
h->key.data _ h->value.data);
|
||||
|
||||
continue;
|
||||
|
||||
} else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
|
||||
|
||||
/* a whole header has been parsed successfully */
|
||||
|
||||
ngx_log_debug(r->connection->log, "HTTP header done");
|
||||
|
||||
return ngx_http_proxy_send_cached_response(p);
|
||||
|
||||
} 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_HTTP_INTERNAL_SERVER_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_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
int rc;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t out;
|
||||
ngx_http_request_t *r;
|
||||
|
||||
r = p->request;
|
||||
|
||||
r->headers_out.status = p->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 */
|
||||
|
||||
if (!((h = ngx_calloc_hunk(r->pool)))) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (!((h->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;
|
||||
}
|
||||
|
||||
/* TODO: part in p->header_in */
|
||||
|
||||
h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
|
||||
|
||||
h->file_pos = p->header_in->pos - p->header_in->start;
|
||||
h->file_last = h->file_pos + p->cache->ctx.header.length;
|
||||
|
||||
h->file->fd = p->cache->ctx.file.fd;
|
||||
h->file->log = r->connection->log;
|
||||
|
||||
out.hunk = h;
|
||||
out.next = NULL;
|
||||
|
||||
return ngx_http_output_filter(r, &out);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,13 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_connect.h>
|
||||
#include <ngx_event_pipe.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t url;
|
||||
ngx_str_t host;
|
||||
ngx_str_t uri;
|
||||
ngx_str_t host_header;
|
||||
@ -19,51 +22,62 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct {
|
||||
ssize_t request_buffer_size;
|
||||
ngx_msec_t connect_timeout;
|
||||
ngx_msec_t send_timeout;
|
||||
ssize_t header_buffer_size;
|
||||
ngx_msec_t read_timeout;
|
||||
ssize_t request_buffer_size;
|
||||
ngx_msec_t connect_timeout;
|
||||
ngx_msec_t send_timeout;
|
||||
ssize_t header_buffer_size;
|
||||
ngx_msec_t read_timeout;
|
||||
|
||||
ngx_bufs_t bufs;
|
||||
ssize_t busy_buffers_size;
|
||||
ngx_bufs_t bufs;
|
||||
ssize_t busy_buffers_size;
|
||||
|
||||
ssize_t max_temp_file_size;
|
||||
ssize_t temp_file_write_size;
|
||||
int cyclic_temp_file;
|
||||
ssize_t max_temp_file_size;
|
||||
ssize_t temp_file_write_size;
|
||||
int cyclic_temp_file;
|
||||
|
||||
int pass_server;
|
||||
int cache;
|
||||
int pass_server;
|
||||
|
||||
int next_upstream;
|
||||
int next_upstream;
|
||||
int use_stale;
|
||||
|
||||
ngx_path_t *temp_path;
|
||||
ngx_path_t *cache_path;
|
||||
ngx_path_t *temp_path;
|
||||
|
||||
ngx_http_proxy_upstream_t *upstream;
|
||||
ngx_peers_t *peers;
|
||||
ngx_http_proxy_upstream_t *upstream;
|
||||
ngx_peers_t *peers;
|
||||
} ngx_http_proxy_loc_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int status;
|
||||
ngx_str_t *peer;
|
||||
int status;
|
||||
ngx_str_t *peer;
|
||||
} ngx_http_proxy_state_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_table_t *headers; /* it must be first field */
|
||||
ngx_table_t *headers; /* it must be first field */
|
||||
|
||||
ngx_table_elt_t *date;
|
||||
ngx_table_elt_t *server;
|
||||
ngx_table_elt_t *connection;
|
||||
ngx_table_elt_t *content_type;
|
||||
ngx_table_elt_t *content_length;
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
ngx_table_elt_t *date;
|
||||
ngx_table_elt_t *server;
|
||||
ngx_table_elt_t *connection;
|
||||
ngx_table_elt_t *content_type;
|
||||
ngx_table_elt_t *content_length;
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
|
||||
off_t content_length_n;
|
||||
off_t content_length_n;
|
||||
} ngx_http_proxy_headers_in_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_http_cache_ctx_t ctx;
|
||||
int status;
|
||||
ngx_str_t status_line;
|
||||
ngx_http_proxy_headers_in_t headers_in;
|
||||
} ngx_http_proxy_cache_t;
|
||||
|
||||
|
||||
typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t;
|
||||
|
||||
struct ngx_http_proxy_ctx_s {
|
||||
@ -72,45 +86,69 @@ struct ngx_http_proxy_ctx_s {
|
||||
|
||||
ngx_http_request_t *request;
|
||||
ngx_http_proxy_loc_conf_t *lcf;
|
||||
ngx_http_proxy_cache_t *cache;
|
||||
ngx_http_proxy_headers_in_t headers_in;
|
||||
|
||||
ngx_hunk_t *header_in;
|
||||
int status;
|
||||
ngx_str_t status_line;
|
||||
ngx_hunk_t *header_in;
|
||||
int status;
|
||||
ngx_str_t status_line;
|
||||
|
||||
ngx_output_chain_ctx_t *output_chain_ctx;
|
||||
ngx_output_chain_ctx_t *output_chain_ctx;
|
||||
|
||||
int method;
|
||||
int method;
|
||||
|
||||
ngx_event_pipe_t *event_pipe;
|
||||
ngx_event_pipe_t *event_pipe;
|
||||
|
||||
unsigned accel:1;
|
||||
unsigned cachable:1;
|
||||
unsigned fatal_error:1;
|
||||
unsigned request_sent:1;
|
||||
unsigned timedout:1;
|
||||
unsigned header_sent:1;
|
||||
unsigned accel:1;
|
||||
|
||||
unsigned cachable:1;
|
||||
unsigned stale:1;
|
||||
|
||||
unsigned request_sent:1;
|
||||
unsigned header_sent:1;
|
||||
|
||||
/* used to parse an upstream HTTP header */
|
||||
char *status_start;
|
||||
char *status_end;
|
||||
int status_count;
|
||||
int state;
|
||||
char *status_start;
|
||||
char *status_end;
|
||||
int status_count;
|
||||
int state;
|
||||
|
||||
ngx_array_t states; /* of ngx_http_proxy_state_t */
|
||||
ngx_array_t states; /* of ngx_http_proxy_state_t */
|
||||
|
||||
char *action;
|
||||
ngx_http_log_ctx_t *saved_ctx;
|
||||
ngx_log_handler_pt saved_handler;
|
||||
char *action;
|
||||
ngx_http_log_ctx_t *saved_ctx;
|
||||
ngx_log_handler_pt saved_handler;
|
||||
};
|
||||
|
||||
|
||||
#define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
|
||||
#define NGX_STALE 1
|
||||
|
||||
#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
|
||||
#define NGX_HTTP_PROXY_FT_HTTP_500 16
|
||||
#define NGX_HTTP_PROXY_FT_HTTP_404 32
|
||||
#define NGX_HTTP_PROXY_FT_BUSY_LOCK 64
|
||||
#define NGX_HTTP_PROXY_FT_MAX_WAITING 128
|
||||
|
||||
|
||||
void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p);
|
||||
|
||||
int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p);
|
||||
int ngx_http_proxy_process_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_parse_status_line(ngx_http_proxy_ctx_t *p);
|
||||
int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
|
||||
ngx_http_proxy_headers_in_t *headers_in);
|
||||
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_proxy_module;
|
||||
extern ngx_http_header_t ngx_http_proxy_headers_in[];
|
||||
|
||||
#define NGX_HTTP_PROXY_FT_ERROR 1
|
||||
#define NGX_HTTP_PROXY_FT_TIMEOUT 2
|
||||
#define NGX_HTTP_PROXY_FT_HTTP_HEADER 4
|
||||
#define NGX_HTTP_PROXY_FT_HTTP_500 8
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */
|
||||
|
75
src/http/modules/proxy/ngx_http_proxy_header.c
Normal file
75
src/http/modules/proxy/ngx_http_proxy_header.c
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_proxy_handler.h>
|
||||
|
||||
|
||||
int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
|
||||
ngx_http_proxy_headers_in_t *headers_in)
|
||||
{
|
||||
int i;
|
||||
ngx_table_elt_t *ho, *h;
|
||||
ngx_http_request_t *r;
|
||||
|
||||
r = p->request;
|
||||
|
||||
h = headers_in->headers->elts;
|
||||
for (i = 0; i < headers_in->headers->nelts; i++) {
|
||||
|
||||
if (&h[i] == headers_in->connection) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p->accel) {
|
||||
if (&h[i] == headers_in->date
|
||||
|| &h[i] == headers_in->accept_ranges) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (&h[i] == headers_in->server && !p->lcf->pass_server) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (&h[i] == headers_in->content_type) {
|
||||
r->headers_out.content_type = &h[i];
|
||||
r->headers_out.content_type->key.len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ho = ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = h[i];
|
||||
|
||||
/*
|
||||
* ngx_http_header_filter() does not handle specially
|
||||
* the following headers if they are set:
|
||||
* r->headers_out.server,
|
||||
* r->headers_out.date,
|
||||
* r->headers_out.content_length
|
||||
*/
|
||||
|
||||
if (&h[i] == headers_in->server) {
|
||||
r->headers_out.server = ho;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (&h[i] == headers_in->date) {
|
||||
r->headers_out.date = ho;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (&h[i] == headers_in->content_length) {
|
||||
r->headers_out.content_length = ho;
|
||||
r->headers_out.content_length_n = ngx_atoi(ho->value.data,
|
||||
ho->value.len);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
204
src/http/modules/proxy/ngx_http_proxy_parse.c
Normal file
204
src/http/modules/proxy/ngx_http_proxy_parse.c
Normal file
@ -0,0 +1,204 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_proxy_handler.h>
|
||||
|
||||
|
||||
int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
char ch;
|
||||
char *pos;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_H,
|
||||
sw_HT,
|
||||
sw_HTT,
|
||||
sw_HTTP,
|
||||
sw_first_major_digit,
|
||||
sw_major_digit,
|
||||
sw_first_minor_digit,
|
||||
sw_minor_digit,
|
||||
sw_status,
|
||||
sw_space_after_status,
|
||||
sw_status_text,
|
||||
sw_almost_done,
|
||||
sw_done
|
||||
} state;
|
||||
|
||||
state = p->state;
|
||||
pos = p->header_in->pos;
|
||||
|
||||
while (pos < p->header_in->last && state < sw_done) {
|
||||
ch = *pos++;
|
||||
|
||||
switch (state) {
|
||||
|
||||
/* "HTTP/" */
|
||||
case sw_start:
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
state = sw_H;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case sw_H:
|
||||
switch (ch) {
|
||||
case 'T':
|
||||
state = sw_HT;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case sw_HT:
|
||||
switch (ch) {
|
||||
case 'T':
|
||||
state = sw_HTT;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case sw_HTT:
|
||||
switch (ch) {
|
||||
case 'P':
|
||||
state = sw_HTTP;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case sw_HTTP:
|
||||
switch (ch) {
|
||||
case '/':
|
||||
state = sw_first_major_digit;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
/* the first digit of major HTTP version */
|
||||
case sw_first_major_digit:
|
||||
if (ch < '1' || ch > '9') {
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
|
||||
state = sw_major_digit;
|
||||
break;
|
||||
|
||||
/* the major HTTP version or dot */
|
||||
case sw_major_digit:
|
||||
if (ch == '.') {
|
||||
state = sw_first_minor_digit;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch < '0' || ch > '9') {
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* the first digit of minor HTTP version */
|
||||
case sw_first_minor_digit:
|
||||
if (ch < '0' || ch > '9') {
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
|
||||
state = sw_minor_digit;
|
||||
break;
|
||||
|
||||
/* the minor HTTP version or the end of the request line */
|
||||
case sw_minor_digit:
|
||||
if (ch == ' ') {
|
||||
state = sw_status;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch < '0' || ch > '9') {
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* HTTP status code */
|
||||
case sw_status:
|
||||
if (ch < '0' || ch > '9') {
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
|
||||
p->status = p->status * 10 + ch - '0';
|
||||
|
||||
if (++p->status_count == 3) {
|
||||
state = sw_space_after_status;
|
||||
p->status_start = pos - 3;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* space or end of line */
|
||||
case sw_space_after_status:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
state = sw_status_text;
|
||||
break;
|
||||
case CR:
|
||||
state = sw_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
state = sw_done;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
/* any text until end of line */
|
||||
case sw_status_text:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
state = sw_almost_done;
|
||||
|
||||
break;
|
||||
case LF:
|
||||
state = sw_done;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* end of request line */
|
||||
case sw_almost_done:
|
||||
p->status_end = pos - 2;
|
||||
switch (ch) {
|
||||
case LF:
|
||||
state = sw_done;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PROXY_PARSE_NO_HEADER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p->header_in->pos = pos;
|
||||
|
||||
if (state == sw_done) {
|
||||
if (p->status_end == NULL) {
|
||||
p->status_end = pos - 1;
|
||||
}
|
||||
|
||||
p->state = sw_start;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p->state = state;
|
||||
return NGX_AGAIN;
|
||||
}
|
43
src/http/modules/proxy/ngx_http_proxy_upstream.c
Normal file
43
src/http/modules/proxy/ngx_http_proxy_upstream.c
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_connect.h>
|
||||
#include <ngx_event_pipe.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_proxy_handler.h>
|
||||
|
||||
|
||||
void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
ngx_chain_t *cl;
|
||||
ngx_output_chain_ctx_t *octx;
|
||||
|
||||
octx = p->output_chain_ctx;
|
||||
|
||||
/* reinit the request chain */
|
||||
|
||||
for (cl = p->request->request_hunks; cl; cl = cl->next) {
|
||||
cl->hunk->pos = cl->hunk->start;
|
||||
}
|
||||
|
||||
/* reinit ngx_output_chain() context */
|
||||
|
||||
octx->hunk = NULL;
|
||||
octx->in = NULL;
|
||||
octx->free = NULL;
|
||||
octx->busy = NULL;
|
||||
|
||||
/* reinit r->header_in buffer */
|
||||
|
||||
if (p->header_in) {
|
||||
if (p->cache) {
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header.size;
|
||||
p->header_in->last = p->header_in->pos;
|
||||
|
||||
} else {
|
||||
p->header_in->pos = p->header_in->start;
|
||||
p->header_in->last = p->header_in->start;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http_request.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_cache.h>
|
||||
#include <ngx_http_filter.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
|
||||
|
@ -1,4 +1,161 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
#include <md5.h>
|
||||
|
||||
|
||||
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
|
||||
{
|
||||
int small;
|
||||
ssize_t n, len;
|
||||
MD5_CTX md5;
|
||||
ngx_err_t err;
|
||||
ngx_str_t key;
|
||||
ngx_http_bin_cache_t *h;
|
||||
|
||||
ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32;
|
||||
if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(ctx->file.name.data, ctx->path->name.data, ctx->path->name.len);
|
||||
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len);
|
||||
MD5End(&md5,
|
||||
ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
|
||||
|
||||
ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _
|
||||
ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
|
||||
|
||||
ngx_create_hashed_filename(&ctx->file, ctx->path);
|
||||
|
||||
ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data);
|
||||
|
||||
/* TODO: look open files cache */
|
||||
|
||||
ctx->file.fd = ngx_open_file(ctx->file.name.data,
|
||||
NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
|
||||
if (ctx->file.fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
|
||||
|
||||
/* TODO: text size */
|
||||
|
||||
ctx->header.size = 2 * sizeof(ssize_t)
|
||||
+ sizeof(ngx_http_cache_header_t)
|
||||
+ ctx->key.len + 1;
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
ngx_open_file_n " \"%s\" failed", ctx->file.name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
n = ngx_read_file(&ctx->file, ctx->buf->pos,
|
||||
ctx->buf->end - ctx->buf->last, 0);
|
||||
|
||||
if (n == NGX_ERROR || n == NGX_AGAIN) {
|
||||
return n;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
small = 1;
|
||||
|
||||
if (n > 1) {
|
||||
if (ctx->buf->pos[0] == 'T') {
|
||||
/* STUB */
|
||||
return NGX_ERROR;
|
||||
|
||||
} else if (ctx->buf->pos[0] == 'B') {
|
||||
|
||||
len = sizeof(ngx_http_bin_cache_t);
|
||||
|
||||
if (n > len) {
|
||||
h = (ngx_http_bin_cache_t *) ctx->buf->pos;
|
||||
key.len = h->key_len;
|
||||
|
||||
if (n >= len + (ssize_t) key.len + 1) {
|
||||
ctx->header = h->header;
|
||||
key.data = h->key;
|
||||
|
||||
small = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
|
||||
"unknown type of cache file \"%s\"",
|
||||
ctx->file.name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (small) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
|
||||
"cache file \"%s\" is to small", ctx->file.name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (key.len != ctx->key.len
|
||||
|| ngx_strncmp(key.data, ctx->key.data, key.len) != 0)
|
||||
{
|
||||
key.data[key.len] = '\0';
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"md5 collision: \"%s\" and \"%s\"",
|
||||
key.data, ctx->key.data);
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
ctx->header.size = len + key.len + 1;
|
||||
ctx->buf->last += n;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx,
|
||||
ngx_str_t *temp_file)
|
||||
{
|
||||
int retry;
|
||||
ngx_err_t err;
|
||||
|
||||
retry = 0;
|
||||
|
||||
for ( ;; ) {
|
||||
if (ngx_rename_file(temp_file->data, ctx->file.name.data)
|
||||
!= NGX_FILE_ERROR)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
if (retry || (err != NGX_ENOENT && err != NGX_ENOTDIR)) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
ngx_rename_file_n "(\"%s\", \"%s\") failed",
|
||||
temp_file->data, ctx->file.name.data);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_create_path(&ctx->file, ctx->path) == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
retry = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* small file in malloc()ed memory, mmap()ed file, file descriptor only,
|
||||
@ -94,3 +251,5 @@ int ngx_crc(char *data, size_t len)
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
71
src/http/ngx_http_cache.h
Normal file
71
src/http/ngx_http_cache.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef _NGX_HTTP_CACHE_H_INCLUDED_
|
||||
#define _NGX_HTTP_CACHE_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
time_t expires;
|
||||
time_t last_modified;
|
||||
off_t length;
|
||||
|
||||
size_t size;
|
||||
} ngx_http_cache_header_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ssize_t type;
|
||||
ngx_http_cache_header_t header;
|
||||
ssize_t key_len;
|
||||
char key[0];
|
||||
} ngx_http_bin_cache_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char type;
|
||||
char space0;
|
||||
char expires[8];
|
||||
char space1;
|
||||
char last_modified[8];
|
||||
char space2;
|
||||
char length[16];
|
||||
char space3;
|
||||
char lf;
|
||||
char key_len[0];
|
||||
} ngx_http_text_cache_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_int32_t crc;
|
||||
ngx_str_t key;
|
||||
ngx_fd_t fd;
|
||||
off_t size;
|
||||
void *data; /* mmap, memory */
|
||||
time_t accessed;
|
||||
time_t last_modified;
|
||||
time_t updated; /* no needed with kqueue */
|
||||
int refs;
|
||||
int flags;
|
||||
} ngx_http_cache_entry_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_file_t file;
|
||||
ngx_str_t key;
|
||||
ngx_path_t *path;
|
||||
ngx_hunk_t *buf;
|
||||
ngx_http_cache_header_t header;
|
||||
} ngx_http_cache_ctx_t;
|
||||
|
||||
|
||||
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx);
|
||||
int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx,
|
||||
ngx_str_t *temp_file);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */
|
@ -376,10 +376,7 @@ ngx_log_debug(r->connection->log, "trans: %s" _ clcfp[i]->name.data);
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ngx_strncmp(r->uri.data, clcfp[i]->name.data,
|
||||
clcfp[i]->name.len);
|
||||
|
||||
ngx_log_debug(r->connection->log, "rc: %d" _ rc);
|
||||
rc = ngx_strncmp(r->uri.data, clcfp[i]->name.data, clcfp[i]->name.len);
|
||||
|
||||
if (rc < 0) {
|
||||
break;
|
||||
|
@ -197,6 +197,8 @@ struct ngx_http_request_s {
|
||||
unsigned header_timeout_set:1;
|
||||
|
||||
unsigned proxy:1;
|
||||
unsigned bypass_cache:1;
|
||||
|
||||
#if 0
|
||||
unsigned cachable:1;
|
||||
#endif
|
||||
|
@ -95,6 +95,8 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev)
|
||||
return;
|
||||
}
|
||||
|
||||
r->temp_file->offset += n;
|
||||
|
||||
r->request_body_hunk->pos = r->request_body_hunk->start;
|
||||
r->request_body_hunk->last = r->request_body_hunk->start;
|
||||
}
|
||||
|
@ -50,9 +50,10 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
|
||||
}
|
||||
|
||||
|
||||
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
|
||||
off_t offset, ngx_pool_t *pool)
|
||||
{
|
||||
char *prev;
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
struct iovec *iov;
|
||||
@ -61,20 +62,39 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
|
||||
/* use pwrite() if there's the only hunk in a chain */
|
||||
|
||||
if (ce->next == NULL) {
|
||||
return ngx_write_file(file, ce->hunk->pos,
|
||||
ce->hunk->last - ce->hunk->pos, offset);
|
||||
if (cl->next == NULL) {
|
||||
return ngx_write_file(file, cl->hunk->pos,
|
||||
cl->hunk->last - cl->hunk->pos, offset);
|
||||
}
|
||||
|
||||
ngx_init_array(io, pool, 10, sizeof(struct iovec), NGX_ERROR);
|
||||
prev = NULL;
|
||||
iov = NULL;
|
||||
size = 0;
|
||||
|
||||
while (ce) {
|
||||
ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
|
||||
iov->iov_base = ce->hunk->pos;
|
||||
iov->iov_len = ce->hunk->last - ce->hunk->pos;
|
||||
size += ce->hunk->last - ce->hunk->pos;
|
||||
ce = ce->next;
|
||||
ngx_init_array(io, pool, 10, sizeof(struct iovec), NGX_ERROR);
|
||||
|
||||
/* create the iovec and coalesce the neighbouring hunks */
|
||||
|
||||
while (cl) {
|
||||
if (prev == cl->hunk->pos) {
|
||||
iov->iov_len += cl->hunk->last - cl->hunk->pos;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
|
||||
iov->iov_base = cl->hunk->pos;
|
||||
iov->iov_len = cl->hunk->last - cl->hunk->pos;
|
||||
}
|
||||
|
||||
size += cl->hunk->last - cl->hunk->pos;
|
||||
prev = cl->hunk->last;
|
||||
cl = cl->next;
|
||||
}
|
||||
|
||||
/* use pwrite() if there's the only iovec buffer */
|
||||
|
||||
if (io.nelts == 1) {
|
||||
iov = io.elts;
|
||||
return ngx_write_file(file, iov[0].iov_base, iov[0].iov_len, offset);
|
||||
}
|
||||
|
||||
if (file->offset != offset) {
|
||||
@ -84,7 +104,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
}
|
||||
}
|
||||
|
||||
n = writev(file->fd, (struct iovec *) io.elts, io.nelts);
|
||||
n = writev(file->fd, io.elts, io.nelts);
|
||||
|
||||
if (n == -1) {
|
||||
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() failed");
|
||||
|
@ -45,6 +45,10 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
off_t offset, ngx_pool_t *pool);
|
||||
|
||||
|
||||
#define ngx_rename_file rename
|
||||
#define ngx_rename_file_n "rename"
|
||||
|
||||
|
||||
#define ngx_mkdir(name) mkdir(name, 0700)
|
||||
#define ngx_mkdir_n "mkdir()"
|
||||
|
||||
|
@ -31,13 +31,28 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
struct sf_hdtr hdtr;
|
||||
ngx_err_t err;
|
||||
ngx_array_t header, trailer;
|
||||
ngx_event_t *wev;
|
||||
ngx_hunk_t *file;
|
||||
ngx_chain_t *cl, *tail;
|
||||
|
||||
if (!c->write->ready) {
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return in;
|
||||
}
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
|
||||
if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->kq_eof) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, wev->kq_errno,
|
||||
"kevent() reported about closed connection");
|
||||
|
||||
wev->error = 1;
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
do {
|
||||
cl = in;
|
||||
file = NULL;
|
||||
@ -181,7 +196,7 @@ ngx_log_debug(c->log, "NOPUSH");
|
||||
"sendfile() sent only %qd bytes", sent);
|
||||
|
||||
} else {
|
||||
c->write->error = 1;
|
||||
wev->error = 1;
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, err,
|
||||
"sendfile() failed");
|
||||
return NGX_CHAIN_ERROR;
|
||||
@ -194,7 +209,7 @@ ngx_log_debug(c->log, "NOPUSH");
|
||||
#endif
|
||||
|
||||
} else {
|
||||
rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
|
||||
rc = writev(c->fd, header.elts, header.nelts);
|
||||
|
||||
if (rc == -1) {
|
||||
err = ngx_errno;
|
||||
@ -206,7 +221,7 @@ ngx_log_debug(c->log, "NOPUSH");
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
|
||||
|
||||
} else {
|
||||
c->write->error = 1;
|
||||
wev->error = 1;
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
@ -268,7 +283,7 @@ ngx_log_debug(c->log, "NOPUSH");
|
||||
* return EAGAIN right away and would not send anything
|
||||
*/
|
||||
|
||||
c->write->ready = 0;
|
||||
wev->ready = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -277,7 +292,7 @@ ngx_log_debug(c->log, "NOPUSH");
|
||||
} while ((tail && tail == in) || eintr);
|
||||
|
||||
if (in) {
|
||||
c->write->ready = 0;
|
||||
wev->ready = 0;
|
||||
}
|
||||
|
||||
return in;
|
||||
|
@ -11,34 +11,34 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
off_t sent;
|
||||
struct iovec *iov;
|
||||
ngx_err_t err;
|
||||
ngx_array_t iovecs;
|
||||
ngx_chain_t *ce;
|
||||
ngx_array_t io;
|
||||
ngx_chain_t *cl;
|
||||
|
||||
if (!c->write->ready) {
|
||||
return in;
|
||||
}
|
||||
|
||||
ngx_init_array(iovecs, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
|
||||
ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
|
||||
|
||||
prev = NULL;
|
||||
iov = NULL;
|
||||
|
||||
/* create the iovec and coalesce the neighbouring chain entries */
|
||||
for (ce = in; ce; ce = ce->next) {
|
||||
/* create the iovec and coalesce the neighbouring hunks */
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
|
||||
if (prev == ce->hunk->pos) {
|
||||
iov->iov_len += ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
if (prev == cl->hunk->pos) {
|
||||
iov->iov_len += cl->hunk->last - cl->hunk->pos;
|
||||
prev = cl->hunk->last;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(&iovecs), NGX_CHAIN_ERROR);
|
||||
iov->iov_base = ce->hunk->pos;
|
||||
iov->iov_len = ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR);
|
||||
iov->iov_base = cl->hunk->pos;
|
||||
iov->iov_len = cl->hunk->last - cl->hunk->pos;
|
||||
prev = cl->hunk->last;
|
||||
}
|
||||
}
|
||||
|
||||
n = writev(c->fd, iovecs.elts, iovecs.nelts);
|
||||
n = writev(c->fd, io.elts, io.nelts);
|
||||
|
||||
if (n == -1) {
|
||||
err = ngx_errno;
|
||||
@ -62,42 +62,40 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
for (ce = in; ce && sent > 0; ce = ce->next) {
|
||||
for (cl = in; cl && sent > 0; cl = cl->next) {
|
||||
|
||||
size = ce->hunk->last - ce->hunk->pos;
|
||||
size = cl->hunk->last - cl->hunk->pos;
|
||||
|
||||
ngx_log_debug(c->log, "SIZE: %d" _ size);
|
||||
|
||||
if (sent >= size) {
|
||||
sent -= size;
|
||||
|
||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
ce->hunk->pos = ce->hunk->last;
|
||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
cl->hunk->pos = cl->hunk->last;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ce->hunk->type & NGX_HUNK_FILE) {
|
||||
ce->hunk->file_pos = ce->hunk->file_last;
|
||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
||||
cl->hunk->file_pos = cl->hunk->file_last;
|
||||
}
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
ce->hunk->pos += sent;
|
||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
cl->hunk->pos += sent;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ce->hunk->type & NGX_HUNK_FILE) {
|
||||
ce->hunk->file_pos += sent;
|
||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
||||
cl->hunk->file_pos += sent;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_destroy_array(&iovecs);
|
||||
|
||||
return ce;
|
||||
return cl;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user