diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index ae209fccb60..4dd9df30beb 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -849,6 +849,7 @@ HttpTransact::BadRequest(State *s)
}
build_error_response(s, status, reason, body_factory_template);
+ s->client_info.keep_alive = HTTP_NO_KEEPALIVE;
TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, nullptr);
}
@@ -8071,6 +8072,9 @@ HttpTransact::build_error_response(State *s, HTTPStatus status_code, const char
retry_after = ret_tmp;
}
s->congestion_control_crat = retry_after;
+ } else if (status_code == HTTP_STATUS_BAD_REQUEST) {
+ // Close the client connection after a malformed request
+ s->client_info.keep_alive = HTTP_NO_KEEPALIVE;
}
// Add a bunch of headers to make sure that caches between
diff --git a/tests/gold_tests/headers/gold/bad_good_request.gold b/tests/gold_tests/headers/gold/bad_good_request.gold
new file mode 100644
index 00000000000..217afe03aea
--- /dev/null
+++ b/tests/gold_tests/headers/gold/bad_good_request.gold
@@ -0,0 +1,23 @@
+HTTP/1.1 400 Invalid HTTP Request
+Date: ``
+Connection: close
+Server: ATS/``
+Cache-Control: no-store
+Content-Type: text/html
+Content-Language: en
+Content-Length: 219
+
+
+
+Bad Request
+
+
+
+Bad Request
+
+
+
+Description: Could not process this request.
+
+
+
diff --git a/tests/gold_tests/headers/gold/bad_protocol_number.gold b/tests/gold_tests/headers/gold/bad_protocol_number.gold
new file mode 100644
index 00000000000..6f16cc17029
--- /dev/null
+++ b/tests/gold_tests/headers/gold/bad_protocol_number.gold
@@ -0,0 +1,22 @@
+HTTP/1.1 505 Unsupported HTTP Version
+Date: ``
+Server: ATS/``
+Cache-Control: no-store
+Content-Type: text/html
+Content-Language: en
+Content-Length: 219
+
+
+
+Bad Request
+
+
+
+Bad Request
+
+
+
+Description: Could not process this request.
+
+
+
diff --git a/tests/gold_tests/headers/gold/bad_te_value.gold b/tests/gold_tests/headers/gold/bad_te_value.gold
new file mode 100644
index 00000000000..7fae2c54bc4
--- /dev/null
+++ b/tests/gold_tests/headers/gold/bad_te_value.gold
@@ -0,0 +1,25 @@
+HTTP/1.1 501 Field not implemented
+Date: ``
+Connection: keep-alive
+Server: ATS/``
+Cache-Control: no-store
+Content-Type: text/html
+Content-Language: en
+Content-Length: 289
+
+
+
+Transcoding Not Available
+
+
+
+Transcoding Not Available
+
+
+
+
+ Description: Unable to provide the document in the
+format requested by your browser.
+
+
+
diff --git a/tests/gold_tests/headers/good_request_after_bad.test.py b/tests/gold_tests/headers/good_request_after_bad.test.py
new file mode 100644
index 00000000000..c5cbf10c37d
--- /dev/null
+++ b/tests/gold_tests/headers/good_request_after_bad.test.py
@@ -0,0 +1,66 @@
+'''
+Verify that request following a ill-formed request is not processed
+'''
+# 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 = '''
+Verify that request following a ill-formed request is not processed
+'''
+ts = Test.MakeATSProcess("ts", enable_cache=True)
+
+ts.Disk.records_config.update({'proxy.config.diags.debug.tags': 'http',
+ 'proxy.config.diags.debug.enabled': 0,
+ })
+
+server = Test.MakeOriginServer("server")
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
+response_header = {
+ "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nLast-Modified: Tue, 08 May 2018 15:49:41 GMT\r\nCache-Control: max-age=1000\r\n\r\n",
+ "timestamp": "1469733493.993",
+ "body": "xxx"}
+server.addResponse("sessionlog.json", request_header, response_header)
+
+ts.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0}'.format(server.Variables.Port)
+)
+
+# Make a good request to get item in the cache for later tests
+tr = Test.AddTestRun("Good control")
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.Command = 'printf "GET / HTTP/1.1\r\nHost: bob\r\n\r\n" | nc 127.0.0.1 {}'.format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+
+tr = Test.AddTestRun("space after header name")
+tr.Processes.Default.Command = 'printf "GET / HTTP/1.1\r\nHost : bob\r\n\r\nGET / HTTP/1.1\r\nHost: boa\r\n\r\n" | nc 127.0.0.1 {}'.format(
+ ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stdout = 'gold/bad_good_request.gold'
+
+tr = Test.AddTestRun("Bad protocol number")
+tr.Processes.Default.Command = 'printf "GET / HTTP/11.1\r\nhost: bob\r\n\r\nGET / HTTP/1.1\r\nHost: boa\r\n\r\n" | nc 127.0.0.1 {}'.format(
+ ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stdout = 'gold/bad_protocol_number.gold'
+
+tr = Test.AddTestRun("Unsupported Transfer Encoding value")
+tr.Processes.Default.Command = 'printf "GET / HTTP/1.1\r\nhost: bob\r\ntransfer-encoding: random\r\n\r\nGET / HTTP/1.1\r\nHost: boa\r\n\r\n" | nc 127.0.0.1 {}'.format(
+ ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stdout = 'gold/bad_te_value.gold'