You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2014/05/22 01:20:32 UTC

git commit: TS-1125: POST's with Expect: 100-continue are slowed by delayed 100 response

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 <ff...@yahoo-inc.com>
Authored: Wed May 21 16:19:49 2014 -0700
Committer: Bryan Call <bc...@apache.org>
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);