You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by su...@apache.org on 2019/07/31 23:36:49 UTC

[trafficserver] branch master updated: Add soft limit for HTTP Request URI and Header field length. Add a default body_factory template when rejecting a request that's too long

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

sudheerv 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 9772eb6  Add soft limit for HTTP Request URI and Header field length. Add a default body_factory template when rejecting a request that's too long
9772eb6 is described below

commit 9772eb68b143ed74d1604ec90fa3714a283c4148
Author: Sudheer Vinukonda <su...@apache.org>
AuthorDate: Fri Jul 26 14:43:43 2019 -0700

    Add soft limit for HTTP Request URI and Header field length.
    Add a default body_factory template when rejecting a request that's too long
    
    Add the soft limit check for MIME header field name as well
    And some code cleanup
    
    Fix the default error response body
    
    Fix build failure
    
    Add unit tests
    
    Add docs for the new settings
    
    Adjust the header field size control to include header name and value,
    to better align with the RFC definition
    
    Fix build error
    
    Simplify the header field size check inline with the config setting
    
    Fix the condition to match the docs accurately
    
    Fix the condition to match the docs accurately
    
    add new body_factory template to Makefile.am
    
    Fix format typo in Makefile
    
    dummy commit to trigger build which still seems to pick old file
    
    Yet another dummy commit to trigger build
    
    Address more review comments
---
 configs/body_factory/default/Makefile.am           |  3 +-
 .../body_factory/default/request#uri_len_too_long  | 15 ++++++
 doc/admin-guide/files/records.config.en.rst        | 14 ++++++
 doc/admin-guide/monitoring/error-messages.en.rst   |  7 +++
 mgmt/RecordsConfig.cc                              |  4 ++
 proxy/hdrs/HTTP.cc                                 | 19 +++++---
 proxy/hdrs/HTTP.h                                  | 15 ++++--
 proxy/hdrs/HdrTSOnly.cc                            |  6 ++-
 proxy/hdrs/HdrTest.cc                              | 54 ++++++++++++++++++++++
 proxy/hdrs/HdrTest.h                               |  1 +
 proxy/hdrs/MIME.cc                                 |  6 +--
 proxy/hdrs/MIME.h                                  |  9 ++--
 proxy/http/HttpConfig.cc                           |  6 +++
 proxy/http/HttpConfig.h                            |  3 ++
 proxy/http/HttpSM.cc                               |  9 +++-
 proxy/http/HttpTransact.cc                         | 17 ++++++-
 16 files changed, 164 insertions(+), 24 deletions(-)

diff --git a/configs/body_factory/default/Makefile.am b/configs/body_factory/default/Makefile.am
index 307284b..953037c 100644
--- a/configs/body_factory/default/Makefile.am
+++ b/configs/body_factory/default/Makefile.am
@@ -44,5 +44,6 @@ dist_bodyfactory_DATA = \
 	timeout\#activity \
 	timeout\#inactivity \
 	transcoding\#unsupported \
-	urlrouting\#no_mapping
+	urlrouting\#no_mapping \
+        request\#uri_len_too_long
 
diff --git a/configs/body_factory/default/request#uri_len_too_long b/configs/body_factory/default/request#uri_len_too_long
new file mode 100644
index 0000000..1b83c42
--- /dev/null
+++ b/configs/body_factory/default/request#uri_len_too_long
@@ -0,0 +1,15 @@
+<HTML>
+<HEAD>
+<TITLE>URI Too Long</TITLE>
+</HEAD>
+
+<BODY BGCOLOR="white" FGCOLOR="black">
+<H1>URI Too Long</H1>
+<HR>
+
+<FONT FACE="Helvetica,Arial"><B>
+Description: Could not process this request because
+the request uri was longer than proxy.config.http.request_line_max_size
+</B></FONT>
+<HR>
+</BODY>
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 394d733..243d03a 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -1097,6 +1097,20 @@ mptcp
    This enables buffering the content for incoming ``POST`` requests. If enabled no outbound
    connection is made until the entire ``POST`` request has been buffered.
 
+.. ts:cv:: CONFIG proxy.config.http.request_line_max_size INT 65535
+
+   Controls the maximum size, in bytes, of an HTTP Request Line in requests. Requests
+   with a request line exceeding this size will be treated as invalid and
+   rejected by the proxy. Note that the HTTP request line typically includes HTTP method,
+   request target and HTTP version string except when the request is made using absolute
+   URI in which case the request line may also include the request scheme and domain name.
+
+.. ts:cv:: CONFIG proxy.config.http.header_field_max_size INT 131070
+
+   Controls the maximum size, in bytes, of an HTTP header field in requests. Headers
+   in a request with the sum of their name and value that exceed this size will cause the
+   entire request to be treated as invalid and rejected by the proxy.
+
 .. ts:cv:: CONFIG proxy.config.http.request_header_max_size INT 131072
 
    Controls the maximum size, in bytes, of an HTTP header in requests. Headers
diff --git a/doc/admin-guide/monitoring/error-messages.en.rst b/doc/admin-guide/monitoring/error-messages.en.rst
index 71cc2ba..407dd86 100644
--- a/doc/admin-guide/monitoring/error-messages.en.rst
+++ b/doc/admin-guide/monitoring/error-messages.en.rst
@@ -311,3 +311,10 @@ with corresponding HTTP response codes and customizable files.
    Cannot perform your request for the document ``URL`` because the
    protocol scheme is unknown.
    ``request#scheme_unsupported``
+
+``URI Too Long``
+   ``414``
+   Could not process this request because the request uri 
+   was too long ..
+   ``request#uri_len_too_long``
+
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index c52c800..3058a2a 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -540,6 +540,10 @@ static const RecordElement RecordsConfig[] =
   {RECT_CONFIG, "proxy.config.http.global_user_agent_header", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_STR, ".*", RECA_NULL}
   ,
 
+  {RECT_CONFIG, "proxy.config.http.request_line_max_size", RECD_INT, "65535", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+  {RECT_CONFIG, "proxy.config.http.header_field_max_size", RECD_INT, "131070", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
   //        ############
   //        # security #
   //        ############
diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc
index 6f86c80..e475284 100644
--- a/proxy/hdrs/HTTP.cc
+++ b/proxy/hdrs/HTTP.cc
@@ -876,7 +876,8 @@ http_parser_clear(HTTPParser *parser)
 
 ParseResult
 http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
-                      bool must_copy_strings, bool eof, bool strict_uri_parsing)
+                      bool must_copy_strings, bool eof, bool strict_uri_parsing, size_t max_request_line_size,
+                      size_t max_hdr_field_size)
 {
   if (parser->m_parsing_http) {
     MIMEScanner *scanner = &parser->m_mime_parser.m_scanner;
@@ -901,8 +902,8 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
   start:
     hh->m_polarity = HTTP_TYPE_REQUEST;
 
-    // Make sure the line is not longer than 64K
-    if (scanner->get_buffered_line_size() >= UINT16_MAX) {
+    // Make sure the line is not longer than max_request_line_size
+    if (scanner->get_buffered_line_size() > max_request_line_size) {
       return PARSE_RESULT_ERROR;
     }
 
@@ -925,6 +926,10 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
     line_start = cur = parsed.data();
     end              = parsed.data_end();
 
+    if ((unsigned)(end - line_start) > max_request_line_size) {
+      return PARSE_RESULT_ERROR;
+    }
+
     must_copy_strings = (must_copy_strings || (!line_is_real));
 
 #if (ENABLE_PARSER_FAST_PATHS)
@@ -966,7 +971,8 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
         return PARSE_RESULT_ERROR;
       }
 
-      ParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
+      ParseResult ret =
+        mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof, max_hdr_field_size);
       // If we're done with the main parse do some validation
       if (ret == PARSE_RESULT_DONE) {
         ret = validate_hdr_host(hh); // check HOST header
@@ -1121,7 +1127,8 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
     end                    = real_end;
     parser->m_parsing_http = false;
 
-    ParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
+    ParseResult ret =
+      mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof, max_hdr_field_size);
     // If we're done with the main parse do some validation
     if (ret == PARSE_RESULT_DONE) {
       ret = validate_hdr_host(hh); // check HOST header
@@ -1132,7 +1139,7 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
     return ret;
   }
 
-  return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
+  return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof, max_hdr_field_size);
 }
 
 ParseResult
diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h
index 9b8d3e5..30fcf6c 100644
--- a/proxy/hdrs/HTTP.h
+++ b/proxy/hdrs/HTTP.h
@@ -442,7 +442,8 @@ const char *http_hdr_reason_lookup(unsigned status);
 void http_parser_init(HTTPParser *parser);
 void http_parser_clear(HTTPParser *parser);
 ParseResult http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
-                                  bool must_copy_strings, bool eof, bool strict_uri_parsing);
+                                  bool must_copy_strings, bool eof, bool strict_uri_parsing, size_t max_request_line_size,
+                                  size_t max_hdr_field_size);
 ParseResult validate_hdr_host(HTTPHdrImpl *hh);
 ParseResult validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh);
 ParseResult http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
@@ -628,10 +629,12 @@ public:
   const char *reason_get(int *length);
   void reason_set(const char *value, int length);
 
-  ParseResult parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, bool strict_uri_parsing = false);
+  ParseResult parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, bool strict_uri_parsing = false,
+                        size_t max_request_line_size = UINT16_MAX, size_t max_hdr_field_size = 131070);
   ParseResult parse_resp(HTTPParser *parser, const char **start, const char *end, bool eof);
 
-  ParseResult parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, bool strict_uri_parsing = false);
+  ParseResult parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, bool strict_uri_parsing = false,
+                        size_t max_request_line_size = UINT16_MAX, size_t max_hdr_field_size = UINT16_MAX);
   ParseResult parse_resp(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof);
 
 public:
@@ -1200,12 +1203,14 @@ HTTPHdr::reason_set(const char *value, int length)
   -------------------------------------------------------------------------*/
 
 inline ParseResult
-HTTPHdr::parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, bool strict_uri_parsing)
+HTTPHdr::parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, bool strict_uri_parsing,
+                   size_t max_request_line_size, size_t max_hdr_field_size)
 {
   ink_assert(valid());
   ink_assert(m_http->m_polarity == HTTP_TYPE_REQUEST);
 
-  return http_parser_parse_req(parser, m_heap, m_http, start, end, true, eof, strict_uri_parsing);
+  return http_parser_parse_req(parser, m_heap, m_http, start, end, true, eof, strict_uri_parsing, max_request_line_size,
+                               max_hdr_field_size);
 }
 
 /*-------------------------------------------------------------------------
diff --git a/proxy/hdrs/HdrTSOnly.cc b/proxy/hdrs/HdrTSOnly.cc
index 55e2d93..3a7c40a 100644
--- a/proxy/hdrs/HdrTSOnly.cc
+++ b/proxy/hdrs/HdrTSOnly.cc
@@ -45,7 +45,8 @@
   -------------------------------------------------------------------------*/
 
 ParseResult
-HTTPHdr::parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, bool strict_uri_parsing)
+HTTPHdr::parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, bool strict_uri_parsing,
+                   size_t max_request_line_size, size_t max_hdr_field_size)
 {
   const char *start;
   const char *tmp;
@@ -71,7 +72,8 @@ HTTPHdr::parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool
     int heap_slot = m_heap->attach_block(r->get_current_block(), start);
 
     m_heap->lock_ronly_str_heap(heap_slot);
-    state = http_parser_parse_req(parser, m_heap, m_http, &tmp, end, false, eof, strict_uri_parsing);
+    state = http_parser_parse_req(parser, m_heap, m_http, &tmp, end, false, eof, strict_uri_parsing, max_request_line_size,
+                                  max_hdr_field_size);
     m_heap->set_ronly_str_heap_end(heap_slot, tmp);
     m_heap->unlock_ronly_str_heap(heap_slot);
 
diff --git a/proxy/hdrs/HdrTest.cc b/proxy/hdrs/HdrTest.cc
index 875e4e1..6fe2d87 100644
--- a/proxy/hdrs/HdrTest.cc
+++ b/proxy/hdrs/HdrTest.cc
@@ -645,6 +645,48 @@ HdrTest::test_http_aux(const char *request, const char *response)
   return (failures_to_status("test_http_aux", (status == 0)));
 }
 
+int
+HdrTest::test_http_req_parse_error(const char *request, const char *response)
+{
+  int err;
+  HTTPHdr req_hdr, rsp_hdr;
+  HTTPParser parser;
+  const char *start;
+  const char *end;
+
+  int status = 1;
+
+  /*** (1) parse the request string into req_hdr ***/
+
+  start = request;
+  end   = start + strlen(start); // 1 character past end of string
+
+  http_parser_init(&parser);
+
+  req_hdr.create(HTTP_TYPE_REQUEST);
+  rsp_hdr.create(HTTP_TYPE_RESPONSE);
+
+  printf("======== test_http_req_parse_error parsing\n\n");
+  err = req_hdr.parse_req(&parser, &start, end, true, 1, 1);
+  if (err != PARSE_RESULT_ERROR) {
+    status = 0;
+  }
+
+  http_parser_clear(&parser);
+
+  /*** (4) print out the response ***/
+
+  printf("\n======== real response (length=%d)\n\n", (int)strlen(response));
+  printf("%s\n", response);
+
+  obj_describe(rsp_hdr.m_http, true);
+
+  req_hdr.destroy();
+  rsp_hdr.destroy();
+
+  return (failures_to_status("test_http_req_parse_error", (status == 0)));
+}
+
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
@@ -1372,6 +1414,12 @@ HdrTest::test_http()
     "\r\n",
   };
 
+  static const char request_too_long[] = {
+    "GET http://www.news.com/i/am/too/long HTTP/1.1\r\n"
+    "Connection: close\r\n"
+    "\r\n",
+  };
+
   static const char request_unterminated[] = {
     "GET http://www.unterminated.com/ HTTP/1.1",
   };
@@ -1440,6 +1488,11 @@ HdrTest::test_http()
     "\r\n",
   };
 
+  static const char response_too_long_req[] = {
+    "HTTP/1.0 414 URI Too Long\r\n"
+    "\r\n",
+  };
+
   status = status & test_http_aux(request0, response0);
   status = status & test_http_aux(request09, response09);
   status = status & test_http_aux(request1, response1);
@@ -1455,6 +1508,7 @@ HdrTest::test_http()
   status = status & test_http_aux(request_blank, response_blank);
   status = status & test_http_aux(request_blank2, response_blank2);
   status = status & test_http_aux(request_blank3, response_blank3);
+  status = status & test_http_req_parse_error(request_too_long, response_too_long_req);
 
   return (failures_to_status("test_http", (status == 0)));
 }
diff --git a/proxy/hdrs/HdrTest.h b/proxy/hdrs/HdrTest.h
index f9b29d9..76128fa 100644
--- a/proxy/hdrs/HdrTest.h
+++ b/proxy/hdrs/HdrTest.h
@@ -70,6 +70,7 @@ private:
   int test_http_hdr_ctl_char(int testnum, const char *req, const char *req_tgt);
   int test_http_hdr_copy_over_aux(int testnum, const char *request, const char *response);
   int test_http_aux(const char *request, const char *response);
+  int test_http_req_parse_error(const char *request, const char *response);
   int test_arena_aux(Arena *arena, int len);
   void bri_box(const char *s);
   int failures_to_status(const char *testname, int nfail);
diff --git a/proxy/hdrs/MIME.cc b/proxy/hdrs/MIME.cc
index 59aa34d..76cb34b 100644
--- a/proxy/hdrs/MIME.cc
+++ b/proxy/hdrs/MIME.cc
@@ -2493,7 +2493,7 @@ mime_parser_clear(MIMEParser *parser)
 
 ParseResult
 mime_parser_parse(MIMEParser *parser, HdrHeap *heap, MIMEHdrImpl *mh, const char **real_s, const char *real_e,
-                  bool must_copy_strings, bool eof)
+                  bool must_copy_strings, bool eof, size_t max_hdr_field_size)
 {
   ParseResult err;
   bool line_is_real;
@@ -2561,8 +2561,8 @@ mime_parser_parse(MIMEParser *parser, HdrHeap *heap, MIMEHdrImpl *mh, const char
     field_value.ltrim_if(&ParseRules::is_ws);
     field_value.rtrim_if(&ParseRules::is_wslfcr);
 
-    // Make sure the name or value is not longer than 64K
-    if (field_name.size() >= UINT16_MAX || field_value.size() >= UINT16_MAX) {
+    // Make sure the name + value is not longer than configured max_hdr_field_size
+    if (field_name.size() + field_value.size() > max_hdr_field_size) {
       return PARSE_RESULT_ERROR;
     }
 
diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h
index 37b1e27..06e9630 100644
--- a/proxy/hdrs/MIME.h
+++ b/proxy/hdrs/MIME.h
@@ -757,7 +757,7 @@ void mime_field_value_append(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, c
 void mime_parser_init(MIMEParser *parser);
 void mime_parser_clear(MIMEParser *parser);
 ParseResult mime_parser_parse(MIMEParser *parser, HdrHeap *heap, MIMEHdrImpl *mh, const char **real_s, const char *real_e,
-                              bool must_copy_strings, bool eof);
+                              bool must_copy_strings, bool eof, size_t max_hdr_field_size = 131070);
 
 void mime_hdr_describe(HdrHeapObjImpl *raw, bool recurse);
 void mime_field_block_describe(HdrHeapObjImpl *raw, bool recurse);
@@ -1013,7 +1013,8 @@ public:
 
   int print(char *buf, int bufsize, int *bufindex, int *chars_to_skip);
 
-  int parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof);
+  int parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof,
+            size_t max_hdr_field_size = UINT16_MAX);
 
   int value_get_index(const char *name, int name_length, const char *value, int value_length) const;
   const char *value_get(const char *name, int name_length, int *value_length) const;
@@ -1288,7 +1289,7 @@ MIMEHdr::print(char *buf, int bufsize, int *bufindex, int *chars_to_skip)
   -------------------------------------------------------------------------*/
 
 inline int
-MIMEHdr::parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof)
+MIMEHdr::parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof, size_t max_hdr_field_size)
 {
   if (!m_heap)
     m_heap = new_HdrHeap();
@@ -1296,7 +1297,7 @@ MIMEHdr::parse(MIMEParser *parser, const char **start, const char *end, bool mus
   if (!m_mime)
     m_mime = mime_hdr_create(m_heap);
 
-  return mime_parser_parse(parser, m_heap, m_mime, start, end, must_copy_strs, eof);
+  return mime_parser_parse(parser, m_heap, m_mime, start, end, must_copy_strs, eof, max_hdr_field_size);
 }
 
 /*-------------------------------------------------------------------------
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index 515d15d..153ade7 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -987,6 +987,9 @@ HttpConfig::startup()
   HttpEstablishStaticConfigLongLong(c.origin_min_keep_alive_connections, "proxy.config.http.per_server.min_keep_alive");
   HttpEstablishStaticConfigByte(c.oride.attach_server_session_to_client, "proxy.config.http.attach_server_session_to_client");
 
+  HttpEstablishStaticConfigLongLong(c.http_request_line_max_size, "proxy.config.http.request_line_max_size");
+  HttpEstablishStaticConfigLongLong(c.http_hdr_field_max_size, "proxy.config.http.header_field_max_size");
+
   HttpEstablishStaticConfigByte(c.disable_ssl_parenting, "proxy.local.http.parent_proxy.disable_connect_tunneling");
   HttpEstablishStaticConfigByte(c.oride.forward_connect_method, "proxy.config.http.forward_connect_method");
 
@@ -1273,6 +1276,9 @@ HttpConfig::reconfigure()
   params->origin_min_keep_alive_connections     = m_master.origin_min_keep_alive_connections;
   params->oride.attach_server_session_to_client = m_master.oride.attach_server_session_to_client;
 
+  params->http_request_line_max_size = m_master.http_request_line_max_size;
+  params->http_hdr_field_max_size    = m_master.http_hdr_field_max_size;
+
   if (params->oride.outbound_conntrack.max > 0 &&
       params->oride.outbound_conntrack.max < params->origin_min_keep_alive_connections) {
     Warning("'%s' < origin_min_keep_alive_connections, setting min=max , please correct your records.config",
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index b148666..1dbea0b 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -785,6 +785,9 @@ public:
 
   MgmtInt body_factory_response_max_size = 8192;
 
+  MgmtInt http_request_line_max_size = 65535;
+  MgmtInt http_hdr_field_max_size    = 131070;
+
   // noncopyable
   /////////////////////////////////////
   // operator = and copy constructor //
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 8c6afa1..9dc242d 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -656,8 +656,9 @@ HttpSM::state_read_client_request_header(int event, void *data)
   // tokenize header //
   /////////////////////
 
-  ParseResult state = t_state.hdr_info.client_request.parse_req(&http_parser, ua_buffer_reader, &bytes_used, ua_entry->eos,
-                                                                t_state.http_config_param->strict_uri_parsing);
+  ParseResult state = t_state.hdr_info.client_request.parse_req(
+    &http_parser, ua_buffer_reader, &bytes_used, ua_entry->eos, t_state.http_config_param->strict_uri_parsing,
+    t_state.http_config_param->http_request_line_max_size, t_state.http_config_param->http_hdr_field_max_size);
 
   client_request_hdr_bytes += bytes_used;
 
@@ -725,6 +726,10 @@ HttpSM::state_read_client_request_header(int event, void *data)
     // Disable further I/O on the client
     ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
 
+    (bytes_used > t_state.http_config_param->http_request_line_max_size) ?
+      t_state.http_return_code = HTTP_STATUS_REQUEST_URI_TOO_LONG :
+      t_state.http_return_code = HTTP_STATUS_NONE;
+
     call_transact_and_set_next_state(HttpTransact::BadRequest);
     break;
 
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index a19fe40..00e7c3b 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -520,7 +520,22 @@ HttpTransact::BadRequest(State *s)
   TxnDebug("http_trans", "[BadRequest]"
                          "parser marked request bad");
   bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
-  build_error_response(s, HTTP_STATUS_BAD_REQUEST, "Invalid HTTP Request", "request#syntax_error");
+
+  const char *body_factory_template = "request#syntax_error";
+  HTTPStatus status                 = HTTP_STATUS_BAD_REQUEST;
+  const char *reason                = "Invalid HTTP Request";
+
+  switch (s->http_return_code) {
+  case HTTP_STATUS_REQUEST_URI_TOO_LONG:
+    body_factory_template = "request#uri_len_too_long";
+    status                = s->http_return_code;
+    reason                = "URI Too Long";
+    break;
+  default:
+    break;
+  }
+
+  build_error_response(s, status, reason, body_factory_template);
   TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, nullptr);
 }