about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-08-09 04:07:15 -0700
committerEric Wong <normalperson@yhbt.net>2009-08-09 04:10:54 -0700
commitb20dca2f1ab4b419bf496fb3212ce424b529ac2b (patch)
tree71c0dd711bdf383ebc07ca87e7239cc83517c451
parent91150f18c4c7fe6ee912bb835ecaea001c322d30 (diff)
downloadunicorn-b20dca2f1ab4b419bf496fb3212ce424b529ac2b.tar.gz
Since Rack requires a Hash object, this is joined in in
accordance with rfc2616, section 4.2[1].  Of course, it's up to
the framework or application to handle such requests.

I could optimize this to avoid creating a single garbage
String object, but I don't think it's common enough to
worry about...

[1] - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
-rw-r--r--ext/unicorn_http/unicorn_http.rl13
-rw-r--r--test/unit/test_http_parser_ng.rb11
2 files changed, 21 insertions, 3 deletions
diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl
index edf39ae..e985e0e 100644
--- a/ext/unicorn_http/unicorn_http.rl
+++ b/ext/unicorn_http/unicorn_http.rl
@@ -57,6 +57,7 @@ static void write_value(VALUE req, struct http_parser *hp,
 {
   VALUE f = find_common_field(PTR_TO(start.field), hp->s.field_len);
   VALUE v;
+  VALUE e;
 
   VALIDATE_MAX_LENGTH(LEN(mark, p), FIELD_VALUE);
   v = STR_NEW(mark, p);
@@ -76,10 +77,16 @@ static void write_value(VALUE req, struct http_parser *hp,
   } else if (f == g_http_trailer) {
     hp->flags |= UH_FL_HASTRAILER;
     invalid_if_trailer(hp->flags);
-  } else if (f == g_http_host && rb_hash_aref(req, f) != Qnil) {
-    return; /* full URLs in REQUEST_URI take precedence */
   }
-  rb_hash_aset(req, f, v);
+
+  e = rb_hash_aref(req, f);
+  if (e == Qnil) {
+    rb_hash_aset(req, f, v);
+  } else if (f != g_http_host) {
+    /* full URLs in REQUEST_URI take precedence for the Host: header */
+    rb_str_buf_cat(e, ",", 1);
+    rb_str_buf_append(e, v);
+  }
 }
 
 /** Machine **/
diff --git a/test/unit/test_http_parser_ng.rb b/test/unit/test_http_parser_ng.rb
index 6fc0bda..8c453dd 100644
--- a/test/unit/test_http_parser_ng.rb
+++ b/test/unit/test_http_parser_ng.rb
@@ -252,4 +252,15 @@ class HttpParserNgTest < Test::Unit::TestCase
     assert_raise(HttpParserError) { @parser.trailers(req, str) }
   end
 
+  def test_repeat_headers
+    str = "PUT / HTTP/1.1\r\n" \
+          "Trailer: Content-MD5\r\n" \
+          "Trailer: Content-SHA1\r\n" \
+          "transfer-Encoding: chunked\r\n\r\n" \
+          "1\r\na\r\n2\r\n..\r\n0\r\n"
+    req = {}
+    assert_equal req, @parser.headers(req, str)
+    assert_equal 'Content-MD5,Content-SHA1', req['HTTP_TRAILER']
+  end
+
 end