From ae02c19867083c6ad3e51506109cb37bca1d36d1 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 19 Mar 2004 05:25:53 +0000 Subject: [PATCH] nginx-0.0.3-2004-03-19-08:25:53 import --- src/event/ngx_event_pipe.c | 65 +++++++++++++----- src/http/modules/ngx_http_index_handler.c | 35 +++++++--- .../modules/proxy/ngx_http_proxy_upstream.c | 8 +-- src/http/ngx_http_core_module.c | 10 +++ src/http/ngx_http_core_module.h | 1 + src/http/ngx_http_request.c | 34 ++++++++-- src/http/ngx_http_request.h | 1 + src/http/ngx_http_request_body.c | 66 ++++++++++++------- src/http/ngx_http_special_response.c | 2 - src/os/unix/ngx_process_cycle.c | 32 ++++----- 10 files changed, 179 insertions(+), 75 deletions(-) diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index c5b15bda9..b7cb6b6ae 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -254,7 +254,6 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) p->upstream_eof = 1; break; } - } p->read_length += n; @@ -269,7 +268,7 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) if (n >= size) { cl->hunk->last = cl->hunk->end; -/* STUB */ cl->hunk->num = p->num++; + /* STUB */ cl->hunk->num = p->num++; if (p->input_filter(p, cl->hunk) == NGX_ERROR) { return NGX_ABORT; @@ -288,7 +287,9 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) } if ((p->upstream_eof || p->upstream_error) && p->free_raw_hunks) { -/* STUB */ p->free_raw_hunks->hunk->num = p->num++; + + /* STUB */ p->free_raw_hunks->hunk->num = p->num++; + if (p->input_filter(p, p->free_raw_hunks->hunk) == NGX_ERROR) { return NGX_ABORT; } @@ -326,9 +327,39 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) return ngx_event_pipe_drain_chains(p); } - if ((p->upstream_eof || p->upstream_error || p->upstream_done) - && p->out == NULL && p->in == NULL) - { + if (p->upstream_eof || p->upstream_error || p->upstream_done) { + + /* pass the p->out and p->in chains to the output filter */ + + if (p->out) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, + "pipe write downstream flush out"); + + if (p->output_filter(p->output_ctx, p->out) == NGX_ERROR) { + p->downstream_error = 1; + return ngx_event_pipe_drain_chains(p); + } + + p->out = NULL; + } + + if (p->in) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, + "pipe write downstream flush in"); + + if (p->output_filter(p->output_ctx, p->in) == NGX_ERROR) { + p->downstream_error = 1; + return ngx_event_pipe_drain_chains(p); + } + + p->in = NULL; + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, + "pipe write downstream done"); + + /* TODO: free unused hunks */ + p->downstream_done = 1; break; } @@ -338,8 +369,9 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) } /* - * bsize is the busy hunks size - * to_write is the size of data that to be written + * bsize is the size of the busy hunks, + * to_write is the size of data in these hunks that + * would be written to a socket */ bsize = 0; @@ -390,25 +422,24 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) } if (out == NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, - "pipe busy hunk data: %d", to_write); + "pipe busy hunk data to write: %d", to_write); if (!(p->upstream_blocked && to_write)) { break; } - /* - * if the upstream is blocked and there are the busy hunks - * to write then write these hunks - */ } + /* + * if the upstream is blocked and there are the busy hunks + * to write then write these hunks + */ + if (p->output_filter(p->output_ctx, out) == NGX_ERROR) { p->downstream_error = 1; - - /* handle the downstream error at the begin of a cycle */ - - continue; + return ngx_event_pipe_drain_chains(p); } ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag); diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 12e96f1c1..de609ac47 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -21,7 +21,7 @@ typedef struct { } ngx_http_index_ctx_t; -#define NGX_HTTP_DEFAULT_INDEX (u_char *) "index.html" +#define NGX_HTTP_DEFAULT_INDEX "index.html" static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, @@ -98,7 +98,6 @@ ngx_module_t ngx_http_index_module = { int ngx_http_index_handler(ngx_http_request_t *r) { u_char *name; - size_t len; ngx_fd_t fd; ngx_int_t rc; ngx_str_t *index; @@ -161,18 +160,38 @@ int ngx_http_index_handler(ngx_http_request_t *r) #endif - len = clcf->root.len + r->uri.len + ilcf->max_index_len; - if (!(ctx->path.data = ngx_palloc(r->pool, len))) { + ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + + ilcf->max_index_len + - clcf->alias * clcf->name.len); + if (ctx->path.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data, clcf->root.len); - ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data, - r->uri.len + 1); - ctx->path.len = ctx->last - ctx->path.data; + + if (clcf->alias) { + ctx->last = ngx_cpystrn(ctx->redirect.data, + r->uri.data + clcf->name.len, + r->uri.len + 1 - clcf->name.len); + + /* + * aliases usually have trailling "/", + * set it in the start of the possible redirect + */ + + if (*ctx->redirect.data != '/') { + ctx->redirect.data--; + } + + } else { + ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data, + r->uri.len + 1); + } } + ctx->path.len = ctx->last - ctx->path.data; + index = ilcf->indices.elts; for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) { @@ -398,7 +417,7 @@ static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, ngx_test_null(index, ngx_push_array(&conf->indices), NGX_CONF_ERROR); index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1; - index->data = NGX_HTTP_DEFAULT_INDEX; + index->data = (u_char *) NGX_HTTP_DEFAULT_INDEX; conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX); return NGX_CONF_OK; diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index f4bc1c4ed..d72f09e0b 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -85,8 +85,8 @@ int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p) return NGX_DONE; } - if (rc == NGX_ERROR) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_ERROR) { + return rc; } } @@ -1243,8 +1243,8 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev) #endif if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, - "http proxy upstream exit"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0, + "http proxy upstream exit: " PTR_FMT, ep->out); ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock); ngx_http_proxy_finalize_request(p, 0); return; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index d95e8f15d..e3c85986c 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -142,6 +142,13 @@ static ngx_command_t ngx_http_core_commands[] = { 0, NULL }, + { ngx_string("client_max_body_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, client_max_body_size), + NULL }, + { ngx_string("client_body_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -1147,6 +1154,7 @@ static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf) */ + lcf->client_max_body_size = NGX_CONF_UNSET_SIZE; lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; lcf->sendfile = NGX_CONF_UNSET; lcf->tcp_nopush = NGX_CONF_UNSET; @@ -1225,6 +1233,8 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, ngx_conf_merge_str_value(conf->default_type, prev->default_type, "text/plain"); + ngx_conf_merge_size_value(conf->client_max_body_size, + prev->client_max_body_size, 10 * 1024 * 1024); ngx_conf_merge_msec_value(conf->client_body_timeout, prev->client_body_timeout, 60000); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index e4c624d59..3af3ed480 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -121,6 +121,7 @@ typedef struct { ngx_array_t *types; ngx_str_t default_type; + size_t client_max_body_size; /* client_max_body_size */ size_t send_lowat; /* send_lowat */ size_t discarded_buffer_size; /* discarded_buffer_size */ diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index b69e79082..1e65a47bb 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -38,7 +38,8 @@ static char *client_header_errors[] = { "client %s sent invalid header, URL: %s", "client %s sent too long header line, URL: %s", "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s", - "client %s sent invalid \"Content-Length\" header, URL: %s" + "client %s sent invalid \"Content-Length\" header, URL: %s", + "client %s wanted to send too large body: " SIZE_T_FMT " bytes, URL: %s" }; @@ -847,6 +848,21 @@ static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) if (r->headers_in.content_length_n == NGX_ERROR) { return NGX_HTTP_PARSE_INVALID_CL_HEADER; } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http cl: " SIZE_T_FMT " max: " SIZE_T_FMT, + r->headers_in.content_length_n, + clcf->client_max_body_size); + + if (clcf->client_max_body_size + && clcf->client_max_body_size + < (size_t) r->headers_in.content_length_n) + { + return NGX_HTTP_PARSE_ENTITY_TOO_LARGE; + } + } if (r->headers_in.connection) { @@ -884,8 +900,8 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc) return; } - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http finalize request"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http finalize request: %d", rc); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { @@ -1590,9 +1606,19 @@ static void ngx_http_client_error(ngx_http_request_t *r, r->connection->log->handler = NULL; if (ctx->url) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + if (client_error == NGX_HTTP_PARSE_ENTITY_TOO_LARGE) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR], + ctx->client, r->headers_in.content_length_n, ctx->url); + + error = NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + r->lingering_close = 1; + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR], ctx->client, ctx->url); + } } else { if (error == NGX_HTTP_REQUEST_URI_TOO_LARGE) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 68ab7cb14..89cabdb9f 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -30,6 +30,7 @@ #define NGX_HTTP_PARSE_TOO_LONG_HEADER 15 #define NGX_HTTP_PARSE_NO_HOST_HEADER 16 #define NGX_HTTP_PARSE_INVALID_CL_HEADER 17 +#define NGX_HTTP_PARSE_ENTITY_TOO_LARGE 18 #define NGX_HTTP_OK 200 diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 4b97b430e..2bc63f780 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -6,11 +6,13 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev); +static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, size_t request_buffer_size) { + ngx_int_t rc; ssize_t size; ngx_hunk_t *h; ngx_chain_t *cl; @@ -48,11 +50,6 @@ ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, ngx_test_null(r->request_body_hunk, ngx_create_temp_hunk(r->pool, size), NGX_ERROR); - r->connection->read->event_handler = - ngx_http_read_client_request_body_handler; - - ngx_http_read_client_request_body_handler(r->connection->read); - ngx_alloc_link_and_set_hunk(cl, r->request_body_hunk, r->pool, NGX_ERROR); @@ -63,25 +60,39 @@ ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, r->request_hunks = cl; } - if (r->request_body_len) { - return NGX_AGAIN; - } + r->connection->read->event_handler = + ngx_http_read_client_request_body_handler; - return NGX_OK; + return ngx_http_do_read_client_request_body(r); } static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) +{ + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_request_t *r; + + c = rev->data; + r = c->data; + + rc = ngx_http_do_read_client_request_body(r); + + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + ngx_http_finalize_request(r, rc); + } +} + + +static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r) { size_t size; ssize_t n; ngx_hunk_t *h; ngx_connection_t *c; - ngx_http_request_t *r; ngx_http_core_loc_conf_t *clcf; - c = rev->data; - r = c->data; + c = r->connection; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http read client request body"); @@ -95,8 +106,7 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->temp_file->offset += n; @@ -113,15 +123,18 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) n = ngx_recv(c, r->request_body_hunk->last, size); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http client request body recv " SIZE_T_FMT, n); + if (n == NGX_AGAIN) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(rev, clcf->client_body_timeout); + ngx_add_timer(c->read, clcf->client_body_timeout); - if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - return; + return NGX_AGAIN; } if (n == 0) { @@ -130,8 +143,7 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) } if (n == 0 || n == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return; + return NGX_HTTP_BAD_REQUEST; } r->request_body_hunk->last += n; @@ -142,8 +154,12 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) } } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http client request body left " SIZE_T_FMT, + r->request_body_len); + if (r->request_body_len) { - return; + return NGX_AGAIN; } if (r->temp_file->file.fd != NGX_INVALID_FILE) { @@ -156,14 +172,12 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) /* TODO: n == 0 or not complete and level event */ if (n == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } h = ngx_calloc_hunk(r->pool); if (h == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->type = NGX_HUNK_FILE; @@ -180,4 +194,6 @@ static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) } r->request_body_handler(r->data); + + return NGX_OK; } diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index ff26e902b..5ffebb4c2 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -204,8 +204,6 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error) if (r->lingering_close == 1) { switch (error) { case NGX_HTTP_BAD_REQUEST: - case NGX_HTTP_REQUEST_URI_TOO_LARGE: - case NGX_HTTP_INTERNAL_SERVER_ERROR: r->lingering_close = 0; } } diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 76d6bb503..e4d95ada9 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -38,24 +38,26 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx) ngx_msec_t delay; ngx_core_conf_t *ccf; - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - sigaddset(&set, SIGALRM); - sigaddset(&set, SIGINT); - sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); - sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); - sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); - sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); - sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); - sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); + if (ngx_process == NGX_PROCESS_MASTER) { + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigaddset(&set, SIGALRM); + sigaddset(&set, SIGINT); + sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); + sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); - if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "sigprocmask() failed"); + if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed"); + } + + sigemptyset(&set); } - sigemptyset(&set); - ngx_setproctitle("master process"); ngx_new_binary = 0;