# HG changeset patch # User Igor Sysoev # Date 1067288460 0 # Node ID 96993d4d50679e838d0c9ec7c0af087cb8663616 # Parent 88abd07d9f62b2f63eb84e2a04f0f8b47e6a4afa nginx-0.0.1-2003-10-28-00:01:00 import diff --git a/src/core/ngx_alloc.h b/src/core/ngx_alloc.h --- a/src/core/ngx_alloc.h +++ b/src/core/ngx_alloc.h @@ -17,6 +17,8 @@ #define ngx_test_null(p, alloc, rc) if ((p = alloc) == NULL) { return rc; } +#define ngx_is_null(p, alloc) if ((p = alloc) == NULL) + typedef struct ngx_pool_large_s ngx_pool_large_t; diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -84,7 +84,6 @@ typedef struct { unsigned sendfile; unsigned need_in_memory; unsigned need_in_temp; - unsigned copy_chain; ngx_pool_t *pool; int hunks; @@ -96,6 +95,14 @@ typedef struct { } ngx_output_chain_ctx_t; +typedef struct { + ngx_chain_t *out; + ngx_chain_t **last; + ngx_connection_t *connection; + ngx_pool_t *pool; +} ngx_chain_write_ctx_t; + + #define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR @@ -144,6 +151,8 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_poo int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in); +int ngx_chain_write(void *data, ngx_chain_t *in); + int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in); void ngx_chain_update_chains(ngx_chain_t **free, ngx_chain_t **busy, ngx_chain_t **out, ngx_hunk_tag_t tag); diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -1,6 +1,7 @@ #include #include +#include #define NGX_NONE 1 @@ -30,8 +31,7 @@ int ngx_output_chain(ngx_output_chain_ct return ctx->output_filter(ctx->output_ctx, in); } - if (!ctx->copy_chain - && in->next == NULL + if (in->next == NULL && (!ngx_output_chain_need_to_copy(ctx, in->hunk))) { return ctx->output_filter(ctx->output_ctx, in); @@ -250,3 +250,31 @@ ngx_log_debug(src->file->log, "READ: %qd return NGX_OK; } + + +int ngx_chain_write(void *data, ngx_chain_t *in) +{ + ngx_chain_write_ctx_t *ctx = data; + + ngx_chain_t *cl; + + + for (/* void */; in; in = in->next) { + ngx_alloc_link_and_set_hunk(cl, in->hunk, ctx->pool, NGX_ERROR); + *ctx->last = cl; + ctx->last = &cl->next; + } + + ctx->out = ngx_write_chain(ctx->connection, ctx->out); + + if (ctx->out == NGX_CHAIN_ERROR) { + return NGX_ERROR; + } + + if (ctx->out == NULL) { + ctx->last = &ctx->out; + return NGX_OK; + } + + return NGX_AGAIN; +} diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -189,7 +189,7 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p if (rc == -1) { err = ngx_socket_errno; if (err != NGX_EINPROGRESS) { - ngx_log_error(NGX_LOG_CRIT, pc->log, err, "connect() failed"); + ngx_log_error(NGX_LOG_ERR, pc->log, err, "connect() failed"); if (ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, @@ -211,6 +211,10 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p event = NGX_LEVEL_EVENT; } + if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { + return NGX_ERROR; + } + if (rc == -1) { /* NGX_EINPROGRESS */ @@ -224,10 +228,6 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p wev->ready = 1; - if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { - return NGX_ERROR; - } - 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 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -175,7 +175,6 @@ static char connection_close_header[] = static int ngx_http_proxy_handler(ngx_http_request_t *r) { - int rc; ngx_http_proxy_ctx_t *p; ngx_http_create_ctx(r, p, ngx_http_proxy_module, @@ -208,11 +207,9 @@ static int ngx_http_proxy_handler(ngx_ht r->request_body_handler = ngx_http_proxy_init_request; r->data = p; - rc = ngx_http_read_client_request_body(r, p->lcf->request_buffer_size); + ngx_http_read_client_request_body(r, p->lcf->request_buffer_size); - if (rc != NGX_OK) { - return rc; - } + return NGX_DONE; } ngx_http_proxy_init_request(p); @@ -227,16 +224,31 @@ static void ngx_http_proxy_init_request( ngx_chain_t *cl; ngx_http_request_t *r; - ngx_output_chain_ctx_t *ctx; + ngx_output_chain_ctx_t *out_ctx; + ngx_chain_write_ctx_t *write_ctx; r = p->request; +ngx_log_debug(r->connection->log, "timer_set: %d" _ + r->connection->read->timer_set); + + if (r->connection->read->timer_set) { + ngx_del_timer(r->connection->read); + } + + ngx_is_null(cl, ngx_http_proxy_create_request(p)) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + +#if 0 cl = ngx_http_proxy_create_request(p); if (cl == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } +#endif if (r->request_hunks) { cl->next = r->request_hunks; @@ -251,28 +263,36 @@ static void ngx_http_proxy_init_request( r->connection->log->handler = ngx_http_proxy_log_error; p->action = "connecting to upstream"; - ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); - if (ctx == NULL) { + out_ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); + if (out_ctx == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); } - p->output_chain_ctx = ctx; + p->output_chain_ctx = out_ctx; if (r->request_body_hunk) { - ctx->free = ngx_alloc_chain_link(r->pool); - if (ctx->free == NULL) { + out_ctx->free = ngx_alloc_chain_link(r->pool); + if (out_ctx->free == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); } - ctx->free->hunk = r->request_body_hunk; - ctx->free->next = NULL; + out_ctx->free->hunk = r->request_body_hunk; + out_ctx->free->next = NULL; } - ctx->sendfile = r->sendfile; - ctx->copy_chain = 1; - ctx->pool = r->pool; - ctx->bufs.num = 1; - ctx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; - ctx->output_filter = (ngx_output_chain_filter_pt) ngx_write_chain; + out_ctx->sendfile = r->sendfile; + out_ctx->pool = r->pool; + out_ctx->bufs.num = 1; + out_ctx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; + out_ctx->output_filter = (ngx_output_chain_filter_pt) ngx_chain_write; + + write_ctx = ngx_pcalloc(r->pool, sizeof(ngx_chain_write_ctx_t)); + if (write_ctx == NULL) { + ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + } + + out_ctx->output_ctx = write_ctx; + write_ctx->pool = r->pool; + write_ctx->last = &write_ctx->out; ngx_http_proxy_send_request(p); } @@ -418,15 +438,19 @@ static void ngx_http_proxy_send_request( int rc; ngx_chain_t *cl; ngx_connection_t *c; + ngx_chain_write_ctx_t *ctx; c = p->upstream.connection; for ( ;; ) { if (c) { - p->output_chain_ctx->output_ctx = c; + p->action = "sending request to upstream"; + ctx = p->output_chain_ctx->output_ctx; + ctx->connection = c; rc = ngx_output_chain(p->output_chain_ctx, - p->request->request_hunks); + !p->request_sent ? p->request->request_hunks: + NULL); if (rc != NGX_ERROR) { p->request_sent = 1; @@ -438,8 +462,23 @@ static void ngx_http_proxy_send_request( if (rc == NGX_AGAIN) { ngx_add_timer(c->write, p->lcf->send_timeout); + if (ngx_handle_write_event(c->write, /* STUB: lowat */ 0) + == NGX_ERROR) + { + ngx_http_proxy_finalize_request(p, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } else { - /* TODO: del event */ + + /* rc == NGX_OK */ + + if (ngx_handle_level_write_event(c->write) == NGX_ERROR) { + ngx_http_proxy_finalize_request(p, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } if (c->tcp_nopush) { if (ngx_tcp_push(c->fd) == NGX_ERROR) { @@ -462,6 +501,8 @@ static void ngx_http_proxy_send_request( } for ( ;; ) { + p->action = "connecting to upstream"; + rc = ngx_event_connect_peer(&p->upstream); if (rc == NGX_ERROR) { @@ -1245,6 +1286,9 @@ ngx_log_debug(p->request->connection->lo static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) { + ngx_log_debug(p->request->connection->log, + "finalize http proxy request"); + if (p->upstream.connection) { ngx_http_proxy_close_connection(p->upstream.connection); p->upstream.connection = NULL; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -130,6 +130,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, doc_root), 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, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, client_body_timeout), + NULL}, + {ngx_string("sendfile"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, @@ -842,6 +849,7 @@ static void *ngx_http_core_create_loc_co */ + lcf->client_body_timeout = NGX_CONF_UNSET; lcf->sendfile = NGX_CONF_UNSET; lcf->send_timeout = NGX_CONF_UNSET; lcf->discarded_buffer_size = NGX_CONF_UNSET; @@ -913,6 +921,8 @@ static char *ngx_http_core_merge_loc_con ngx_conf_merge_str_value(conf->default_type, prev->default_type, "text/plain"); + ngx_conf_merge_msec_value(conf->client_body_timeout, + prev->client_body_timeout, 10000); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 10000); ngx_conf_merge_size_value(conf->discarded_buffer_size, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -110,6 +110,7 @@ typedef struct { ngx_array_t *types; ngx_str_t default_type; + ngx_msec_t client_body_timeout; /* client_body_timeout */ int sendfile; /* sendfile */ ngx_msec_t send_timeout; /* send_timeout */ ssize_t send_lowat; /* send_lowat */ diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -32,27 +32,28 @@ #define NGX_HTTP_PARSE_INVALID_CL_HEADER 17 -#define NGX_HTTP_OK 200 -#define NGX_HTTP_PARTIAL_CONTENT 206 +#define NGX_HTTP_OK 200 +#define NGX_HTTP_PARTIAL_CONTENT 206 -#define NGX_HTTP_SPECIAL_RESPONSE 300 -#define NGX_HTTP_MOVED_PERMANENTLY 301 -#define NGX_HTTP_MOVED_TEMPORARILY 302 -#define NGX_HTTP_NOT_MODIFIED 304 +#define NGX_HTTP_SPECIAL_RESPONSE 300 +#define NGX_HTTP_MOVED_PERMANENTLY 301 +#define NGX_HTTP_MOVED_TEMPORARILY 302 +#define NGX_HTTP_NOT_MODIFIED 304 -#define NGX_HTTP_BAD_REQUEST 400 -#define NGX_HTTP_FORBIDDEN 403 -#define NGX_HTTP_NOT_FOUND 404 -#define NGX_HTTP_NOT_ALLOWED 405 -#define NGX_HTTP_REQUEST_TIME_OUT 408 -#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 -#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 +#define NGX_HTTP_BAD_REQUEST 400 +#define NGX_HTTP_FORBIDDEN 403 +#define NGX_HTTP_NOT_FOUND 404 +#define NGX_HTTP_NOT_ALLOWED 405 +#define NGX_HTTP_REQUEST_TIME_OUT 408 +#define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE 413 +#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 +#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 -#define NGX_HTTP_INTERNAL_SERVER_ERROR 500 -#define NGX_HTTP_NOT_IMPLEMENTED 501 -#define NGX_HTTP_BAD_GATEWAY 502 -#define NGX_HTTP_SERVICE_UNAVAILABLE 503 -#define NGX_HTTP_GATEWAY_TIME_OUT 504 +#define NGX_HTTP_INTERNAL_SERVER_ERROR 500 +#define NGX_HTTP_NOT_IMPLEMENTED 501 +#define NGX_HTTP_BAD_GATEWAY 502 +#define NGX_HTTP_SERVICE_UNAVAILABLE 503 +#define NGX_HTTP_GATEWAY_TIME_OUT 504 diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -30,8 +30,11 @@ int ngx_http_read_client_request_body(ng if (size >= r->headers_in.content_length_n) { r->header_in->pos += r->headers_in.content_length_n; + return NGX_OK; } + + r->header_in->pos = r->header_in->last; } r->request_body_len = r->headers_in.content_length_n - size; @@ -73,10 +76,11 @@ int ngx_http_read_client_request_body(ng static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) { - ssize_t n, size; - ngx_hunk_t *h; - ngx_connection_t *c; - ngx_http_request_t *r; + ssize_t n, size; + 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; @@ -87,6 +91,11 @@ static void ngx_http_read_client_request r->request_hunks); /* TODO: n == 0 or not complete and level event */ + if (n == NGX_ERROR) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + r->request_body_hunk->pos = r->request_body_hunk->start; r->request_body_hunk->last = r->request_body_hunk->start; } @@ -100,6 +109,9 @@ static void ngx_http_read_client_request n = ngx_recv(c, r->request_body_hunk->last, size); if (n == NGX_AGAIN) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(rev, clcf->client_body_timeout); + if (ngx_handle_read_event(rev) == NGX_ERROR) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } @@ -132,6 +144,10 @@ static void ngx_http_read_client_request r->request_hunks); /* TODO: n == 0 or not complete and level event */ + if (n == NGX_ERROR) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } h = ngx_calloc_hunk(r->pool); if (h == NULL) { diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -78,6 +78,14 @@ static char error_408_page[] = ; +static char error_413_page[] = +"" CRLF +"413 Request Entity Too Large" CRLF +"" CRLF +"

413 Request Entity Too Large

" CRLF +; + + static char error_414_page[] = "" CRLF "414 Request-URI Too Large" CRLF @@ -110,6 +118,14 @@ static char error_502_page[] = ; +static char error_503_page[] = +"" CRLF +"503 Service Temporarily Unavailable" CRLF +"" CRLF +"

503 Service Temporarily Unavailable

" CRLF +; + + static char error_504_page[] = "" CRLF "504 Gateway Time-out" CRLF @@ -137,7 +153,7 @@ static ngx_str_t error_pages[] = { ngx_null_string, /* 410 */ ngx_null_string, /* 411 */ ngx_null_string, /* 412 */ - ngx_null_string, /* 413 */ + ngx_string(error_413_page), ngx_string(error_414_page), ngx_null_string, /* 415 */ ngx_string(error_416_page), @@ -145,7 +161,7 @@ static ngx_str_t error_pages[] = { ngx_string(error_500_page), ngx_null_string, /* 501 */ ngx_string(error_502_page), - ngx_null_string, /* 503 */ + ngx_string(error_503_page), ngx_string(error_504_page) }; @@ -181,6 +197,7 @@ int ngx_http_special_response_handler(ng if (r->keepalive != 0) { switch (error) { case NGX_HTTP_BAD_REQUEST: + case NGX_HTTP_REQUEST_ENTITY_TOO_LARGE: case NGX_HTTP_REQUEST_URI_TOO_LARGE: case NGX_HTTP_INTERNAL_SERVER_ERROR: r->keepalive = 0;