trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zw...@apache.org
Subject [trafficserver] 03/08: Add 100-continue expectation support on H2 connection
Date Tue, 10 Dec 2019 23:21:32 GMT
This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 14ebf508edd69ef6c25b81041c3b0ab0a5a16406
Author: Masaori Koshiba <masaori@apache.org>
AuthorDate: Wed Nov 20 14:05:54 2019 +0900

    Add 100-continue expectation support on H2 connection
    
    (cherry picked from commit c0fe598af5ad41a73c44d8f10fc5bae6baa555f7)
---
 proxy/hdrs/HTTP.h                              | 23 +++++++++++++++++++++--
 proxy/http2/Http2Stream.cc                     | 11 +++++++++++
 tests/gold_tests/h2/gold/httpbin_0_stdout.gold |  9 ++-------
 tests/gold_tests/h2/gold/httpbin_3_stderr.gold |  9 +++++++++
 tests/gold_tests/h2/gold/httpbin_3_stdout.gold |  7 +++++++
 tests/gold_tests/h2/gold/httpbin_access.gold   |  1 +
 tests/gold_tests/h2/httpbin.test.py            | 19 +++++++++++++++++--
 7 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index 30fcf6c..c7c43e1 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -623,7 +623,7 @@ public:
   /// header internals, they must be able to do this.
   void mark_target_dirty() const;
 
-  HTTPStatus status_get();
+  HTTPStatus status_get() const;
   void status_set(HTTPStatus status);
 
   const char *reason_get(int *length);
@@ -642,6 +642,7 @@ public:
   bool is_cache_control_set(const char *cc_directive_wks);
   bool is_pragma_no_cache_set();
   bool is_keep_alive_set() const;
+  bool expect_final_response() const;
   HTTPKeepAlive keep_alive_get() const;
 
 protected:
@@ -1001,6 +1002,24 @@ HTTPHdr::is_keep_alive_set() const
   return this->keep_alive_get() == HTTP_KEEPALIVE;
 }
 
+/**
+   Check the status code is informational and expecting final response
+   - e.g. "100 Continue", "103 Early Hints"
+
+   Please note that "101 Switching Protocol" is not included.
+ */
+inline bool
+HTTPHdr::expect_final_response() const
+{
+  switch (this->status_get()) {
+  case HTTP_STATUS_CONTINUE:
+  case HTTP_STATUS_EARLY_HINTS:
+    return true;
+  default:
+    return false;
+  }
+}
+
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
@@ -1151,7 +1170,7 @@ http_hdr_status_get(HTTPHdrImpl *hh)
   -------------------------------------------------------------------------*/
 
 inline HTTPStatus
-HTTPHdr::status_get()
+HTTPHdr::status_get() const
 {
   ink_assert(valid());
 
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index eb98c4c..8da3d86 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -639,6 +639,17 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t
write_len,
         h2_proxy_ssn->connection_state.send_headers_frame(this);
       }
 
+      // Roll back states of response header to read final response
+      if (this->response_header.expect_final_response()) {
+        this->response_header_done = false;
+        response_header.destroy();
+        response_header.create(HTTP_TYPE_RESPONSE);
+        http_parser_clear(&http_parser);
+        http_parser_init(&http_parser);
+      }
+
+      this->signal_write_event(call_update);
+
       if (this->response_reader->is_read_avail_more_than(0)) {
         this->_milestones.mark(Http2StreamMilestone::START_TX_DATA_FRAMES);
         this->send_response_body(call_update);
diff --git a/tests/gold_tests/h2/gold/httpbin_0_stdout.gold b/tests/gold_tests/h2/gold/httpbin_0_stdout.gold
index c46139d..d8e6107 100644
--- a/tests/gold_tests/h2/gold/httpbin_0_stdout.gold
+++ b/tests/gold_tests/h2/gold/httpbin_0_stdout.gold
@@ -1,10 +1,5 @@
 {
-  "args": {}, ``
-  "headers": {
-    "Accept": "*/*", ``
-    "Host": ``
-    "User-Agent": "curl/``
-  }, ``
-  "origin": ``
+  ``
   "url": "http://``/get"
+  ``
 }
diff --git a/tests/gold_tests/h2/gold/httpbin_3_stderr.gold b/tests/gold_tests/h2/gold/httpbin_3_stderr.gold
new file mode 100644
index 0000000..8109f9d
--- /dev/null
+++ b/tests/gold_tests/h2/gold/httpbin_3_stderr.gold
@@ -0,0 +1,9 @@
+``
+> POST /post HTTP/2
+``
+> Expect: 100-continue
+``
+< HTTP/2 100``
+``
+< HTTP/2 200``
+``
diff --git a/tests/gold_tests/h2/gold/httpbin_3_stdout.gold b/tests/gold_tests/h2/gold/httpbin_3_stdout.gold
new file mode 100644
index 0000000..6105808
--- /dev/null
+++ b/tests/gold_tests/h2/gold/httpbin_3_stdout.gold
@@ -0,0 +1,7 @@
+{
+  ``
+  "form": {
+    "key": "value"
+  },
+  ``
+}
diff --git a/tests/gold_tests/h2/gold/httpbin_access.gold b/tests/gold_tests/h2/gold/httpbin_access.gold
index 3f77947..d409c47 100644
--- a/tests/gold_tests/h2/gold/httpbin_access.gold
+++ b/tests/gold_tests/h2/gold/httpbin_access.gold
@@ -1,3 +1,4 @@
 [``] GET http://127.0.0.1:``/get HTTP/1.1 http/2 `` `` TCP_MISS 200 ``
 [``] GET http://127.0.0.1:``/bytes/0 HTTP/1.1 http/2 `` `` TCP_MISS 200 0
 [``] GET http://127.0.0.1:``/stream-bytes/102400?seed=0 HTTP/1.1 http/2 `` `` TCP_MISS 200
102400
+``
diff --git a/tests/gold_tests/h2/httpbin.test.py b/tests/gold_tests/h2/httpbin.test.py
index d31247c..d77fcc2 100644
--- a/tests/gold_tests/h2/httpbin.test.py
+++ b/tests/gold_tests/h2/httpbin.test.py
@@ -78,14 +78,19 @@ logging:
 
 Test.Disk.File(os.path.join(ts.Variables.LOGDIR, 'access.log'), exists=True, content='gold/httpbin_access.gold')
 
+# TODO: when httpbin 0.8.0 or later is released, remove below json pretty print hack
+json_printer = '''
+python -c "import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))"
+'''
+
 # ----
 # Test Cases
 # ----
 
 # Test Case 0: Basic request and resposne
 test_run = Test.AddTestRun()
-# TODO: when httpbin 0.8.0 or later is released, remove below json pretty print hack
-test_run.Processes.Default.Command = "curl -vs -k --http2 https://127.0.0.1:{0}/get | python
-c 'import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))".format(ts.Variables.ssl_port)
+test_run.Processes.Default.Command = "curl -vs -k --http2 https://127.0.0.1:{0}/get | {1}".format(
+    ts.Variables.ssl_port, json_printer)
 test_run.Processes.Default.ReturnCode = 0
 test_run.Processes.Default.StartBefore(httpbin, ready=When.PortOpen(httpbin.Variables.Port))
 test_run.Processes.Default.StartBefore(Test.Processes.ts)
@@ -110,6 +115,16 @@ test_run.Processes.Default.Streams.stdout = "gold/httpbin_2_stdout.gold"
 test_run.Processes.Default.Streams.stderr = "gold/httpbin_2_stderr.gold"
 test_run.StillRunningAfter = httpbin
 
+# Test Case 3: Expect 100-Continue
+test_run = Test.AddTestRun()
+test_run.Processes.Default.Command = "curl -vs -k --http2 https://127.0.0.1:{0}/post --data
'key=value' -H 'Expect: 100-continue' --expect100-timeout 1 --max-time 5 | {1}".format(
+    ts.Variables.ssl_port, json_printer)
+test_run.Processes.Default.ReturnCode = 0
+test_run.Processes.Default.Streams.stdout = "gold/httpbin_3_stdout.gold"
+test_run.Processes.Default.Streams.stderr = "gold/httpbin_3_stderr.gold"
+test_run.StillRunningAfter = httpbin
+
+
 # Check Logging
 test_run = Test.AddTestRun()
 test_run.DelayStart = 10


Mime
View raw message