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'