about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-09-06 14:29:57 -0700
committerEric Wong <normalperson@yhbt.net>2009-09-06 14:31:37 -0700
commit1b1029efa7089a8a3628286fe006b1fc1ae8601e (patch)
treea5d5ec3ac6eb82989809447100a61ba2ef1cbb02
parent2213d73a2d23bb39e8a4fa82a33d03daf4c39df2 (diff)
downloadunicorn-1b1029efa7089a8a3628286fe006b1fc1ae8601e.tar.gz
This probably doesn't affect anyone with HTTP/1.1, but
future versions of HTTP will use absolute URIs and maybe
we'll eventually get clients that (mistakenly) send us
Host: headers along with absolute URIs.
-rw-r--r--ext/unicorn_http/unicorn_http.rl11
-rw-r--r--test/unit/test_http_parser.rb11
2 files changed, 19 insertions, 3 deletions
diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl
index f296637..59748e2 100644
--- a/ext/unicorn_http/unicorn_http.rl
+++ b/ext/unicorn_http/unicorn_http.rl
@@ -38,7 +38,7 @@ struct http_parser {
     size_t field_len; /* only used during header processing */
     size_t dest_offset; /* only used during body processing */
   } s;
-  VALUE cont;
+  VALUE cont; /* Qfalse: unset, Qnil: ignored header, T_STRING: append */
   union {
     off_t content;
     off_t chunk;
@@ -139,9 +139,12 @@ static void write_cont_value(struct http_parser *hp,
 {
   char *vptr;
 
-  if (!hp->cont)
-    rb_raise(eHttpParserError, "invalid continuation line");
+  if (hp->cont == Qfalse)
+     rb_raise(eHttpParserError, "invalid continuation line");
+  if (NIL_P(hp->cont))
+     return; /* we're ignoring this header (probably Host:) */
 
+  assert(TYPE(hp->cont) == T_STRING && "continuation line is not a string");
   assert(hp->mark > 0 && "impossible continuation line offset");
 
   if (LEN(mark, p) == 0)
@@ -200,6 +203,7 @@ static void write_value(VALUE req, struct http_parser *hp,
      * ignored, absolute URLs in REQUEST_URI take precedence over
      * the Host: header (ref: rfc 2616, section 5.2.1)
      */
+     hp->cont = Qnil;
   } else {
     rb_str_buf_cat(e, ",", 1);
     hp->cont = rb_str_buf_append(e, v);
@@ -333,6 +337,7 @@ static void http_parser_init(struct http_parser *hp)
 {
   int cs = 0;
   memset(hp, 0, sizeof(struct http_parser));
+  hp->cont = Qfalse; /* zero on MRI, should be optimized away by above */
   %% write init;
   hp->cs = cs;
 }
diff --git a/test/unit/test_http_parser.rb b/test/unit/test_http_parser.rb
index 5ba0239..7475de5 100644
--- a/test/unit/test_http_parser.rb
+++ b/test/unit/test_http_parser.rb
@@ -180,6 +180,17 @@ class HttpParserTest < Test::Unit::TestCase
     assert_equal 'hi y x ASDF', req['HTTP_X_ASDF']
   end
 
+  def test_continuation_with_absolute_uri_and_ignored_host_header
+    parser = HttpParser.new
+    header = "GET http://example.com/ HTTP/1.1\r\n" \
+             "Host: \r\n" \
+             "    YHBT.net\r\n" \
+             "\r\n"
+    req = {}
+    assert_equal req, parser.headers(req, header)
+    assert_equal 'example.com', req['HTTP_HOST']
+  end
+
   # this may seem to be testing more of an implementation detail, but
   # it also helps ensure we're safe in the presence of multiple parsers
   # in case we ever go multithreaded/evented...