You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by dr...@apache.org on 2018/04/05 15:25:35 UTC

[trafficserver] branch master updated: Fix post process to propagate early server response.

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

dragon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new cafd146  Fix post process to propagate early server response.
cafd146 is described below

commit cafd146a56f09bc565ec4adf0308c7625e665a67
Author: Susan Hinrichs <sh...@apache.org>
AuthorDate: Mon Mar 26 17:11:31 2018 -0500

    Fix post process to propagate early server response.
    
    Setup server read response in parallel with the post tunnel so
    early server response headers are used and not replaced with
    an ATS connection response.  Added a test to check this case.
---
 proxy/http/HttpSM.cc                             |  8 +-
 tests/gold_tests/post_error/create_post_body.py  | 24 ++++++
 tests/gold_tests/post_error/gold/post_error.gold |  3 +
 tests/gold_tests/post_error/post_error.test.py   | 69 +++++++++++++++++
 tests/gold_tests/post_error/post_server.c        | 96 ++++++++++++++++++++++++
 5 files changed, 198 insertions(+), 2 deletions(-)

diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 347bb64..2dfbba7 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -1986,6 +1986,8 @@ HttpSM::state_send_server_request_header(int event, void *data)
         setup_transform_to_server_transfer();
       } else {
         do_setup_post_tunnel(HTTP_SERVER_VC);
+        // Start up read response in parallel in case of early error response
+        setup_server_read_response_header();
       }
     } else {
       // It's time to start reading the response
@@ -2718,7 +2720,7 @@ HttpSM::tunnel_handler_post(int event, void *data)
       call_transact_and_set_next_state(HttpTransact::HandleRequestBufferDone);
       break;
     }
-    setup_server_read_response_header();
+    // Read reasponse already setup
     break;
   default:
     ink_release_assert(0);
@@ -5330,7 +5332,7 @@ HttpSM::handle_post_failure()
     tunnel.deallocate_buffers();
     tunnel.reset();
     // There's data from the server so try to read the header
-    setup_server_read_response_header();
+    // Read response is already set up
   } else {
     tunnel.deallocate_buffers();
     tunnel.reset();
@@ -5385,6 +5387,8 @@ HttpSM::handle_http_server_open()
       (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING) &&
       do_post_transform_open()) {
     do_setup_post_tunnel(HTTP_TRANSFORM_VC);
+    // Start up read response in parallel in case of early error response
+    setup_server_read_response_header();
   } else {
     setup_server_send_request_api();
   }
diff --git a/tests/gold_tests/post_error/create_post_body.py b/tests/gold_tests/post_error/create_post_body.py
new file mode 100644
index 0000000..1c3c971
--- /dev/null
+++ b/tests/gold_tests/post_error/create_post_body.py
@@ -0,0 +1,24 @@
+'''
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+post_body = str(123456).zfill(1024)
+postfile = open("postbody", "w")
+for x in range(0, 3000):
+    postfile.write(post_body)
+postfile.close()
+
diff --git a/tests/gold_tests/post_error/gold/post_error.gold b/tests/gold_tests/post_error/gold/post_error.gold
new file mode 100644
index 0000000..e071159
--- /dev/null
+++ b/tests/gold_tests/post_error/gold/post_error.gold
@@ -0,0 +1,3 @@
+``
+< HTTP/1.1 401 Auth Needed
+``
diff --git a/tests/gold_tests/post_error/post_error.test.py b/tests/gold_tests/post_error/post_error.test.py
new file mode 100644
index 0000000..26f1055
--- /dev/null
+++ b/tests/gold_tests/post_error/post_error.test.py
@@ -0,0 +1,69 @@
+'''
+'''
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import os
+Test.Summary = '''
+Test post_error
+'''
+
+# need Curl
+Test.SkipUnless(
+    Condition.HasProgram("curl", "Curl need to be installed on system for this test to work")
+)
+Test.ContinueOnFail = True
+
+# build post server code
+tr=Test.Build(target='post_server',sources=['post_server.c'])
+tr.Setup.Copy('post_server.c')
+
+tr = Test.AddTestRun()
+tr.Setup.Copy('create_post_body.py')
+tr.Processes.Default.Command = "python create_post_body.py"
+
+# Define default ATS
+ts = Test.MakeATSProcess("ts", select_ports=False)
+
+# create Process
+server = Test.Processes.Process("post_server")
+port = 8888
+command = "./post_server {0}".format(port)
+
+# create process
+server.Command = command
+server.Ready = When.PortOpen(port)
+server.ReturnCode = Any(None, 0)
+
+ts.Disk.remap_config.AddLine(
+    'map / http://127.0.0.1:{0}'.format(port)
+)
+
+ts.Disk.records_config.update({
+    # enable ssl port
+    'proxy.config.http.server_ports': '{0}'.format(ts.Variables.port)
+})
+
+
+
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = 'curl -H"Expect:" -v -k -d "@postbody" http://127.0.0.1:{0}/'.format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.All = "gold/post_error.gold"
+tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.port))
+tr.Processes.Default.StartBefore(server)
+tr.StillRunningAfter = server
+
diff --git a/tests/gold_tests/post_error/post_server.c b/tests/gold_tests/post_error/post_server.c
new file mode 100644
index 0000000..bff4889
--- /dev/null
+++ b/tests/gold_tests/post_error/post_server.c
@@ -0,0 +1,96 @@
+/** @file
+
+  POST test server
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+const char *response_buffer = "HTTP/1.1 401 Auth Needed\r\nHost:example.com\r\nContent-length:0\r\n\r\n";
+int
+main(int argc, char *argv[])
+{
+  if (argc < 2) {
+    fprintf(stderr, "USAGE: %s <listen port>\n", argv[0]);
+    exit(1);
+  }
+  printf("Starting...\n");
+
+  int listenfd = socket(AF_INET, SOCK_STREAM, 0);
+  struct sockaddr_in serv_addr, peer_addr;
+  socklen_t peer_len;
+
+  serv_addr.sin_family      = AF_INET;
+  serv_addr.sin_addr.s_addr = INADDR_ANY;
+  int port                  = atoi(argv[1]);
+  serv_addr.sin_port        = htons(port);
+  bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+  listen(listenfd, 10);
+
+  for (;;) {
+    socklen_t client_len;
+    struct sockaddr_in client;
+    int client_sock = accept(listenfd, reinterpret_cast<struct sockaddr *>(&client), &client_len);
+    if (client_sock < 0) {
+      perror("Accept failed");
+      exit(1);
+    }
+
+    printf("client_sock=%d\n", client_sock);
+
+    // Read data until we get a full header (Seen \r\n\r\n)
+    // Being simple minded and assume they all show up in a single read
+    char buffer[1024];
+    bool done_header_read = false;
+    do {
+      int count = read(client_sock, buffer, sizeof(buffer));
+      if (count <= 0) {
+        // Client bailed out on us
+        perror("Client read failed");
+        close(client_sock);
+        client_sock      = -1;
+        done_header_read = false;
+      }
+      // Not super efficient, but don't care for this test application
+      for (int i = 0; i < count - 3 && !done_header_read; i++) {
+        if (memcmp(buffer + i, "\r\n\r\n", 4) == 0) {
+          done_header_read = true;
+        }
+      }
+    } while (!done_header_read);
+
+    // Send back a fixed response header
+    write(client_sock, response_buffer, strlen(response_buffer));
+
+    // Close
+    close(client_sock);
+    printf("Sent response\n");
+  }
+  printf("Finishing\n");
+
+  exit(0);
+}

-- 
To stop receiving notification emails like this one, please contact
dragon@apache.org.