This is an automated email from the ASF dual-hosted git repository.

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

commit 8754223ceeb6db022230398bd10dcf2ccc0f9546
Author: Masaori Koshiba <[email protected]>
AuthorDate: Wed Nov 20 14:05:54 2019 +0900

    Add 100-continue expectation support on H2 connection
    
    (cherry picked from commit c0fe598af5ad41a73c44d8f10fc5bae6baa555f7)
    
    Conflicts:
        tests/gold_tests/h2/gold/httpbin_0_stdout.gold
        tests/gold_tests/h2/httpbin.test.py
---
 proxy/hdrs/HTTP.h                              | 23 +++++++++++++++++++++--
 proxy/http2/Http2Stream.cc                     | 11 +++++++++++
 tests/gold_tests/h2/gold/httpbin_0_stdout.gold |  2 +-
 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            | 18 +++++++++++++++++-
 7 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index 7d91765..6867d37 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -618,7 +618,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);
@@ -635,6 +635,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:
@@ -1004,6 +1005,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;
+  }
+}
+
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
@@ -1154,7 +1173,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 6b33d3d..1a2c242 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -630,6 +630,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 cb7b2d6..d8e6107 100644
--- a/tests/gold_tests/h2/gold/httpbin_0_stdout.gold
+++ b/tests/gold_tests/h2/gold/httpbin_0_stdout.gold
@@ -1,5 +1,5 @@
 {
   ``
-  "url":"http://``/get";
+  "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 f30eea4..851eee2 100644
--- a/tests/gold_tests/h2/httpbin.test.py
+++ b/tests/gold_tests/h2/httpbin.test.py
@@ -78,13 +78,19 @@ logs:
 
 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()
-test_run.Processes.Default.Command = 'curl -vs -k --http2 
https://127.0.0.1:{0}/get'.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, 
ready=When.PortOpen(ts.Variables.ssl_port))
@@ -109,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

Reply via email to