Repository: trafficserver Updated Branches: refs/heads/master f660f5667 -> e5da353c5
TS-1125: POST's with Expect: 100-continue are slowed by delayed 100 response Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e5da353c Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e5da353c Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e5da353c Branch: refs/heads/master Commit: e5da353c51fc6b1bc5cc150db4a5f4f4e334fd6c Parents: f660f56 Author: Feifei Cai <[email protected]> Authored: Wed May 21 16:19:49 2014 -0700 Committer: Bryan Call <[email protected]> Committed: Wed May 21 16:20:16 2014 -0700 ---------------------------------------------------------------------- mgmt/RecordsConfig.cc | 2 ++ proxy/hdrs/HTTP.cc | 4 ++++ proxy/hdrs/HTTP.h | 2 ++ proxy/hdrs/HdrToken.cc | 6 ++++-- proxy/http/HttpConfig.cc | 4 ++++ proxy/http/HttpConfig.h | 5 ++++- proxy/http/HttpSM.cc | 26 ++++++++++++++++++++++++++ proxy/http/HttpTransact.cc | 5 +++++ proxy/http/HttpTransactHeaders.cc | 12 ++++++++++++ proxy/http/HttpTransactHeaders.h | 1 + 10 files changed, 64 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/mgmt/RecordsConfig.cc ---------------------------------------------------------------------- diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 31506a5..cb46861 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -431,6 +431,8 @@ RecordElement RecordsConfig[] = { // # {RECT_CONFIG, "proxy.config.http.send_http11_requests", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL} , + {RECT_CONFIG, "proxy.config.http.send_100_continue_response", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL} + , {RECT_CONFIG, "proxy.config.http.share_server_sessions", RECD_INT, "2", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL} , {RECT_CONFIG, "proxy.config.http.server_session_sharing.match", RECD_STRING, "both", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/hdrs/HTTP.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc index 24ad43b..5933381 100644 --- a/proxy/hdrs/HTTP.cc +++ b/proxy/hdrs/HTTP.cc @@ -109,6 +109,7 @@ const char *HTTP_VALUE_PROXY_REVALIDATE; const char *HTTP_VALUE_PUBLIC; const char *HTTP_VALUE_S_MAXAGE; const char *HTTP_VALUE_NEED_REVALIDATE_ONCE; +const char *HTTP_VALUE_100_CONTINUE; // Cache-control: extension "need-revalidate-once" is used internally by T.S. // to invalidate a document, and it is not returned/forwarded. // If a cached document has this extension set (ie, is invalidated), @@ -143,6 +144,7 @@ int HTTP_LEN_PROXY_REVALIDATE; int HTTP_LEN_PUBLIC; int HTTP_LEN_S_MAXAGE; int HTTP_LEN_NEED_REVALIDATE_ONCE; +int HTTP_LEN_100_CONTINUE; Arena* const HTTPHdr::USE_HDR_HEAP_MAGIC = reinterpret_cast<Arena*>(1); @@ -257,6 +259,7 @@ http_init() HTTP_VALUE_PUBLIC = hdrtoken_string_to_wks("public"); HTTP_VALUE_S_MAXAGE = hdrtoken_string_to_wks("s-maxage"); HTTP_VALUE_NEED_REVALIDATE_ONCE = hdrtoken_string_to_wks("need-revalidate-once"); + HTTP_VALUE_100_CONTINUE = hdrtoken_string_to_wks("100-continue"); HTTP_LEN_BYTES = hdrtoken_wks_to_length(HTTP_VALUE_BYTES); HTTP_LEN_CHUNKED = hdrtoken_wks_to_length(HTTP_VALUE_CHUNKED); @@ -280,6 +283,7 @@ http_init() HTTP_LEN_PUBLIC = hdrtoken_wks_to_length(HTTP_VALUE_PUBLIC); HTTP_LEN_S_MAXAGE = hdrtoken_wks_to_length(HTTP_VALUE_S_MAXAGE); HTTP_LEN_NEED_REVALIDATE_ONCE = hdrtoken_wks_to_length(HTTP_VALUE_NEED_REVALIDATE_ONCE); + HTTP_LEN_100_CONTINUE = hdrtoken_wks_to_length(HTTP_VALUE_100_CONTINUE); // TODO: We need to look into enable these CC values as WKS XXX #if 0 http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/hdrs/HTTP.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h index cddd2fe..d5c8bd6 100644 --- a/proxy/hdrs/HTTP.h +++ b/proxy/hdrs/HTTP.h @@ -403,6 +403,7 @@ extern const char *HTTP_VALUE_PROXY_REVALIDATE; extern const char *HTTP_VALUE_PUBLIC; extern const char *HTTP_VALUE_S_MAXAGE; extern const char *HTTP_VALUE_NEED_REVALIDATE_ONCE; +extern const char *HTTP_VALUE_100_CONTINUE; extern int HTTP_LEN_BYTES; extern int HTTP_LEN_CHUNKED; @@ -426,6 +427,7 @@ extern int HTTP_LEN_PROXY_REVALIDATE; extern int HTTP_LEN_PUBLIC; extern int HTTP_LEN_S_MAXAGE; extern int HTTP_LEN_NEED_REVALIDATE_ONCE; +extern int HTTP_LEN_100_CONTINUE; /* Private */ void http_hdr_adjust(HTTPHdrImpl *hdrp, int32_t offset, int32_t length, int32_t delta); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/hdrs/HdrToken.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HdrToken.cc b/proxy/hdrs/HdrToken.cc index 2a2909a..dbb15ba 100644 --- a/proxy/hdrs/HdrToken.cc +++ b/proxy/hdrs/HdrToken.cc @@ -188,7 +188,8 @@ static const char *_hdrtoken_strs[] = { "X-ID", "X-Forwarded-For", "TE", - "Strict-Transport-Security" + "Strict-Transport-Security", + "100-continue" }; static HdrTokenTypeBinding _hdrtoken_strs_type_initializers[] = { @@ -527,7 +528,8 @@ static const char *_hdrtoken_commonly_tokenized_strs[] = { "X-ID", "X-Forwarded-For", "TE", - "Strict-Transport-Security" + "Strict-Transport-Security", + "100-continue" }; /*------------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpConfig.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index 8ea140d..50feaf3 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -1423,6 +1423,8 @@ HttpConfig::startup() HttpEstablishStaticConfigByte(c.ignore_accept_encoding_mismatch, "proxy.config.http.cache.ignore_accept_encoding_mismatch"); HttpEstablishStaticConfigByte(c.ignore_accept_charset_mismatch, "proxy.config.http.cache.ignore_accept_charset_mismatch"); + HttpEstablishStaticConfigByte(c.send_100_continue_response, "proxy.config.http.send_100_continue_response"); + HttpEstablishStaticConfigByte(c.oride.cache_when_to_revalidate, "proxy.config.http.cache.when_to_revalidate"); HttpEstablishStaticConfigByte(c.cache_when_to_add_no_cache_to_msie_requests, "proxy.config.http.cache.when_to_add_no_cache_to_msie_requests"); @@ -1673,6 +1675,8 @@ HttpConfig::reconfigure() params->ignore_accept_encoding_mismatch = m_master.ignore_accept_encoding_mismatch; params->ignore_accept_charset_mismatch = m_master.ignore_accept_charset_mismatch; + params->send_100_continue_response = INT_TO_BOOL(m_master.send_100_continue_response); + params->oride.cache_when_to_revalidate = m_master.oride.cache_when_to_revalidate; params->cache_when_to_add_no_cache_to_msie_requests = m_master.cache_when_to_add_no_cache_to_msie_requests; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpConfig.h ---------------------------------------------------------------------- diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h index cf3c946..c4e92dd 100644 --- a/proxy/http/HttpConfig.h +++ b/proxy/http/HttpConfig.h @@ -792,6 +792,8 @@ public: MgmtByte ignore_accept_encoding_mismatch; MgmtByte ignore_accept_charset_mismatch; + MgmtByte send_100_continue_response; + OverridableHttpConfigParams oride; private: @@ -939,7 +941,8 @@ HttpConfigParams::HttpConfigParams() ignore_accept_mismatch(0), ignore_accept_language_mismatch(0), ignore_accept_encoding_mismatch(0), - ignore_accept_charset_mismatch(0) + ignore_accept_charset_mismatch(0), + send_100_continue_response(0) { } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpSM.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 10a81eb..c967148 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -91,6 +91,9 @@ static int scat_count = 0; static const int sub_header_size = sizeof("Content-type: ") - 1 + 2 + sizeof("Content-range: bytes ") - 1 + 4; static const int boundary_size = 2 + sizeof("RANGE_SEPARATOR") - 1 + 2; +static const char *str_100_continue_response = "HTTP/1.1 100 Continue\r\n\r\n"; +static const int len_100_continue_response = strlen(str_100_continue_response); + /** * Takes two milestones and returns the difference. * @param start The start time @@ -1886,6 +1889,21 @@ HttpSM::state_send_server_request_header(int event, void *data) if (post_transform_info.vc) { setup_transform_to_server_transfer(); } else { + if (t_state.http_config_param->send_100_continue_response) { + int len = 0; + const char *expect = t_state.hdr_info.client_request.value_get(MIME_FIELD_EXPECT, MIME_LEN_EXPECT, &len); + // When receive an "Expect: 100-continue" request from client, ATS sends a "100 Continue" response to client + // imediately, before receive the real response from original server. + if ((len == HTTP_LEN_100_CONTINUE) && (strncasecmp(expect, HTTP_VALUE_100_CONTINUE, HTTP_LEN_100_CONTINUE) == 0)) { + int64_t alloc_index = buffer_size_to_index(len_100_continue_response); + ua_entry->write_buffer = new_MIOBuffer(alloc_index); + IOBufferReader *buf_start = ua_entry->write_buffer->alloc_reader(); + + DebugSM("http_seq", "send 100 Continue response to client"); + int64_t nbytes = ua_entry->write_buffer->write(str_100_continue_response, len_100_continue_response); + ua_session->do_io_write(ua_session->get_netvc(), nbytes, buf_start); + } + } do_setup_post_tunnel(HTTP_SERVER_VC); } } else { @@ -3265,6 +3283,14 @@ HttpSM::tunnel_handler_post_ua(int event, HttpTunnelProducer * p) case VC_EVENT_READ_COMPLETE: case HTTP_TUNNEL_EVENT_PRECOMPLETE: + // We have completed reading POST data from client here. + // It's time to free MIOBuffer of 100 Continue's response now, + // althought this is a little late. + if (t_state.http_config_param->send_100_continue_response) { + free_MIOBuffer(ua_entry->write_buffer); + ua_entry->write_buffer = NULL; + } + // Completed successfully if (t_state.txn_conf->keep_alive_post_out == 0) { // don't share the session if keep-alive for post is not on http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpTransact.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index db3aae0..f6db127 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -7884,6 +7884,11 @@ HttpTransact::build_request(State* s, HTTPHdr* base_request, HTTPHdr* outgoing_r } } + if (s->http_config_param->send_100_continue_response) { + HttpTransactHeaders::remove_100_continue_headers(s, outgoing_request); + DebugTxn("http_trans", "[build_request] request expect 100-continue headers removed"); + } + s->request_sent_time = ink_cluster_time(); s->current.now = s->request_sent_time; // The assert is backwards in this case because request is being (re)sent. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpTransactHeaders.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransactHeaders.cc b/proxy/http/HttpTransactHeaders.cc index 4574c21..9be81d0 100644 --- a/proxy/http/HttpTransactHeaders.cc +++ b/proxy/http/HttpTransactHeaders.cc @@ -1007,6 +1007,18 @@ HttpTransactHeaders::remove_conditional_headers(HTTPHdr *outgoing) // TODO: how about RANGE and IF_RANGE? } +void +HttpTransactHeaders::remove_100_continue_headers(HttpTransact::State *s, HTTPHdr *outgoing) +{ + int len = 0; + const char *expect = s->hdr_info.client_request.value_get(MIME_FIELD_EXPECT, MIME_LEN_EXPECT, &len); + + if ((len == HTTP_LEN_100_CONTINUE) && (strncasecmp(expect, HTTP_VALUE_100_CONTINUE, HTTP_LEN_100_CONTINUE) == 0)) { + outgoing->field_delete(MIME_FIELD_EXPECT, MIME_LEN_EXPECT); + } +} + + //////////////////////////////////////////////////////////////////////// // Deal with lame-o servers by removing the host name from the url. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e5da353c/proxy/http/HttpTransactHeaders.h ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransactHeaders.h b/proxy/http/HttpTransactHeaders.h index 0fa3a03..cc6f475 100644 --- a/proxy/http/HttpTransactHeaders.h +++ b/proxy/http/HttpTransactHeaders.h @@ -79,6 +79,7 @@ public: static void insert_basic_realm_in_proxy_authenticate(const char *realm, HTTPHdr * header, bool bRevPrxy); static void remove_conditional_headers(HTTPHdr * outgoing); + static void remove_100_continue_headers(HttpTransact::State *s, HTTPHdr * outgoing); static void remove_host_name_from_url(HTTPHdr * outgoing_request); static void add_global_user_agent_header_to_request(HttpConfigParams *http_config_param, HTTPHdr * header); static void add_server_header_to_response(OverridableHttpConfigParams *http_txn_conf, HTTPHdr * header);
