# HG changeset patch # User Igor Sysoev # Date 1230299022 0 # Node ID 26d9d4a41e914b8e3c36f08a76ee8370e54642fb # Parent 821497e016b65f8a67dd68bd15d53a0f96ff8377 send "100 Continue" just before reading request body 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 @@ -23,7 +23,6 @@ typedef struct { static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r); static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r, ngx_http_location_tree_node_t *node); -static ngx_int_t ngx_http_core_send_continue(ngx_http_request_t *r); static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); @@ -818,7 +817,7 @@ ngx_http_core_find_config_phase(ngx_http { u_char *p; size_t len; - ngx_int_t rc, expect; + ngx_int_t rc; ngx_http_core_loc_conf_t *clcf; r->content_handler = NULL; @@ -862,18 +861,6 @@ ngx_http_core_find_config_phase(ngx_http return NGX_OK; } - if (r->headers_in.expect - && r == r->main - && r->http_version > NGX_HTTP_VERSION_10) - { - expect = ngx_http_core_send_continue(r); - - if (expect != NGX_OK) { - ngx_http_finalize_request(r, expect); - return NGX_OK; - } - } - if (rc == NGX_DONE) { r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { @@ -1493,45 +1480,6 @@ ngx_http_core_find_static_location(ngx_h } -static ngx_int_t -ngx_http_core_send_continue(ngx_http_request_t *r) -{ - ngx_int_t n; - ngx_str_t *expect; - - if (r->expect_tested) { - return NGX_OK; - } - - r->expect_tested = 1; - - expect = &r->headers_in.expect->value; - - if (expect->len != sizeof("100-continue") - 1 - || ngx_strncasecmp(expect->data, (u_char *) "100-continue", - sizeof("100-continue") - 1) - != 0) - { - return NGX_OK; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "send 100 Continue"); - - n = r->connection->send(r->connection, - (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF, - sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1); - - if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) { - return NGX_OK; - } - - /* we assume that such small packet should be send successfully */ - - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - void * ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash) { @@ -2128,6 +2076,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->internal = 1; sr->discard_body = r->discard_body; + sr->expect_tested = 1; sr->main_filter_need_in_memory = r->main_filter_need_in_memory; sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; 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 @@ -15,6 +15,7 @@ static ngx_int_t ngx_http_write_request_ ngx_chain_t *body); static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r); +static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r); /* @@ -41,6 +42,10 @@ ngx_http_read_client_request_body(ngx_ht return NGX_OK; } + if (ngx_http_test_expect(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -433,6 +438,10 @@ ngx_http_discard_request_body(ngx_http_r return NGX_OK; } + if (ngx_http_test_expect(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + rev = r->connection->read; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body"); @@ -581,3 +590,45 @@ ngx_http_read_discarded_request_body(ngx return NGX_AGAIN; } + + +static ngx_int_t +ngx_http_test_expect(ngx_http_request_t *r) +{ + ngx_int_t n; + ngx_str_t *expect; + + if (r->expect_tested + || r->headers_in.expect == NULL + || r->http_version < NGX_HTTP_VERSION_11) + { + return NGX_OK; + } + + r->expect_tested = 1; + + expect = &r->headers_in.expect->value; + + if (expect->len != sizeof("100-continue") - 1 + || ngx_strncasecmp(expect->data, (u_char *) "100-continue", + sizeof("100-continue") - 1) + != 0) + { + return NGX_OK; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "send 100 Continue"); + + n = r->connection->send(r->connection, + (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF, + sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1); + + if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) { + return NGX_OK; + } + + /* we assume that such small packet should be send successfully */ + + return NGX_ERROR; +} 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 @@ -379,6 +379,8 @@ ngx_http_special_response_handler(ngx_ht } } + r->expect_tested = 1; + if (ngx_http_discard_request_body(r) != NGX_OK) { error = NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -431,11 +433,18 @@ static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) { u_char ch, *p, *last; + ngx_int_t overwrite; ngx_str_t *uri, *args, u, a; ngx_table_elt_t *location; ngx_http_core_loc_conf_t *clcf; - r->err_status = err_page->overwrite; + overwrite = err_page->overwrite; + + if (overwrite && overwrite != NGX_HTTP_OK) { + r->expect_tested = 1; + } + + r->err_status = overwrite; r->zero_in_uri = 0;