pico_http_parser 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -6
- data/benchmark/benchmark.rb +3 -9
- data/ext/pico_http_parser/pico_http_parser.c +101 -16
- data/ext/pico_http_parser/picohttpparser/Makefile +2 -1
- data/ext/pico_http_parser/picohttpparser/README.md +3 -3
- data/ext/pico_http_parser/picohttpparser/bench.c +3 -2
- data/ext/pico_http_parser/picohttpparser/picohttpparser.c +60 -3
- data/ext/pico_http_parser/picohttpparser/picohttpparser.h +2 -1
- data/ext/pico_http_parser/picohttpparser/test.c +13 -1
- data/lib/pico_http_parser/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 417f57e6c7289be7606e9fdda1b65346751f3c10
|
4
|
+
data.tar.gz: 420957b9c7d8ed9338c29d20030109ea0f6c17c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cd7184656ea42efb5f22aa27a42d30ed381f241c665859fbc9e94937195248db6216a4be25903799841148c51842fd2fa93bf0ddf39b699cb48192eb44d0e1a
|
7
|
+
data.tar.gz: 8656caa1f569d72acc097392e67c9316e26c7aa5546d165d1d600566e80a6e1057660696e8096fb00db9a6b7a88860fa890d8a801dbdbedf9f877c4f06e51f62
|
data/README.md
CHANGED
@@ -54,16 +54,17 @@ given request is incomplete
|
|
54
54
|
On my Macbook Air
|
55
55
|
|
56
56
|
```
|
57
|
+
$ ruby benchmark.rb
|
57
58
|
Calculating -------------------------------------
|
58
|
-
PicoHTTPParser 13.
|
59
|
-
Unicorn's HttpParser
|
59
|
+
PicoHTTPParser 13.655k i/100ms
|
60
|
+
Unicorn's HttpParser 11.554k i/100ms
|
60
61
|
-------------------------------------------------
|
61
|
-
PicoHTTPParser
|
62
|
-
Unicorn's HttpParser
|
62
|
+
PicoHTTPParser 155.331k (�� 3.7%) i/s - 778.335k
|
63
|
+
Unicorn's HttpParser 127.455k (�� 3.5%) i/s - 647.024k
|
63
64
|
|
64
65
|
Comparison:
|
65
|
-
PicoHTTPParser:
|
66
|
-
Unicorn's HttpParser:
|
66
|
+
PicoHTTPParser: 155331.2 i/s
|
67
|
+
Unicorn's HttpParser: 127455.1 i/s - 1.22x slower
|
67
68
|
```
|
68
69
|
|
69
70
|
## SEE ALSO
|
data/benchmark/benchmark.rb
CHANGED
@@ -2,15 +2,9 @@ require File.expand_path(File.dirname(__FILE__) + '/bench_helper')
|
|
2
2
|
|
3
3
|
require 'pico_http_parser'
|
4
4
|
|
5
|
-
request_body =
|
6
|
-
GET /
|
7
|
-
|
8
|
-
Cookie: blah=woop\r
|
9
|
-
\r
|
10
|
-
REQ
|
11
|
-
loop = 300000
|
12
|
-
|
13
|
-
#File.read(File.expand_path(File.dirname(__FILE__) + '/sample_request.http'))
|
5
|
+
# request_body = "GET /foo/bar/baz.html?key=value HTTP/1.0\r\nHost: blooperblorp\r\n\r\n"
|
6
|
+
request_body = "GET /foo/bar/baz.html?key=value HTTP/1.0\r\nHost: blooperblorp\r\nCookie: foobar\r\nX-Forwared-For: 127.0.0.1\r\n\r\n"
|
7
|
+
# request_body = "GET /foo/bar/baz.html?key=value HTTP/1.0\r\n\r\n"
|
14
8
|
|
15
9
|
Benchmark.ips do |x|
|
16
10
|
x.time = 5
|
@@ -8,6 +8,58 @@
|
|
8
8
|
|
9
9
|
VALUE cPicoHTTPParser;
|
10
10
|
|
11
|
+
static VALUE request_method_key;
|
12
|
+
static VALUE request_uri_key;
|
13
|
+
static VALUE script_name_key;
|
14
|
+
static VALUE server_protocol_key;
|
15
|
+
static VALUE query_string_key;
|
16
|
+
|
17
|
+
struct common_header {
|
18
|
+
const char * name;
|
19
|
+
size_t name_len;
|
20
|
+
VALUE key;
|
21
|
+
};
|
22
|
+
static int common_headers_num = 0;
|
23
|
+
static struct common_header common_headers[20];
|
24
|
+
|
25
|
+
static
|
26
|
+
void set_common_header(const char * key, int key_len, const int raw)
|
27
|
+
{
|
28
|
+
char tmp[MAX_HEADER_NAME_LEN + sizeof("HTTP_") - 1];
|
29
|
+
const char* name;
|
30
|
+
size_t name_len;
|
31
|
+
const char * s;
|
32
|
+
char* d;
|
33
|
+
size_t n;
|
34
|
+
VALUE env_key;
|
35
|
+
|
36
|
+
if ( raw == 1) {
|
37
|
+
for (s = key, n = key_len, d = tmp;
|
38
|
+
n != 0;
|
39
|
+
s++, --n, d++) {
|
40
|
+
*d = *s == '-' ? '_' : TOU(*s);
|
41
|
+
name = tmp;
|
42
|
+
name_len = key_len;
|
43
|
+
}
|
44
|
+
} else {
|
45
|
+
strcpy(tmp, "HTTP_");
|
46
|
+
for (s = key, n = key_len, d = tmp + 5;
|
47
|
+
n != 0;
|
48
|
+
s++, --n, d++) {
|
49
|
+
*d = *s == '-' ? '_' : TOU(*s);
|
50
|
+
name = tmp;
|
51
|
+
name_len = key_len + 5;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
env_key = rb_obj_freeze(rb_str_new(name,name_len));
|
55
|
+
common_headers[common_headers_num].name = key;
|
56
|
+
common_headers[common_headers_num].name_len = key_len;
|
57
|
+
common_headers[common_headers_num].key = env_key;
|
58
|
+
rb_gc_register_address(&common_headers[common_headers_num].key);
|
59
|
+
common_headers_num++;
|
60
|
+
}
|
61
|
+
|
62
|
+
|
11
63
|
static
|
12
64
|
size_t find_ch(const char* s, size_t len, char ch)
|
13
65
|
{
|
@@ -31,6 +83,16 @@ int header_is(const struct phr_header* header, const char* name,
|
|
31
83
|
return 1;
|
32
84
|
}
|
33
85
|
|
86
|
+
static
|
87
|
+
VALUE find_common_header(const struct phr_header* header) {
|
88
|
+
int i;
|
89
|
+
for ( i = 0; i < common_headers_num; i++ ) {
|
90
|
+
if ( header_is(header, common_headers[i].name, common_headers[i].name_len) ) {
|
91
|
+
return common_headers[i].key;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
return Qnil;
|
95
|
+
}
|
34
96
|
|
35
97
|
static
|
36
98
|
int store_path_info(VALUE envref, const char* src, size_t src_len) {
|
@@ -93,11 +155,12 @@ VALUE phr_parse_http_request(VALUE self, VALUE buf, VALUE envref)
|
|
93
155
|
if (ret < 0)
|
94
156
|
goto done;
|
95
157
|
|
96
|
-
rb_hash_aset(envref,
|
97
|
-
rb_hash_aset(envref,
|
98
|
-
rb_hash_aset(envref,
|
99
|
-
|
100
|
-
|
158
|
+
rb_hash_aset(envref, request_method_key, rb_str_new(method,method_len));
|
159
|
+
rb_hash_aset(envref, request_uri_key, rb_str_new(path, path_len));
|
160
|
+
rb_hash_aset(envref, script_name_key, rb_str_new2(""));
|
161
|
+
strcpy(tmp, "HTTP/1.");
|
162
|
+
tmp[7] = 48 + ((minor_version > 1 || minor_version < 0 ) ? 0 : minor_version);
|
163
|
+
rb_hash_aset(envref, server_protocol_key, rb_str_new(tmp, sizeof("HTTP/1.0") - 1));
|
101
164
|
|
102
165
|
/* PATH_INFO QUERY_STRING */
|
103
166
|
path_len = find_ch(path, path_len, '#'); /* strip off all text after # after storing request_uri */
|
@@ -108,7 +171,7 @@ VALUE phr_parse_http_request(VALUE self, VALUE buf, VALUE envref)
|
|
108
171
|
goto done;
|
109
172
|
}
|
110
173
|
if (question_at != path_len) ++question_at;
|
111
|
-
rb_hash_aset(envref,
|
174
|
+
rb_hash_aset(envref, query_string_key, rb_str_new(path + question_at, path_len - question_at));
|
112
175
|
|
113
176
|
last_value = Qnil;
|
114
177
|
for (i = 0; i < num_headers; ++i) {
|
@@ -116,13 +179,9 @@ VALUE phr_parse_http_request(VALUE self, VALUE buf, VALUE envref)
|
|
116
179
|
const char* name;
|
117
180
|
size_t name_len;
|
118
181
|
VALUE slot;
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
} else if (header_is(headers + i, "CONTENT-LENGTH", sizeof("CONTENT-LENGTH") - 1)) {
|
123
|
-
name = "CONTENT_LENGTH";
|
124
|
-
name_len = sizeof("CONTENT_LENGTH") - 1;
|
125
|
-
} else {
|
182
|
+
VALUE env_key;
|
183
|
+
env_key = find_common_header(headers + i);
|
184
|
+
if ( env_key == Qnil ) {
|
126
185
|
const char* s;
|
127
186
|
char* d;
|
128
187
|
size_t n;
|
@@ -138,20 +197,22 @@ VALUE phr_parse_http_request(VALUE self, VALUE buf, VALUE envref)
|
|
138
197
|
*d = *s == '-' ? '_' : TOU(*s);
|
139
198
|
name = tmp;
|
140
199
|
name_len = headers[i].name_len + 5;
|
200
|
+
env_key = rb_str_new(name, name_len);
|
141
201
|
}
|
142
202
|
}
|
143
|
-
slot = rb_hash_aref(envref,
|
203
|
+
slot = rb_hash_aref(envref, env_key);
|
144
204
|
if ( slot != Qnil ) {
|
145
205
|
rb_str_cat2(slot, ", ");
|
146
206
|
rb_str_cat(slot, headers[i].value, headers[i].value_len);
|
147
207
|
} else {
|
148
208
|
slot = rb_str_new(headers[i].value, headers[i].value_len);
|
149
|
-
rb_hash_aset(envref,
|
209
|
+
rb_hash_aset(envref, env_key, slot);
|
150
210
|
last_value = slot;
|
151
211
|
}
|
152
212
|
} else {
|
153
213
|
/* continuing lines of a mulitiline header */
|
154
|
-
|
214
|
+
if ( last_value != Qnil )
|
215
|
+
rb_str_cat(last_value, headers[i].value, headers[i].value_len);
|
155
216
|
}
|
156
217
|
}
|
157
218
|
|
@@ -161,6 +222,30 @@ VALUE phr_parse_http_request(VALUE self, VALUE buf, VALUE envref)
|
|
161
222
|
|
162
223
|
void Init_pico_http_parser()
|
163
224
|
{
|
225
|
+
request_method_key = rb_obj_freeze(rb_str_new2("REQUEST_METHOD"));
|
226
|
+
rb_gc_register_address(&request_method_key);
|
227
|
+
request_uri_key = rb_obj_freeze(rb_str_new2("REQUEST_URI"));
|
228
|
+
rb_gc_register_address(&request_uri_key);
|
229
|
+
script_name_key = rb_obj_freeze(rb_str_new2("SCRIPT_NAME"));
|
230
|
+
rb_gc_register_address(&script_name_key);
|
231
|
+
server_protocol_key = rb_obj_freeze(rb_str_new2("SERVER_PROTOCOL"));
|
232
|
+
rb_gc_register_address(&server_protocol_key);
|
233
|
+
query_string_key = rb_obj_freeze(rb_str_new2("QUERY_STRING"));
|
234
|
+
rb_gc_register_address(&query_string_key);
|
235
|
+
|
236
|
+
set_common_header("ACCEPT",sizeof("ACCEPT") - 1, 0);
|
237
|
+
set_common_header("ACCEPT-ENCODING",sizeof("ACCEPT-ENCODING") - 1, 0);
|
238
|
+
set_common_header("ACCEPT-LANGUAGE",sizeof("ACCEPT-LANGUAGE") - 1, 0);
|
239
|
+
set_common_header("CACHE-CONTROL",sizeof("CACHE-CONTROL") - 1, 0);
|
240
|
+
set_common_header("CONNECTION",sizeof("CONNECTION") - 1, 0);
|
241
|
+
set_common_header("CONTENT-LENGTH",sizeof("CONTENT-LENGTH") - 1, 1);
|
242
|
+
set_common_header("CONTENT-TYPE",sizeof("CONTENT-TYPE") - 1, 1);
|
243
|
+
set_common_header("COOKIE",sizeof("COOKIE") - 1, 0);
|
244
|
+
set_common_header("HOST",sizeof("HOST") - 1, 0);
|
245
|
+
set_common_header("IF-MODIFIED-SINCE",sizeof("IF-MODIFIED-SINCE") - 1, 0);
|
246
|
+
set_common_header("REFERER",sizeof("REFERER") - 1, 0);
|
247
|
+
set_common_header("USER-AGENT",sizeof("USER-AGENT") - 1, 0);
|
248
|
+
set_common_header("X-FORWARDED-FOR",sizeof("X-FORWARDED-FOR") - 1, 0);
|
164
249
|
|
165
250
|
cPicoHTTPParser = rb_const_get(rb_cObject, rb_intern("PicoHTTPParser"));
|
166
251
|
rb_define_module_function(cPicoHTTPParser, "parse_http_request", phr_parse_http_request, 2);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PicoHTTPParser
|
2
2
|
=============
|
3
3
|
|
4
|
-
Copyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester)
|
4
|
+
Copyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester), [Shigeo Mitsunari](https://github.com/herumi)
|
5
5
|
|
6
6
|
PicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.
|
7
7
|
|
@@ -17,8 +17,8 @@ The software is dual-licensed under the Perl License or the MIT License.
|
|
17
17
|
Benchmark
|
18
18
|
---------
|
19
19
|
|
20
|
-
![benchmark results](http://i.gyazo.com/
|
20
|
+
![benchmark results](http://i.gyazo.com/a85c18d3162dfb46b485bb41e0ad443a.png)
|
21
21
|
|
22
|
-
The benchmark code is from [fukamachi/fast-http](https://github.com/fukamachi/fast-http/).
|
22
|
+
The benchmark code is from [fukamachi/fast-http@6b91103](https://github.com/fukamachi/fast-http/tree/6b9110347c7a3407310c08979aefd65078518478).
|
23
23
|
|
24
24
|
The internals of picohttpparser has been described to some extent in [my blog entry]( http://blog.kazuhooku.com/2014/11/the-internals-h2o-or-how-to-write-fast.html).
|
@@ -1,5 +1,6 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase
|
2
|
+
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
|
3
|
+
* Shigeo Mitsunari
|
3
4
|
*
|
4
5
|
* The software is licensed under either the MIT License (below) or the Perl
|
5
6
|
* license.
|
@@ -40,7 +41,7 @@ int main(void)
|
|
40
41
|
size_t num_headers;
|
41
42
|
int i, ret;
|
42
43
|
|
43
|
-
for (i = 0; i <
|
44
|
+
for (i = 0; i < 10000000; i++) {
|
44
45
|
num_headers = sizeof(headers) / sizeof(headers[0]);
|
45
46
|
ret = phr_parse_request(REQ, sizeof(REQ) - 1, &method, &method_len, &path,
|
46
47
|
&path_len, &minor_version, headers, &num_headers,
|
@@ -1,5 +1,6 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase
|
2
|
+
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
|
3
|
+
* Shigeo Mitsunari
|
3
4
|
*
|
4
5
|
* The software is licensed under either the MIT License (below) or the Perl
|
5
6
|
* license.
|
@@ -24,6 +25,9 @@
|
|
24
25
|
*/
|
25
26
|
|
26
27
|
#include <stddef.h>
|
28
|
+
#ifdef __SSE4_2__
|
29
|
+
# include <x86intrin.h>
|
30
|
+
#endif
|
27
31
|
#include "picohttpparser.h"
|
28
32
|
|
29
33
|
/* $Id$ */
|
@@ -53,8 +57,13 @@
|
|
53
57
|
|
54
58
|
#define ADVANCE_TOKEN(tok, toklen) do { \
|
55
59
|
const char* tok_start = buf; \
|
56
|
-
|
60
|
+
static const char ranges2[] __attribute__((aligned(16))) = "\000\040\177\177"; \
|
61
|
+
int found2; \
|
62
|
+
buf = findchar_fast(buf, buf_end, ranges2, sizeof(ranges2) - 1, &found2); \
|
63
|
+
if (! found2) { \
|
57
64
|
CHECK_EOF(); \
|
65
|
+
} \
|
66
|
+
while (1) { \
|
58
67
|
if (*buf == ' ') { \
|
59
68
|
break; \
|
60
69
|
} else if (unlikely(! IS_PRINTABLE_ASCII(*buf))) { \
|
@@ -63,6 +72,8 @@
|
|
63
72
|
return NULL; \
|
64
73
|
} \
|
65
74
|
} \
|
75
|
+
++buf; \
|
76
|
+
CHECK_EOF(); \
|
66
77
|
} \
|
67
78
|
tok = tok_start; \
|
68
79
|
toklen = buf - tok_start; \
|
@@ -78,12 +89,50 @@ static const char* token_char_map =
|
|
78
89
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
79
90
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
80
91
|
|
92
|
+
static const char* findchar_fast(const char* buf, const char* buf_end, const char *ranges, size_t ranges_size, int* found)
|
93
|
+
{
|
94
|
+
*found = 0;
|
95
|
+
#if __SSE4_2__
|
96
|
+
if (likely(buf_end - buf >= 16)) {
|
97
|
+
__m128i ranges16 = _mm_loadu_si128((const __m128i*)ranges);
|
98
|
+
|
99
|
+
size_t left = (buf_end - buf) & ~15;
|
100
|
+
do {
|
101
|
+
__m128i b16 = _mm_loadu_si128((void*)buf);
|
102
|
+
int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
|
103
|
+
if (unlikely(r != 16)) {
|
104
|
+
buf += r;
|
105
|
+
*found = 1;
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
buf += 16;
|
109
|
+
left -= 16;
|
110
|
+
} while (likely(left != 0));
|
111
|
+
}
|
112
|
+
#endif
|
113
|
+
return buf;
|
114
|
+
}
|
115
|
+
|
81
116
|
static const char* get_token_to_eol(const char* buf, const char* buf_end,
|
82
117
|
const char** token, size_t* token_len,
|
83
118
|
int* ret)
|
84
119
|
{
|
85
120
|
const char* token_start = buf;
|
86
121
|
|
122
|
+
#ifdef __SSE4_2__
|
123
|
+
static const char ranges1[] =
|
124
|
+
"\0\010"
|
125
|
+
/* allow HT */
|
126
|
+
"\012\037"
|
127
|
+
/* allow SP and up to but not including DEL */
|
128
|
+
"\177\177"
|
129
|
+
/* allow chars w. MSB set */
|
130
|
+
;
|
131
|
+
int found;
|
132
|
+
buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
|
133
|
+
if (found)
|
134
|
+
goto FOUND_CTL;
|
135
|
+
#else
|
87
136
|
/* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */
|
88
137
|
while (likely(buf_end - buf >= 8)) {
|
89
138
|
#define DOIT() if (unlikely(! IS_PRINTABLE_ASCII(*buf))) goto NonPrintable; ++buf
|
@@ -97,6 +146,7 @@ static const char* get_token_to_eol(const char* buf, const char* buf_end,
|
|
97
146
|
}
|
98
147
|
++buf;
|
99
148
|
}
|
149
|
+
#endif
|
100
150
|
for (; ; ++buf) {
|
101
151
|
CHECK_EOF();
|
102
152
|
if (unlikely(! IS_PRINTABLE_ASCII(*buf))) {
|
@@ -211,14 +261,21 @@ static const char* parse_headers(const char* buf, const char* buf_end,
|
|
211
261
|
/* parsing name, but do not discard SP before colon, see
|
212
262
|
* http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
|
213
263
|
headers[*num_headers].name = buf;
|
214
|
-
|
264
|
+
static const char ranges1[] __attribute__((aligned(16))) = "::\x00\037";
|
265
|
+
int found;
|
266
|
+
buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
|
267
|
+
if (! found) {
|
215
268
|
CHECK_EOF();
|
269
|
+
}
|
270
|
+
while (1) {
|
216
271
|
if (*buf == ':') {
|
217
272
|
break;
|
218
273
|
} else if (*buf < ' ') {
|
219
274
|
*ret = -1;
|
220
275
|
return NULL;
|
221
276
|
}
|
277
|
+
++buf;
|
278
|
+
CHECK_EOF();
|
222
279
|
}
|
223
280
|
headers[*num_headers].name_len = buf - headers[*num_headers].name;
|
224
281
|
++buf;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/* use `make test` to run the test */
|
2
2
|
/*
|
3
|
-
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase
|
3
|
+
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
|
4
|
+
* Shigeo Mitsunari
|
4
5
|
*
|
5
6
|
* The software is licensed under either the MIT License (below) or the Perl
|
6
7
|
* license.
|
@@ -97,6 +98,15 @@ static void test_request(void)
|
|
97
98
|
ok(headers[2].name == NULL);
|
98
99
|
ok(bufis(headers[2].value, headers[2].value_len, " \tc"));
|
99
100
|
|
101
|
+
PARSE("GET / HTTP/1.0\r\nfoo : ab\r\n\r\n", 0, 0,
|
102
|
+
"parse header name with trailing space");
|
103
|
+
ok(num_headers == 1);
|
104
|
+
ok(bufis(method, method_len, "GET"));
|
105
|
+
ok(bufis(path, path_len, "/"));
|
106
|
+
ok(minor_version == 0);
|
107
|
+
ok(bufis(headers[0].name, headers[0].name_len, "foo "));
|
108
|
+
ok(bufis(headers[0].value, headers[0].value_len, "ab"));
|
109
|
+
|
100
110
|
PARSE("GET", 0, -2, "incomplete 1");
|
101
111
|
ok(method == NULL);
|
102
112
|
PARSE("GET ", 0, -2, "incomplete 2");
|
@@ -125,6 +135,8 @@ static void test_request(void)
|
|
125
135
|
PARSE("GET /\x7fhello HTTP/1.0\r\n\r\n", 0, -1, "DEL in uri-path");
|
126
136
|
PARSE("GET / HTTP/1.0\r\na\0b: c\r\n\r\n", 0, -1, "NUL in header name");
|
127
137
|
PARSE("GET / HTTP/1.0\r\nab: c\0d\r\n\r\n", 0, -1, "NUL in header value");
|
138
|
+
PARSE("GET / HTTP/1.0\r\na\033b: c\r\n\r\n", 0, -1, "CTL in header name");
|
139
|
+
PARSE("GET / HTTP/1.0\r\nab: c\033\r\n\r\n", 0, -1, "CTL in header value");
|
128
140
|
PARSE("GET /\xa0 HTTP/1.0\r\nh: c\xa2y\r\n\r\n", 0, 0, "accept MSB chars");
|
129
141
|
ok(num_headers == 1);
|
130
142
|
ok(bufis(method, method_len, "GET"));
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pico_http_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Nagano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|