Permalink
Browse files

apache compatible way of header handling

  • Loading branch information...
1 parent c1f2304 commit 9837c9025a924edfd9ffa8b5849b55abadb8c3ba 奥 一穂 committed Sep 13, 2009
Showing with 50 additions and 16 deletions.
  1. +10 −7 XS.xs
  2. +6 −7 picohttpparser/picohttpparser.c
  3. +15 −1 picohttpparser/test.c
  4. +19 −1 t/01simple.t
View
@@ -68,6 +68,7 @@ CODE:
if (headers[i].name != NULL) {
const char* name;
size_t name_len;
+ SV** slot;
if (header_is(headers + i, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1)) {
name = "CONTENT_TYPE";
name_len = sizeof("CONTENT_TYPE") - 1;
@@ -97,15 +98,17 @@ CODE:
name = tmp;
name_len = headers[i].name_len + 5;
}
- last_value = newSVpv(headers[i].value, headers[i].value_len);
- hv_store(env, name, name_len, last_value, 0);
+ slot = hv_fetch(env, name, name_len, 1);
+ if (SvOK(*slot)) {
+ sv_catpvn(*slot, ", ", 2);
+ sv_catpvn(*slot, headers[i].value, headers[i].value_len);
+ } else {
+ *slot = newSVpvn(headers[i].value, headers[i].value_len);
+ }
+ last_value = *slot;
} else {
/* continuing lines of a mulitiline header */
- if (headers[i].value_len != 0) {
- /* should be optimized, but multiline headers aren't used anyway */
- sv_catpvn(last_value, " ", 1);
- sv_catpvn(last_value, headers[i].value, headers[i].value_len);
- }
+ sv_catpvn(last_value, headers[i].value, headers[i].value_len);
}
}
@@ -132,16 +132,15 @@ int phr_parse_request(const char* _buf, size_t len, const char** method,
}
headers[*num_headers].name_len = buf - headers[*num_headers].name;
++buf;
+ for (; ; ++buf) {
+ CHECK_EOF();
+ if (! (*buf == ' ' || *buf == '\t')) {
+ break;
+ }
+ }
} else {
headers[*num_headers].name = NULL;
headers[*num_headers].name_len = 0;
- ++buf;
- }
- for (; ; ++buf) {
- CHECK_EOF();
- if (! (*buf == ' ' || *buf == '\t')) {
- break;
- }
}
headers[*num_headers].value = buf;
for (; ; ++buf) {
View
@@ -28,7 +28,7 @@ int main(void)
struct phr_header headers[4];
size_t num_headers;
- tests(17);
+ tests(28);
#define PARSE(s, last_len, exp, comment) \
num_headers = sizeof(headers) / sizeof(headers[0]); \
@@ -58,6 +58,20 @@ int main(void)
ok(strrcmp(headers[1].name, headers[1].name_len, "Cookie"), "cookie");
ok(strrcmp(headers[1].value, headers[1].value_len, ""), "cookie value");
+ PARSE("GET / HTTP/1.0\r\nfoo: \r\nfoo: b\r\n \tc\r\n\r\n", 0, 0,
+ "parse multiline");
+ ok(num_headers == 3, "# of headers");
+ ok(strrcmp(method, method_len, "GET"), "method");
+ ok(strrcmp(path, path_len, "/"), "path");
+ ok(minor_version == 0, "minor version");
+ ok(strrcmp(headers[0].name, headers[0].name_len, "foo"), "header #1 name");
+ ok(strrcmp(headers[1].value, headers[1].value_len, ""), "header #1 value");
+ ok(strrcmp(headers[1].name, headers[1].name_len, "foo"), "header #2 name");
+ ok(strrcmp(headers[1].value, headers[1].value_len, "b"), "header #2 value");
+ ok(headers[2].name == NULL, "header #3");
+ ok(strrcmp(headers[2].value, headers[2].value_len, " \tc"),
+ "header #3 value");
+
PARSE("GET /hoge HTTP/1.0\r\n\r", strlen("GET /hoge HTTP/1.0\r\n\r") - 1,
-2, "slowloris (incomplete)");
PARSE("GET /hoge HTTP/1.0\r\n\r\n", strlen("GET /hoge HTTP/1.0\r\n\r\n") - 1,
View
@@ -1,4 +1,4 @@
-use Test::More tests => 4;
+use Test::More tests => 6;
use HTTP::Parser::XS qw(parse_http_request);
@@ -33,3 +33,21 @@ is_deeply(\%env, {
HTTP_HOST => 'example.com',
HTTP_USER_AGENT => 'hoge',
}, 'result of GET with headers');
+
+$req = <<"EOT";
+GET / HTTP/1.0\r
+Foo: \r
+Foo: \r
+ abc\r
+ de\r
+Foo: fgh\r
+\r
+EOT
+is(parse_http_request($req, \%env), length($req), 'multiline header');
+is_deeply(\%env, {
+ REQUEST_METHOD => 'GET',
+ SCRIPT_NAME => '',
+ PATH_INFO => '/',
+ SERVER_PROTOCOL => 'HTTP/1.0',
+ HTTP_FOO => ', abc de, fgh',
+}, 'multiline');

0 comments on commit 9837c90

Please sign in to comment.