From b89f94414e0bd79dab212480895cd42f5e427755 Mon Sep 17 00:00:00 2001 From: Sean Cunningham Date: Fri, 29 Apr 2011 13:59:33 -0400 Subject: [PATCH] Support multi-line folding in header values. Normal value cb is called for subsequent lines. LWS is skipped. Note that \t whitespace character is now supported after header field name. RFC 2616, Section 2.2 "HTTP/1.1 header field values can be folded onto multiple lines if the continuation line begins with a space or horizontal tab. All linear white space, including folding, has the same semantics as SP. A recipient MAY replace any linear white space with a single SP before interpreting the field value or forwarding the message downstream." --- http_parser.c | 18 ++++++++++++++++-- test.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/http_parser.c b/http_parser.c index 41edcaa..e8f5364 100644 --- a/http_parser.c +++ b/http_parser.c @@ -241,6 +241,7 @@ enum state , s_header_field , s_header_value_start , s_header_value + , s_header_value_lws , s_header_almost_done @@ -1040,6 +1041,7 @@ size_t http_parser_execute (http_parser *parser, } case s_header_field_start: + header_field_start: { if (ch == CR) { state = s_headers_almost_done; @@ -1217,7 +1219,7 @@ size_t http_parser_execute (http_parser *parser, case s_header_value_start: { - if (ch == ' ') break; + if (ch == ' ' || ch == '\t') break; MARK(header_value); @@ -1360,7 +1362,7 @@ size_t http_parser_execute (http_parser *parser, { STRICT_CHECK(ch != LF); - state = s_header_field_start; + state = s_header_value_lws; switch (header_state) { case h_connection_keep_alive: @@ -1378,6 +1380,18 @@ size_t http_parser_execute (http_parser *parser, break; } + case s_header_value_lws: + { + if (ch == ' ' || ch == '\t') + state = s_header_value_start; + else + { + state = s_header_field_start; + goto header_field_start; + } + break; + } + case s_headers_almost_done: headers_almost_done: { diff --git a/test.c b/test.c index a4b80a2..876cacf 100644 --- a/test.c +++ b/test.c @@ -582,6 +582,35 @@ const struct message requests[] = ,.body= "" } +#define LINE_FOLDING_IN_HEADER 20 +, {.name= "line folding in header value" + ,.type= HTTP_REQUEST + ,.raw= "GET / HTTP/1.1\r\n" + "Line1: abc\r\n" + "\tdef\r\n" + " ghi\r\n" + "\t\tjkl\r\n" + " mno \r\n" + "\t \tqrs\r\n" + "Line2: \t line2\t\r\n" + "\r\n" + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.method= HTTP_GET + ,.query_string= "" + ,.fragment= "" + ,.request_path= "/" + ,.request_url= "/" + ,.num_headers= 2 + ,.headers= { { "Line1", "abcdefghijklmno qrs" } + , { "Line2", "line2\t" } + } + ,.body= "" + } + + #define QUERY_TERMINATED_HOST 21 , {.name= "host terminated by a query string" ,.type= HTTP_REQUEST @@ -1943,7 +1972,7 @@ main (void) "\tRA==\r\n" "\t-----END CERTIFICATE-----\r\n" "\r\n"; - test_simple(dumbfuck2, 0); + test_simple(dumbfuck2, 1); #if 0 // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body