nginx-0.0.1-2003-11-03-01:56:18 import

This commit is contained in:
Igor Sysoev 2003-11-02 22:56:18 +00:00
parent fe0f5cc6e1
commit 659774979f
26 changed files with 1418 additions and 747 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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))) {

View File

@ -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 _

View File

@ -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;

View File

@ -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;

View 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;
};

View File

@ -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);

View 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

View File

@ -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_ */

View 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;
}

View 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;
}

View 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;
}
}
}

View File

@ -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>

View File

@ -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
View 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_ */

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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");

View File

@ -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()"

View File

@ -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;

View File

@ -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;
}