diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 3a0e9dd2e..652647100 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -36,11 +36,11 @@ typedef struct ngx_connection_s ngx_connection_t; #define NGX_OK 0 #define NGX_ERROR -1 #define NGX_AGAIN -2 +#define NGX_DONE -3 #define NGX_DECLINED -4 #define NGX_ABORT -5 /* -#define NGX_DONE -3 #define NGX_BUSY -3 #define NGX_ALERT -5 */ diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h index a66d47610..3a10076cc 100644 --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -85,9 +85,9 @@ typedef struct { (h->type == (h->type & (NGX_HUNK_FLUSH|NGX_HUNK_LAST))) -#define nxg_hunk_size(h) \ - (h->type & NGX_HUNK_IN_MEMORY) ? h->last - h->pos: \ - (size_t) h->file_last - h->file_pos +#define ngx_hunk_size(h) \ + ((h->type & NGX_HUNK_IN_MEMORY) ? h->last - h->pos: \ + (size_t) (h->file_last - h->file_pos)) ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size, @@ -108,14 +108,13 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size, #define ngx_alloc_ce_and_set_hunk ngx_add_hunk_to_chain -#define ngx_chain_add_ce(ngx_chain_t *chain, ngx_chain_t **last, \ - ngx_chain_t *ce) \ +#define ngx_chain_add_ce(chain, last, ce) \ if (chain) { \ - last->next = ce; \ + *last = ce; \ } else { \ chain = ce; \ } \ - last = ce; + last = &ce->next int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **ch, ngx_chain_t *in); diff --git a/src/core/ngx_modules.c b/src/core/ngx_modules.c index d7268c9eb..dfe0243ad 100644 --- a/src/core/ngx_modules.c +++ b/src/core/ngx_modules.c @@ -89,7 +89,7 @@ ngx_module_t *ngx_modules[] = { /* &ngx_http_ssi_filter_module, */ &ngx_http_charset_filter_module, - /* &ngx_http_static_module, */ + &ngx_http_static_module, &ngx_http_index_module, &ngx_http_proxy_module, diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index b2b70d44c..c76ade1c8 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -220,6 +220,8 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc) return NGX_AGAIN; } + wev->ready = 1; + if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { return NGX_ERROR; } diff --git a/src/event/ngx_event_proxy.c b/src/event/ngx_event_proxy.c index 5dfa67109..c6bd8a373 100644 --- a/src/event/ngx_event_proxy.c +++ b/src/event/ngx_event_proxy.c @@ -4,21 +4,27 @@ #include #include +static int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p); +ngx_inline static void ngx_remove_shadow_links(ngx_hunk_t *hunk); +ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free, + ngx_hunk_t *h); +ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain, + ngx_chain_t *ce); + int ngx_event_proxy_read_upstream(ngx_event_proxy_t *p) { int n, rc, size; - ngx_hunk_t *h, *nh; - ngx_chain_t *chain, *rest, *ce, *next; - - rest = NULL; + ngx_hunk_t *h; + ngx_chain_t *chain, *ce, *te; p->upstream_level++; -ngx_log_debug(p->log, "read upstream"); - - for ( ;; ) { + ngx_log_debug(p->log, "read upstream: %d" _ p->upstream->read->ready); + while (p->preread_hunks + || (p->upstream->read->ready && !p->upstream_done)) + { if (p->preread_hunks) { /* use the pre-read hunks if they exist */ @@ -27,7 +33,7 @@ ngx_log_debug(p->log, "read upstream"); p->preread_hunks = NULL; n = p->preread_size; -ngx_log_debug(p->log, "preread: %d" _ n); + ngx_log_debug(p->log, "preread: %d" _ n); } else { @@ -46,24 +52,14 @@ ngx_log_debug(p->log, "preread: %d" _ n); "readv() failed"); p->upstream_error = 1; + break; + } else if (p->upstream->read->eof && p->upstream->read->available == 0) { p->upstream_eof = 1; + + break; } - - if ((p->upstream_eof || p->upstream_error) - && p->free_raw_hunk) - { - if (p->input_filter(p->input_data, p->free_raw_hunk->hunk) - == NGX_ERROR) { - return NGX_ABORT; - } - - /* TODO: p->free_raw_hunk->next can be free()ed */ - p->free_raw_hunk = p->free_raw_hunk->next; - } - - break; } #endif @@ -74,23 +70,18 @@ ngx_log_debug(p->log, "preread: %d" _ n); chain = p->free_raw_hunks; p->free_raw_hunks = NULL; -ngx_log_debug(p->log, "free hunk: %08X:%d" _ chain->hunk _ - chain->hunk->end - chain->hunk->last); - } else if (p->hunks < p->bufs.num) { /* allocate a new hunk if it's still allowed */ ngx_test_null(h, ngx_create_temp_hunk(p->pool, - p->bufs.size, 20, 20); + p->bufs.size, 0, 0), NGX_ABORT); p->hunks++; ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT); chain = te; -ngx_log_debug(p->log, "new hunk: %08X" _ chain->hunk); - } else if (!p->cachable && p->downstream->write->ready) { /* @@ -98,7 +89,7 @@ ngx_log_debug(p->log, "new hunk: %08X" _ chain->hunk); * a downstream is ready then write the hunks to a downstream. */ -ngx_log_debug(p->log, "downstream ready"); + ngx_log_debug(p->log, "downstream ready"); break; @@ -111,7 +102,7 @@ ngx_log_debug(p->log, "downstream ready"); rc = ngx_event_proxy_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_offset); if (rc == NGX_AGAIN) { if (ngx_event_flags & NGX_USE_LEVEL_EVENT @@ -133,21 +124,18 @@ ngx_log_debug(p->log, "temp offset: %d" _ p->temp_offset); chain = p->free_raw_hunks; p->free_raw_hunks = NULL; -ngx_log_debug(p->log, "new file hunk: %08X:%d" _ chain->hunk _ - chain->hunk->end - chain->hunk->last); - } else { /* if there're no hunks to read in then disable a level event */ -ngx_log_debug(p->log, "no hunks to read in"); + ngx_log_debug(p->log, "no hunks to read in"); break; } n = ngx_recv_chain(p->upstream, chain); -ngx_log_debug(p->log, "recv_chain: %d" _ n); + ngx_log_debug(p->log, "recv_chain: %d" _ n); if (n == NGX_ERROR) { p->upstream_error = 1; @@ -159,10 +147,7 @@ ngx_log_debug(p->log, "recv_chain: %d" _ n); } if (n == 0) { - THINK - if (chain->hunk->shadow == NULL) { - p->free_hunks = chain; - } + p->free_raw_hunks = chain; p->upstream_eof = 1; break; @@ -172,180 +157,41 @@ ngx_log_debug(p->log, "recv_chain: %d" _ n); for (ce = chain; ce && n > 0; ce = ce->next) { - size = ce->hunk->end - ce->hunk->last; - - if (n >= size) { - ce->hunk->last = ce->hunk->end; - - if (p->input_filter(p->input_data, ce->hunk) == NGX_ERROR) { - return NGX_ABORT; - } - - n -= size; - - } else if (p->upstream_eof || p->upstream_error) { - - if (p->input_filter(p->input_data, ce->hunk) == NGX_ERROR) { - return NGX_ABORT; - } - - } else { - ce->hunk->last += n; - n = 0; - } - - - - - - - - - next = ce->next; - ce->next = NULL; - - if (ce->hunk->shadow) { - for (h = ce->hunk->shadow; - (h->type & NGX_HUNK_LAST_SHADOW) == 0; - h = nh) - { - nh = h->shadow; - h->shadow = NULL; - h->type &= ~(NGX_HUNK_TEMP - |NGX_HUNK_IN_MEMORY - |NGX_HUNK_RECYCLED); - } - - h->shadow = NULL; - h->type &= ~(NGX_HUNK_TEMP - |NGX_HUNK_IN_MEMORY - |NGX_HUNK_RECYCLED - |NGX_HUNK_LAST_SHADOW); - ce->hunk->shadow = NULL; - } + ngx_remove_shadow_links(ce->hunk); size = ce->hunk->end - ce->hunk->last; if (n >= size) { ce->hunk->last = ce->hunk->end; - if (p->read_hunks) { - p->last_read_hunk->next = ce; - - } else { - p->read_hunks = ce; + if (p->input_filter(p, ce->hunk) == NGX_ERROR) { + return NGX_ABORT; } - p->last_read_hunk = ce; - n -= size; + chain = ce->next; + } else { ce->hunk->last += n; - p->free_hunks = ce; - n = 0; } } - if (chain == p->free_hunks) { - chain = NULL; - } + p->free_raw_hunks = chain; + } - /* - * the input filter i.e. that moves HTTP/1.1 chunks - * from a read chain to an incoming chain - */ - - if (p->input_filter(p, chain) == NGX_ERROR) { + if ((p->upstream_eof || p->upstream_error) && p->free_raw_hunks) { + if (p->input_filter(p, p->free_raw_hunks->hunk) == NGX_ERROR) { return NGX_ABORT; } -ngx_log_debug(p->log, "rest chain: %08X" _ ce); - - /* - * if the rest hunks are file hunks then move them to a file chain - * otherwise add them to a free chain - */ - - if (rest) { - if (rest->hunk->shadow) { - p->file_hunks = rest; - - } else { - if (p->free_hunks) { - p->free_hunks->next = rest; - - } else { - p->free_hunks = rest; - } - } - - break; - } - } - -ngx_log_debug(p->log, "eof: %d" _ p->upstream_eof); - - /* - * if there's the end of upstream response then move - * the partially filled hunk from a free chain to an incoming chain - */ - - if (p->upstream_eof) { - if (p->free_hunks - && p->free_hunks->hunk->pos < p->free_hunks->hunk->last) - { - -#if (NGX_EVENT_COPY_FILTER) - - if (p->input_filter(p, NULL) == NGX_ERROR) { - return NGX_ABORT; - } -#else - - if (p->input_filter) { - if (p->input_filter(p, NULL) == NGX_ERROR) { - return NGX_ABORT; - } - - } else { - ce = p->free_hunks; - - if (p->in_hunks) { - p->last_in_hunk->next = ce; - - } else { - p->in_hunks = ce; - } - - p->last_in_hunk = ce; - } - - p->free_hunks = ce->next; - ce->next = NULL; - -#endif /* NGX_EVENT_COPY_FILTER */ - } - -#if 0 - /* free the unneeded hunks */ - - for (ce = p->free_hunks; ce; ce = ce->next) { - ngx_free_hunk(p->pool, ce->hunk); - } -#endif - - if (p->in_hunks) { - p->last_in_hunk->hunk->type |= NGX_HUNK_LAST; - - } else if (p->out_hunks) { - p->last_out_hunk->hunk->type |= NGX_HUNK_LAST; - } + /* TODO: p->free_raw_hunk->next can be free()ed */ + p->free_raw_hunks = p->free_raw_hunks->next; } if (p->cachable) { - if (p->in_hunks) { + if (p->in) { rc = ngx_event_proxy_write_chain_to_temp_file(p); if (rc != NGX_OK) { @@ -353,13 +199,13 @@ ngx_log_debug(p->log, "eof: %d" _ p->upstream_eof); } } - if (p->out_hunks && p->downstream->write->ready) { + if (p->out && p->downstream->write->ready) { if (ngx_event_proxy_write_to_downstream(p) == NGX_ABORT) { return NGX_ABORT; } } - } else if ((p->out_hunks || p->in_hunks) && p->downstream->write->ready) { + } else if ((p->out || p->in) && p->downstream->write->ready) { if (ngx_event_proxy_write_to_downstream(p) == NGX_ABORT) { return NGX_ABORT; } @@ -375,25 +221,22 @@ ngx_log_debug(p->log, "upstream level: %d" _ p->upstream_level); } } - if (p->upstream_eof) { - return NGX_OK; - - } else { - return NGX_AGAIN; - } + return NGX_OK; } int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) { - ngx_chain_t *out, *ce; + int rc; + ngx_hunk_t *h; + ngx_chain_t *out, *ce, *te; while (p->downstream->write->ready) { if (p->out) { out = p->out; - if (p->busy_len + ngx_hunk_size(out->hunk)) > p->max_busy_len) { + if (p->busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len) { break; } @@ -403,7 +246,7 @@ int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) } else if (!p->cachable && p->in) { out = p->in; - if (p->busy_len + ngx_hunk_size(out->hunk)) > p->max_busy_len) { + if (p->busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len) { break; } @@ -415,9 +258,9 @@ int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) out->next = NULL; - rc = p->output_filter(p->output_data, out->hunk); + rc = p->output_filter(p->output_ctx, out->hunk); - ngx_chain_update_chains(p->free, p->busy, out); + ngx_chain_update_chains(&p->free, &p->busy, &out); /* calculate p->busy_len */ @@ -435,14 +278,14 @@ int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) h->shadow = NULL; ngx_alloc_ce_and_set_hunk(te, ce->hunk->shadow, p->pool, NGX_ABORT); - ngx_add_after_partially_filled_hunk(p->free_raw_hunks, te); + ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te); ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW; } ce->hunk->shadow = NULL; } - if (p->upstream.read->ready) + if (p->upstream->read->ready) { if (ngx_event_proxy_read_upstream(p) == NGX_ERROR) { return NGX_ABORT; } @@ -450,7 +293,8 @@ int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) } if (p->downstream_level == 0) { - if (ngx_handler_write_event(p->downstream->write) == NGX_ERROR) { + if (ngx_handle_write_event(p->downstream->write, + /* TODO: lowat */ 0) == NGX_ERROR) { return NGX_ABORT; } } @@ -463,13 +307,13 @@ int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) } -int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p) +static int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p) { int rc, size; ngx_hunk_t *h; - ngx_chain_t *entry, *next, *saved_in, *saved_read; + ngx_chain_t *ce, *next, *in, **last; -ngx_log_debug(p->log, "write to file"); + 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, @@ -483,86 +327,59 @@ ngx_log_debug(p->log, "write to file"); return NGX_AGAIN; } - if (p->cachable == 0 && p->temp_file_warn) { + if (!p->cachable && p->temp_file_warn) { ngx_log_error(NGX_LOG_WARN, p->log, 0, p->temp_file_warn); } } - if (p->cachable == 0) { + if (!p->cachable) { - entry = p->read_hunks; size = 0; + ce = p->in; do { - size += entry->hunk->last - entry->hunk->pos; + size += ce->hunk->last - ce->hunk->pos; if (size >= p->temp_file_write_size) { break; } - entry = entry->next; + ce = ce->next; - } while (entry); + } while (ce); - saved_read = entry->next; - entry->next = NULL; - - if (saved_read) { - for (entry = p->in_hunks; entry->next; entry = entry->next) { - if (entry->next->hunk->shadow == saved_read->hunk) { - break; - } - } - saved_in = entry->next; - entry->next = NULL; - - } else { - saved_in = NULL; - } + in = ce->next; + last = &ce->next; + ce->next = NULL; } else { - saved_read = NULL; - saved_in = NULL; + in = NULL; + last = &p->in; } - if (ngx_write_chain_to_file(p->temp_file, p->in_hunks, p->temp_offset, + if (ngx_write_chain_to_file(p->temp_file, p->in, p->temp_offset, p->pool) == NGX_ERROR) { return NGX_ABORT; } - for (entry = p->in_hunks; entry; entry = next) { - next = entry->next; - entry->next = NULL; + for (ce = p->in; ce; ce = next) { + next = ce->next; + ce->next = NULL; - h = entry->hunk; + h = ce->hunk; h->type |= NGX_HUNK_FILE; h->file = p->temp_file; h->file_pos = p->temp_offset; p->temp_offset += h->last - h->pos; h->file_last = p->temp_offset; -ngx_log_debug(p->log, "event proxy file hunk: %08X:%08X" _ h _ h->shadow); - if (h->type & NGX_HUNK_LAST_SHADOW) { -#if 0 - h->shadow->last = h->shadow->pos; -#else h->shadow->last = h->shadow->pos = h->shadow->start; -#endif } - if (p->out_hunks) { - p->last_out_hunk->next = entry; - - } else { - p->out_hunks = entry; - } - - p->last_out_hunk = entry; + ngx_chain_add_ce(p->out, p->last_out, ce); } - p->file_hunks = p->read_hunks; - - p->read_hunks = saved_read; - p->in_hunks = saved_in; + p->in = in; + p->last_in = last; return NGX_OK; } @@ -593,22 +410,44 @@ int ngx_event_proxy_copy_input_filter(ngx_event_proxy_t *p, ngx_hunk_t *hunk) hunk->shadow = h; ngx_alloc_ce_and_set_hunk(ce, h, p->pool, NGX_ERROR); - ngx_chain_add_ce(p->in_hunk, p->last_in_hunk, ce); + ngx_chain_add_ce(p->in, p->last_in, ce); return NGX_OK; } -ngx_inline static void ngx_remove_shadow_links(ngx_chain_t *ce) +ngx_inline static void ngx_remove_shadow_links(ngx_hunk_t *hunk) { - for ( + ngx_hunk_t *h, *next; + + if (hunk->shadow == NULL) { + return; + } + + h = hunk->shadow; + + while (!(h->type & NGX_HUNK_LAST_SHADOW)) { + next = h->shadow; + h->type &= ~(NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY|NGX_HUNK_RECYCLED); + h->shadow = NULL; + h = next; + } + + h->type &= ~(NGX_HUNK_TEMP + |NGX_HUNK_IN_MEMORY + |NGX_HUNK_RECYCLED + |NGX_HUNK_LAST_SHADOW); + h->shadow = NULL; + + hunk->shadow = NULL; } -ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free; - ngx_hunk_t *h); +ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free, + ngx_hunk_t *h) { - ngx_hunk_t *s; + ngx_hunk_t *s; + ngx_chain_t *ce, **le; if (h->shadow == NULL) { return; @@ -635,15 +474,20 @@ ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free; } -ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t *chain, +ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain, ngx_chain_t *ce) { - if (chain->hunk->pos != chain->hunk->last) { - ce->next = chain->next; - chain->next = ce; + if (*chain == NULL) { + *chain = ce; + return; + } + + if ((*chain)->hunk->pos != (*chain)->hunk->last) { + ce->next = (*chain)->next; + (*chain)->next = ce; } else { - ce->next = chain; - chain = ce; + ce->next = (*chain); + (*chain) = ce; } } diff --git a/src/event/ngx_event_proxy.h b/src/event/ngx_event_proxy.h index bab95418f..3e38d314a 100644 --- a/src/event/ngx_event_proxy.h +++ b/src/event/ngx_event_proxy.h @@ -10,40 +10,37 @@ typedef struct ngx_event_proxy_s ngx_event_proxy_t; typedef int (*ngx_event_proxy_input_filter_pt)(ngx_event_proxy_t *p, - ngx_chain_t *chain); + ngx_hunk_t *hunk); typedef int (*ngx_event_proxy_output_filter_pt)(void *data, ngx_hunk_t *hunk); struct ngx_event_proxy_s { - ngx_chain_t *read_hunks; - ngx_chain_t *last_read_hunk; + ngx_chain_t *free_raw_hunks; + ngx_chain_t *in; + ngx_chain_t **last_in; - ngx_chain_t *file_hunks; + ngx_chain_t *out; + ngx_chain_t **last_out; - ngx_chain_t *in_hunks; - ngx_chain_t *last_in_hunk; + ngx_chain_t *free; + ngx_chain_t *busy; - ngx_chain_t *out_hunks; - ngx_chain_t *last_out_hunk; + /* + * the input filter i.e. that moves HTTP/1.1 chunks + * from the raw hunks to an incoming chain + */ - ngx_chain_t *free_hunks; -#if 0 - ngx_chain_t *last_free_hunk; -#endif + ngx_event_proxy_input_filter_pt input_filter; + void *input_ctx; - ngx_hunk_t *busy_hunk; - - ngx_event_proxy_input_filter_pt input_filter; - void *input_data; - - ngx_event_proxy_output_filter_pt output_filter; - void *output_data; + ngx_event_proxy_output_filter_pt output_filter; + void *output_ctx; unsigned cachable:1; - unsigned block_upstream:1; + unsigned upstream_done:1; unsigned upstream_eof:1; unsigned upstream_error:1; - unsigned downstream_eof:1; + unsigned downstream_done:1; unsigned downstream_error:1; int upstream_level; @@ -52,6 +49,9 @@ struct ngx_event_proxy_s { int hunks; ngx_bufs_t bufs; + size_t busy_len; + size_t max_busy_len; + off_t temp_offset; off_t max_temp_file_size; int temp_file_write_size; @@ -63,9 +63,6 @@ struct ngx_event_proxy_s { ngx_log_t *log; ngx_chain_t *preread_hunks; -#if 0 - ngx_chain_t *last_preread_hunk; -#endif int preread_size; ngx_file_t *temp_file; @@ -76,7 +73,7 @@ struct ngx_event_proxy_s { int ngx_event_proxy_read_upstream(ngx_event_proxy_t *p); int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p); -int ngx_event_proxy_copy_input_filter(ngx_event_proxy_t *p, ngx_chain_t *chain); +int ngx_event_proxy_copy_input_filter(ngx_event_proxy_t *p, ngx_hunk_t *hunk); #endif /* _NGX_EVENT_PROXY_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 1bf2bd99d..9ec932517 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -79,7 +79,7 @@ ngx_module_t ngx_http_index_module = { int ngx_http_index_handler(ngx_http_request_t *r) { - int i, rc, test_dir, path_not_found; + int rc; char *name, *file; ngx_str_t redirect, *index; ngx_err_t err; @@ -132,7 +132,7 @@ int ngx_http_index_handler(ngx_http_request_t *r) fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN); - if (fd == NGX_AGAIN) { + if (fd == (ngx_fd_t) NGX_AGAIN) { return NGX_AGAIN; } diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c index b8aa8d443..8b414d76d 100644 --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -4,7 +4,188 @@ #include -int ngx_http_static_handler(ngx_http_request_t *r) +static int ngx_http_static_handler(ngx_http_request_t *r); +static int ngx_http_static_init(ngx_cycle_t *cycle); + + +static ngx_command_t ngx_http_static_commands[] = { + + ngx_null_command +}; + + + +ngx_http_module_t ngx_http_static_module_ctx = { + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_static_module = { + NGX_MODULE, + &ngx_http_static_module_ctx, /* module context */ + ngx_http_static_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + ngx_http_static_init, /* init module */ + NULL /* init child */ +}; + + +int ngx_http_static_translate_handler(ngx_http_request_t *r) +{ + char *location, *last; + ngx_err_t err; + ngx_table_elt_t *h; + ngx_http_core_loc_conf_t *clcf; + + if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + return NGX_HTTP_NOT_ALLOWED; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (r->uri.data[r->uri.len - 1] == '/') { + if (r->path.data == NULL) { + ngx_test_null(r->path.data, + ngx_palloc(r->pool, + clcf->doc_root.len + r->uri.len), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data, + clcf->doc_root.len), + r->uri.data, r->uri.len + 1); + + } else { + r->path.data[r->path.len] = '\0'; + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "directory index of \"%s\" is forbidden", r->path.data); + + return NGX_HTTP_FORBIDDEN; + } + + /* "+ 2" is for trailing '/' in redirect and '\0' */ + ngx_test_null(r->file.name.data, + ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + location = ngx_cpymem(r->file.name.data, clcf->doc_root.data, + clcf->doc_root.len), + + last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1); + +ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); + +#if (WIN9X) + + /* + * There is no way to open a file or a directory in Win9X with + * one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag. + * so we need to check its type before the opening + */ + + r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data); + if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { + err = ngx_errno; + ngx_log_error(NGX_LOG_ERR, r->connection->log, err, + ngx_file_type_n " \"%s\" failed", r->file.name.data); + + if (err == NGX_ENOENT || err == NGX_ENOTDIR) { + return NGX_HTTP_NOT_FOUND; + + } else if (err == NGX_EACCES) { + return NGX_HTTP_FORBIDDEN; + + } else { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } + +#else + + if (r->file.fd == NGX_INVALID_FILE) { + r->file.fd = ngx_open_file(r->file.name.data, + NGX_FILE_RDONLY, NGX_FILE_OPEN); + } + + 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; + + } else if (err == NGX_EACCES) { + return NGX_HTTP_FORBIDDEN; + + } else { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } + +ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd); + + if (!r->file.info_valid) { + if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_stat_fd_n " \"%s\" failed", r->file.name.data); + + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", + r->file.name.data); + } + + r->file.fd = NGX_INVALID_FILE; + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->file.info_valid = 1; + } +#endif + + if (ngx_is_dir(r->file.info)) { +ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); + +#if !(WIN9X) + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", r->file.name.data); + } + + r->file.fd = NGX_INVALID_FILE; +#endif + + ngx_test_null(h, ngx_push_table(r->headers_out.headers), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + *last++ = '/'; + *last = '\0'; + h->key.len = 8; + h->key.data = "Location" ; + h->value.len = last - location; + h->value.data = location; + r->headers_out.location = h; + + return NGX_HTTP_MOVED_PERMANENTLY; + } + + r->content_handler = ngx_http_static_handler; + + return NGX_OK; +} + + +static int ngx_http_static_handler(ngx_http_request_t *r) { int rc, key, i; ngx_log_e level; @@ -20,10 +201,6 @@ int ngx_http_static_handler(ngx_http_request_t *r) return rc; } - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { - return NGX_HTTP_NOT_ALLOWED; - } - ctx = r->connection->log->data; ctx->action = "sending response"; @@ -142,3 +319,22 @@ int ngx_http_static_handler(ngx_http_request_t *r) return ngx_http_output_filter(r, h); } + + +static int ngx_http_static_init(ngx_cycle_t *cycle) +{ + ngx_http_handler_pt *h; + ngx_http_conf_ctx_t *ctx; + ngx_http_core_main_conf_t *cmcf; + + ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; + cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; + + ngx_test_null(h, ngx_push_array( + &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), + NGX_ERROR); + *h = ngx_http_static_translate_handler; + + return NGX_OK; +} + diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index b21eac47a..58ce51a46 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -17,7 +17,8 @@ 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 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_upstream_body(ngx_event_t *rev); +static void ngx_http_proxy_process_upstream(ngx_event_t *rev); +static void ngx_http_proxy_process_downstream(ngx_event_t *wev); static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p); @@ -27,8 +28,21 @@ static void ngx_http_proxy_close_connection(ngx_connection_t *c); static int ngx_http_proxy_init(ngx_cycle_t *cycle); static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, + ngx_http_proxy_upstream_t *u); + static ngx_command_t ngx_http_proxy_commands[] = { + + {ngx_string("proxy_pass"), + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_proxy_set_pass, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL}, + ngx_null_command }; @@ -54,7 +68,7 @@ ngx_module_t ngx_http_proxy_module = { &ngx_http_proxy_module_ctx, /* module context */ ngx_http_proxy_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ - ngx_http_proxy_init, /* init module */ + NULL, /* init module */ NULL /* init child */ }; @@ -99,22 +113,9 @@ static char conn_close_header[] = "Connection: close" CRLF; -static int ngx_http_proxy_translate_handler(ngx_http_request_t *r) -{ -#if 0 - r->handler = ngx_http_proxy_handler; - return NGX_OK; -#else - return NGX_DECLINED; -#endif -} - - static int ngx_http_proxy_handler(ngx_http_request_t *r) { - int rc; - ngx_http_proxy_ctx_t *p; - ngx_http_proxy_loc_conf_t *lcf; + ngx_http_proxy_ctx_t *p; ngx_http_create_ctx(r, p, ngx_http_proxy_module, sizeof(ngx_http_proxy_ctx_t), @@ -126,6 +127,8 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) p->request = r; p->method = r->method; + + /* TODO: from lcf->upstream */ p->uri.data = "/"; p->uri.len = 1; p->location_len = 1; @@ -144,7 +147,7 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) ngx_http_proxy_send_request(p); - return NGX_OK; + return NGX_DONE; } @@ -580,7 +583,6 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev) static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) { - int event; ssize_t n; ngx_event_t *rev; @@ -589,7 +591,10 @@ static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) n = p->header_in->last - p->header_in->pos; if (n > 0) { +#if 0 + /* TODO THINK */ rev->ready = 0; +#endif return n; } @@ -700,11 +705,12 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) return; } + ep->input_filter = ngx_event_proxy_copy_input_filter; ep->output_filter = (ngx_event_proxy_output_filter_pt) ngx_http_output_filter; - ep->output_data = r; - ep->block_size = p->lcf->block_size; - ep->max_block_size = p->lcf->max_block_size; + ep->output_ctx = r; + ep->bufs = p->lcf->bufs; + ep->max_busy_len = p->lcf->max_busy_len; ep->upstream = p->upstream.connection; ep->downstream = r->connection; ep->pool = r->pool; @@ -742,16 +748,18 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) lcx->action = "reading an upstream"; #endif - ngx_event_proxy_read_upstream(ep); - p->upstream.connection->read->event_handler = - ngx_http_proxy_process_upstream_body; + ngx_http_proxy_process_upstream; + r->connection->write->event_handler = + ngx_http_proxy_process_downstream; + + ngx_http_proxy_process_upstream(p->upstream.connection->read); return; } -static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev) +static void ngx_http_proxy_process_upstream(ngx_event_t *rev) { ngx_connection_t *c; ngx_http_proxy_ctx_t *p; @@ -759,25 +767,58 @@ static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev) c = rev->data; p = c->data; - ngx_log_debug(rev->log, "http proxy process upstream body"); + ngx_log_debug(rev->log, "http proxy process upstream"); if (rev->timedout) { - ngx_http_proxy_close_connection(p->upstream.connection); + ngx_http_proxy_close_connection(c); p->upstream.connection = NULL; return; } - ngx_event_proxy_read_upstream(p->event_proxy); - - if (p->event_proxy->upstream_eof) { - ngx_http_proxy_close_connection(p->upstream.connection); - p->upstream.connection = NULL; + if (ngx_event_proxy_read_upstream(p->event_proxy) == NGX_ABORT) { + ngx_http_proxy_finalize_request(p, 0); return; } - if (p->event_proxy->upstream_error) { - ngx_http_proxy_close_connection(p->upstream.connection); - p->upstream.connection = NULL; + if (p->event_proxy->upstream_eof + || p->event_proxy->upstream_error + || p->event_proxy->upstream_done) + { + ngx_http_proxy_finalize_request(p, ngx_http_send_last(p->request)); + return; + } + + return; +} + + +static void ngx_http_proxy_process_downstream(ngx_event_t *wev) +{ + ngx_connection_t *c; + ngx_http_proxy_ctx_t *p; + + c = wev->data; + p = c->data; + + ngx_log_debug(wev->log, "http proxy process downstream"); + + if (wev->timedout) { + ngx_http_close_connection(c); + return; + } + + if (ngx_event_proxy_write_to_downstream(p->event_proxy) == NGX_ABORT) { + ngx_http_proxy_finalize_request(p, 0); + return; + } + + if (p->event_proxy->downstream_done) { + ngx_http_proxy_finalize_request(p, 0); + return; + } + + if (p->event_proxy->downstream_error) { + ngx_http_close_connection(c); return; } @@ -1076,25 +1117,6 @@ static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) } -static int ngx_http_proxy_init(ngx_cycle_t *cycle) -{ - ngx_http_handler_pt *h; - ngx_http_conf_ctx_t *ctx; - ngx_http_core_main_conf_t *cmcf; - - ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; - cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; - - ngx_test_null(h, ngx_push_array( - &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), - NGX_ERROR); - - *h = ngx_http_proxy_translate_handler; - - return NGX_OK; -} - - static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) { int i; @@ -1121,8 +1143,9 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->header_size = 4096; conf->read_timeout = 30000; - conf->block_size = 4096; - conf->max_block_size = 4096 * 3; + conf->bufs.num = 10; + conf->bufs.size = 4096; + conf->max_busy_len = 8192 + 4096; conf->max_temp_file_size = 4096 * 5; conf->temp_file_write_size = 4096 * 2; @@ -1147,3 +1170,206 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) return conf; } + + +static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_proxy_loc_conf_t *lcf = conf; + + int i, len; + char *err, *host; + ngx_str_t *value; + struct hostent *h; + u_int32_t addr; + ngx_http_conf_ctx_t *ctx; + ngx_http_core_loc_conf_t *clcf; + + + value = cf->args->elts; + + if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) { + return "invalid URL prefix"; + } + + ngx_test_null(lcf->upstream, + ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_t)), + NGX_CONF_ERROR); + + value[1].data += 7; + value[1].len -= 7; + + err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream); + + if (err) { + return err; + } + + ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream->host.len + 1), + NGX_CONF_ERROR); + ngx_cpystrn(host, lcf->upstream->host.data, lcf->upstream->host.len + 1); + + addr = inet_addr(host); + + if (addr == INADDR_NONE) { + h = gethostbyname(host); + + if (h == NULL || h->h_addr_list[0] == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "host %s not found", host); + return NGX_CONF_ERROR; + } + + for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } + + /* MP: ngx_shared_palloc() */ + + ngx_test_null(lcf->peers, + ngx_pcalloc(cf->pool, + sizeof(ngx_peers_t) + + sizeof(ngx_peer_t) * (i - 1)), + NGX_CONF_ERROR); + + lcf->peers->number = i; + + for (i = 0; h->h_addr_list[i] != NULL; i++) { + lcf->peers->peers[i].host.data = host; + lcf->peers->peers[i].host.len = lcf->upstream->host.len; + lcf->peers->peers[i].addr = *(u_int32_t *)(h->h_addr_list[i]); + lcf->peers->peers[i].port = lcf->upstream->port; + + len = INET_ADDRSTRLEN + lcf->upstream->port_text.len + 1; + ngx_test_null(lcf->peers->peers[i].addr_port_text.data, + ngx_palloc(cf->pool, len), + NGX_CONF_ERROR); + + len = ngx_inet_ntop(AF_INET, + (char *) &lcf->peers->peers[i].addr, + lcf->peers->peers[i].addr_port_text.data, + len); + + lcf->peers->peers[i].addr_port_text.data[len++] = ':'; + + ngx_cpystrn(lcf->peers->peers[i].addr_port_text.data + len, + lcf->upstream->port_text.data, + lcf->upstream->port_text.len + 1); + + lcf->peers->peers[i].addr_port_text.len = + len + lcf->upstream->port_text.len + 1; + } + + } else { + + /* MP: ngx_shared_palloc() */ + + ngx_test_null(lcf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)), + NGX_CONF_ERROR); + + lcf->peers->number = 1; + + lcf->peers->peers[0].host.data = host; + lcf->peers->peers[0].host.len = lcf->upstream->host.len; + lcf->peers->peers[0].addr = addr; + lcf->peers->peers[0].port = lcf->upstream->port; + + len = lcf->upstream->host.len + lcf->upstream->port_text.len + 1; + + ngx_test_null(lcf->peers->peers[0].addr_port_text.data, + ngx_palloc(cf->pool, len + 1), + NGX_CONF_ERROR); + + len = lcf->upstream->host.len; + + ngx_memcpy(lcf->peers->peers[0].addr_port_text.data, + lcf->upstream->host.data, len); + + lcf->peers->peers[0].addr_port_text.data[len++] = ':'; + + ngx_cpystrn(lcf->peers->peers[0].addr_port_text.data + len, + lcf->upstream->port_text.data, + lcf->upstream->port_text.len + 1); + } + + ctx = cf->ctx; + clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; + lcf->upstream->location = &clcf->name; + clcf->handler = ngx_http_proxy_handler; + + return NULL; +} + +static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, + ngx_http_proxy_upstream_t *u) +{ + size_t i; + + if (url->data[0] == ':' || url->data[0] == '/') { + return "invalid upstream URL"; + } + + u->host.data = url->data; + u->host_header.data = url->data; + + for (i = 1; i < url->len; i++) { + if (url->data[i] == ':') { + u->port_text.data = &url->data[i] + 1; + u->host.len = i; + } + + if (url->data[i] == '/') { + u->uri.data = &url->data[i]; + u->uri.len = url->len - i; + u->host_header.len = i; + + if (u->host.len == 0) { + u->host.len = i; + } + + if (u->port_text.data == NULL) { + u->port = htons(80); + u->port_text.len = 2; + u->port_text.data = "80"; + return NULL; + } + + u->port_text.len = &url->data[i] - u->port_text.data; + + if (u->port_text.len > 0) { + u->port = ngx_atoi(u->port_text.data, u->port_text.len); + if (u->port > 0) { + u->port = htons((u_short) u->port); + return NULL; + } + } + + return "invalid port in upstream URL"; + } + } + + if (u->host.len == 0) { + u->host.len = i; + } + + u->host_header.len = i; + + u->uri.data = "/"; + u->uri.len = 1; + + if (u->port_text.data == NULL) { + u->port = htons(80); + u->port_text.len = 2; + u->port_text.data = "80"; + return NULL; + } + + u->port_text.len = &url->data[i] - u->port_text.data; + + if (u->port_text.len > 0) { + u->port = ngx_atoi(u->port_text.data, u->port_text.len); + if (u->port > 0) { + u->port = htons((u_short) u->port); + return NULL; + } + } + + return "invalid port in upstream URL"; +} diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h index 5212eb2eb..795373adf 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -9,21 +9,33 @@ typedef struct { - ngx_msec_t connect_timeout; - ngx_msec_t send_timeout; - ssize_t header_size; - ngx_msec_t read_timeout; + ngx_str_t host; + ngx_str_t uri; + ngx_str_t *location; + ngx_str_t host_header; + ngx_str_t port_text; + int port; +} ngx_http_proxy_upstream_t; + + +typedef struct { + ngx_msec_t connect_timeout; + ngx_msec_t send_timeout; + ssize_t header_size; + ngx_msec_t read_timeout; + + ngx_bufs_t bufs; /* STUB */ - int block_size; - int max_block_size; - int max_temp_file_size; - int temp_file_write_size; + int max_busy_len; + int max_temp_file_size; + int temp_file_write_size; /* */ - ngx_path_t *temp_path; + ngx_path_t *temp_path; - ngx_peers_t *peers; + ngx_http_proxy_upstream_t *upstream; + ngx_peers_t *peers; } ngx_http_proxy_loc_conf_t; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 59d4d6f58..1eee5725f 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -6,9 +6,6 @@ #include -/* STUB */ -int ngx_http_static_handler(ngx_http_request_t *r); -/**/ static void ngx_http_phase_event_handler(ngx_event_t *rev); static void ngx_http_run_phases(ngx_http_request_t *r); @@ -304,7 +301,6 @@ static void ngx_http_run_phases(ngx_http_request_t *r) return; } - /* TODO: no handlers found ? */ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -346,164 +342,20 @@ ngx_log_debug(r->connection->log, "rc: %d" _ rc); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if ((ngx_io.flags & NGX_IO_SENDFILE) == 0 || clcf->sendfile == 0) { + if (!(ngx_io.flags & NGX_IO_SENDFILE) || !clcf->sendfile) { r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; } - return NGX_OK; -} - - -int ngx_http_core_translate_handler(ngx_http_request_t *r) -{ - char *location, *last; - ngx_err_t err; - ngx_table_elt_t *h; - ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->handler) { + /* + * if the location already has content handler then skip + * the translation phase + */ + r->content_handler = clcf->handler; - return NGX_OK; + r->phase++; } - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (r->uri.data[r->uri.len - 1] == '/') { - if (r->path.data == NULL) { - ngx_test_null(r->path.data, - ngx_palloc(r->pool, - clcf->doc_root.len + r->uri.len), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data, - clcf->doc_root.len), - r->uri.data, r->uri.len + 1); - - } else { - r->path.data[r->path.len] = '\0'; - } - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "directory index of \"%s\" is forbidden", r->path.data); - - return NGX_HTTP_FORBIDDEN; - } - - /* "+ 2" is for trailing '/' in redirect and '\0' */ - ngx_test_null(r->file.name.data, - ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - location = ngx_cpymem(r->file.name.data, clcf->doc_root.data, - clcf->doc_root.len), - - last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1); - -ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); - -#if (WIN9X) - - /* - * There is no way to open a file or a directory in Win9X with - * one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag. - * so we need to check its type before the opening - */ - - r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data); - if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { - err = ngx_errno; - ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - ngx_file_type_n " \"%s\" failed", r->file.name.data); - - if (err == NGX_ENOENT || err == NGX_ENOTDIR) { - return NGX_HTTP_NOT_FOUND; - - } else if (err == NGX_EACCES) { - return NGX_HTTP_FORBIDDEN; - - } else { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } - -#else - - if (r->file.fd == NGX_INVALID_FILE) { - r->file.fd = ngx_open_file(r->file.name.data, - NGX_FILE_RDONLY, NGX_FILE_OPEN); - } - - 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; - - } else if (err == NGX_EACCES) { - return NGX_HTTP_FORBIDDEN; - - } else { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } - -ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd); - - if (!r->file.info_valid) { - if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_stat_fd_n " \"%s\" failed", r->file.name.data); - - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - r->file.name.data); - } - - r->file.fd = NGX_INVALID_FILE; - - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - r->file.info_valid = 1; - } -#endif - - if (ngx_is_dir(r->file.info)) { -ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); - -#if !(WIN9X) - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", r->file.name.data); - } - - r->file.fd = NGX_INVALID_FILE; -#endif - - /* BROKEN: need to include server name */ - - ngx_test_null(h, ngx_push_table(r->headers_out.headers), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - *last++ = '/'; - *last = '\0'; - h->key.len = 8; - h->key.data = "Location" ; - h->value.len = last - location; - h->value.data = location; - r->headers_out.location = h; - - return NGX_HTTP_MOVED_PERMANENTLY; - } - - r->content_handler = ngx_http_static_handler; - return NGX_OK; } @@ -609,18 +461,15 @@ int ngx_http_delay_handler(ngx_http_request_t *r) static int ngx_http_core_init(ngx_cycle_t *cycle) { +#if 0 ngx_http_handler_pt *h; +#endif ngx_http_conf_ctx_t *ctx; ngx_http_core_main_conf_t *cmcf; ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; - ngx_test_null(h, ngx_push_array( - &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), - NGX_ERROR); - *h = ngx_http_core_translate_handler; - #if 0 ngx_test_null(h, ngx_push_array( &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 5efbf3e2d..71b1c21cf 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -765,7 +765,7 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc) { ngx_log_debug(r->connection->log, "finalize http request"); - if (r->main || r->closed) { + if (rc == NGX_DONE || r->main || r->closed) { return; } diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index 14c071775..7e7a42b34 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -163,11 +163,11 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error) } else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) { /* 4XX */ - err = error - NGX_HTTP_BAD_REQUEST + 4; + err = error - NGX_HTTP_BAD_REQUEST + 3; } else { /* 5XX */ - err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 17; + err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17; } if (r->keepalive != 0) { diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index cef432821..e61cc333f 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -22,8 +22,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) if (rev->available == 0) { if (rev->eof) { + rev->ready = 0; if (rev->error) { - rev->ready = 0; ngx_set_socket_errno(rev->error); return ngx_unix_recv_error(rev, rev->error); } @@ -44,7 +44,10 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { rev->available -= n; if (rev->available <= 0) { - rev->ready = 0; + if (!rev->eof) { + rev->ready = 0; + } + if (rev->available < 0) { rev->available = 0; }