h1p 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -1
- data/Gemfile.lock +1 -1
- data/README.md +28 -14
- data/Rakefile +1 -1
- data/benchmarks/bm_http1_parser.rb +1 -1
- data/benchmarks/pipelined.rb +101 -0
- data/examples/callable.rb +1 -1
- data/examples/http_server.rb +2 -2
- data/ext/h1p/h1p.c +340 -196
- data/ext/h1p/limits.rb +7 -6
- data/lib/h1p/version.rb +1 -1
- data/test/run.rb +5 -0
- data/test/test_h1p_client.rb +532 -0
- data/test/{test_h1p.rb → test_h1p_server.rb} +36 -36
- metadata +11 -8
data/ext/h1p/h1p.c
CHANGED
@@ -37,6 +37,8 @@ VALUE STR_pseudo_method;
|
|
37
37
|
VALUE STR_pseudo_path;
|
38
38
|
VALUE STR_pseudo_protocol;
|
39
39
|
VALUE STR_pseudo_rx;
|
40
|
+
VALUE STR_pseudo_status;
|
41
|
+
VALUE STR_pseudo_status_message;
|
40
42
|
|
41
43
|
VALUE STR_chunked;
|
42
44
|
VALUE STR_content_length;
|
@@ -46,6 +48,9 @@ VALUE SYM_backend_read;
|
|
46
48
|
VALUE SYM_backend_recv;
|
47
49
|
VALUE SYM_stock_readpartial;
|
48
50
|
|
51
|
+
VALUE SYM_client;
|
52
|
+
VALUE SYM_server;
|
53
|
+
|
49
54
|
enum read_method {
|
50
55
|
method_readpartial, // receiver.readpartial(len, buf, pos, raise_on_eof: false) (Polyphony-specific)
|
51
56
|
method_backend_read, // Polyphony.backend_read (Polyphony-specific)
|
@@ -54,17 +59,27 @@ enum read_method {
|
|
54
59
|
method_stock_readpartial // receiver.readpartial(len)
|
55
60
|
};
|
56
61
|
|
62
|
+
enum parser_mode {
|
63
|
+
mode_server,
|
64
|
+
mode_client
|
65
|
+
};
|
66
|
+
|
57
67
|
typedef struct parser {
|
68
|
+
enum parser_mode mode;
|
58
69
|
VALUE io;
|
59
70
|
VALUE buffer;
|
60
71
|
VALUE headers;
|
61
|
-
int pos;
|
62
72
|
int current_request_rx;
|
63
73
|
|
64
74
|
enum read_method read_method;
|
65
75
|
int body_read_mode;
|
66
76
|
int body_left;
|
67
77
|
int request_completed;
|
78
|
+
|
79
|
+
char *buf_ptr;
|
80
|
+
int buf_len;
|
81
|
+
int buf_pos;
|
82
|
+
|
68
83
|
} Parser_t;
|
69
84
|
|
70
85
|
VALUE cParser = Qnil;
|
@@ -125,14 +140,21 @@ enum read_method detect_read_method(VALUE io) {
|
|
125
140
|
rb_raise(rb_eRuntimeError, "Provided reader should be a callable or respond to #__parser_read_method__");
|
126
141
|
}
|
127
142
|
|
128
|
-
|
143
|
+
enum parser_mode parse_parser_mode(VALUE mode) {
|
144
|
+
if (mode == SYM_server) return mode_server;
|
145
|
+
if (mode == SYM_client) return mode_client;
|
146
|
+
|
147
|
+
rb_raise(rb_eRuntimeError, "Invalid parser mode specified");
|
148
|
+
}
|
149
|
+
|
150
|
+
VALUE Parser_initialize(VALUE self, VALUE io, VALUE mode) {
|
129
151
|
Parser_t *parser;
|
130
152
|
GetParser(self, parser);
|
131
153
|
|
154
|
+
parser->mode = parse_parser_mode(mode);
|
132
155
|
parser->io = io;
|
133
156
|
parser->buffer = rb_str_new_literal("");
|
134
157
|
parser->headers = Qnil;
|
135
|
-
parser->pos = 0;
|
136
158
|
|
137
159
|
// pre-allocate the buffer
|
138
160
|
rb_str_modify_expand(parser->buffer, INITIAL_BUFFER_SIZE);
|
@@ -140,6 +162,11 @@ VALUE Parser_initialize(VALUE self, VALUE io) {
|
|
140
162
|
parser->read_method = detect_read_method(io);
|
141
163
|
parser->body_read_mode = BODY_READ_MODE_UNKNOWN;
|
142
164
|
parser->body_left = 0;
|
165
|
+
|
166
|
+
parser->buf_ptr = 0;
|
167
|
+
parser->buf_len = 0;
|
168
|
+
parser->buf_pos = 0;
|
169
|
+
|
143
170
|
return self;
|
144
171
|
}
|
145
172
|
|
@@ -148,95 +175,96 @@ VALUE Parser_initialize(VALUE self, VALUE io) {
|
|
148
175
|
#define str_downcase(str) (rb_funcall((str), ID_downcase, 0))
|
149
176
|
#define str_upcase(str) (rb_funcall((str), ID_upcase, 0))
|
150
177
|
|
151
|
-
#define FILL_BUFFER_OR_GOTO_EOF(
|
178
|
+
#define FILL_BUFFER_OR_GOTO_EOF(parser) { if (!fill_buffer(parser)) goto eof; }
|
152
179
|
|
153
|
-
#define BUFFER_POS(
|
154
|
-
#define BUFFER_LEN(
|
155
|
-
#define BUFFER_CUR(
|
156
|
-
#define BUFFER_AT(
|
157
|
-
#define BUFFER_PTR(
|
158
|
-
#define BUFFER_STR(
|
159
|
-
#define BUFFER_STR_DOWNCASE(
|
160
|
-
#define BUFFER_STR_UPCASE(
|
180
|
+
#define BUFFER_POS(parser) ((parser)->buf_pos)
|
181
|
+
#define BUFFER_LEN(parser) ((parser)->buf_len)
|
182
|
+
#define BUFFER_CUR(parser) ((parser)->buf_ptr[(parser)->buf_pos])
|
183
|
+
#define BUFFER_AT(parser, pos) ((parser)->buf_ptr[pos])
|
184
|
+
#define BUFFER_PTR(parser, pos) ((parser)->buf_ptr + pos)
|
185
|
+
#define BUFFER_STR(parser, pos, len) (rb_obj_freeze(rb_utf8_str_new((parser)->buf_ptr + pos, len)))
|
186
|
+
#define BUFFER_STR_DOWNCASE(parser, pos, len) (rb_obj_freeze(str_downcase(rb_utf8_str_new((parser)->buf_ptr + pos, len))))
|
187
|
+
#define BUFFER_STR_UPCASE(parser, pos, len) (rb_obj_freeze(str_upcase(rb_utf8_str_new((parser)->buf_ptr + pos, len))))
|
161
188
|
|
162
|
-
#define INC_BUFFER_POS(
|
163
|
-
BUFFER_POS(
|
164
|
-
if (BUFFER_POS(
|
189
|
+
#define INC_BUFFER_POS(parser) { \
|
190
|
+
BUFFER_POS(parser)++; \
|
191
|
+
if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser); \
|
165
192
|
}
|
166
193
|
|
167
|
-
#define INC_BUFFER_POS_NO_FILL(
|
194
|
+
#define INC_BUFFER_POS_NO_FILL(parser) BUFFER_POS(parser)++;
|
168
195
|
|
169
|
-
#define INC_BUFFER_POS_UTF8(
|
170
|
-
unsigned char c = BUFFER_CUR(
|
196
|
+
#define INC_BUFFER_POS_UTF8(parser, len) { \
|
197
|
+
unsigned char c = BUFFER_CUR(parser); \
|
171
198
|
if ((c & 0xf0) == 0xf0) { \
|
172
|
-
while (BUFFER_LEN(
|
173
|
-
BUFFER_POS(
|
199
|
+
while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 4) FILL_BUFFER_OR_GOTO_EOF(parser); \
|
200
|
+
BUFFER_POS(parser) += 4; \
|
174
201
|
len += 4; \
|
175
202
|
} \
|
176
203
|
else if ((c & 0xe0) == 0xe0) { \
|
177
|
-
while (BUFFER_LEN(
|
178
|
-
BUFFER_POS(
|
204
|
+
while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 3) FILL_BUFFER_OR_GOTO_EOF(parser); \
|
205
|
+
BUFFER_POS(parser) += 3; \
|
179
206
|
len += 3; \
|
180
207
|
} \
|
181
208
|
else if ((c & 0xc0) == 0xc0) { \
|
182
|
-
while (BUFFER_LEN(
|
183
|
-
BUFFER_POS(
|
209
|
+
while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 2) FILL_BUFFER_OR_GOTO_EOF(parser); \
|
210
|
+
BUFFER_POS(parser) += 2; \
|
184
211
|
len += 2; \
|
185
212
|
} \
|
186
213
|
else { \
|
187
|
-
BUFFER_POS(
|
214
|
+
BUFFER_POS(parser)++; \
|
188
215
|
len ++; \
|
189
|
-
if (BUFFER_POS(
|
216
|
+
if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser); \
|
190
217
|
} \
|
191
218
|
}
|
192
219
|
|
193
|
-
#define INIT_PARSER_STATE(
|
194
|
-
(
|
195
|
-
if (BUFFER_POS(
|
196
|
-
FILL_BUFFER_OR_GOTO_EOF(
|
220
|
+
#define INIT_PARSER_STATE(parser) { \
|
221
|
+
(parser)->buf_len = RSTRING_LEN((parser)->buffer); \
|
222
|
+
if (BUFFER_POS(parser) == BUFFER_LEN(parser)) \
|
223
|
+
FILL_BUFFER_OR_GOTO_EOF(parser) \
|
197
224
|
else \
|
198
|
-
(
|
225
|
+
(parser)->buf_ptr = RSTRING_PTR((parser)->buffer); \
|
199
226
|
}
|
200
227
|
|
201
228
|
#define RAISE_BAD_REQUEST(msg) rb_raise(cError, msg)
|
202
229
|
|
203
|
-
#define SET_HEADER_VALUE_FROM_BUFFER(
|
204
|
-
VALUE value = BUFFER_STR(
|
205
|
-
rb_hash_aset(headers, key, value); \
|
230
|
+
#define SET_HEADER_VALUE_FROM_BUFFER(parser, key, pos, len) { \
|
231
|
+
VALUE value = BUFFER_STR(parser, pos, len); \
|
232
|
+
rb_hash_aset(parser->headers, key, value); \
|
206
233
|
RB_GC_GUARD(value); \
|
207
234
|
}
|
208
235
|
|
209
|
-
#define SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(
|
210
|
-
VALUE value = BUFFER_STR_DOWNCASE(
|
211
|
-
rb_hash_aset(headers, key, value); \
|
236
|
+
#define SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, key, pos, len) { \
|
237
|
+
VALUE value = BUFFER_STR_DOWNCASE(parser, pos, len); \
|
238
|
+
rb_hash_aset(parser->headers, key, value); \
|
212
239
|
RB_GC_GUARD(value); \
|
213
240
|
}
|
214
241
|
|
215
|
-
#define SET_HEADER_UPCASE_VALUE_FROM_BUFFER(
|
216
|
-
VALUE value = BUFFER_STR_UPCASE(
|
217
|
-
rb_hash_aset(headers, key, value); \
|
242
|
+
#define SET_HEADER_UPCASE_VALUE_FROM_BUFFER(parser, key, pos, len) { \
|
243
|
+
VALUE value = BUFFER_STR_UPCASE(parser, pos, len); \
|
244
|
+
rb_hash_aset(parser->headers, key, value); \
|
218
245
|
RB_GC_GUARD(value); \
|
219
246
|
}
|
220
247
|
|
221
|
-
#define
|
222
|
-
|
223
|
-
if (BUFFER_CUR(state) != '\n') goto bad_request; \
|
224
|
-
INC_BUFFER_POS(state); \
|
248
|
+
#define SET_HEADER_VALUE_INT(parser, key, value) { \
|
249
|
+
rb_hash_aset(parser->headers, key, INT2NUM(value)); \
|
225
250
|
}
|
226
251
|
|
227
|
-
#define
|
228
|
-
INC_BUFFER_POS(
|
229
|
-
if (BUFFER_CUR(
|
230
|
-
|
252
|
+
#define CONSUME_CRLF(parser) { \
|
253
|
+
INC_BUFFER_POS(parser); \
|
254
|
+
if (BUFFER_CUR(parser) != '\n') goto bad_request; \
|
255
|
+
INC_BUFFER_POS(parser); \
|
256
|
+
}
|
257
|
+
|
258
|
+
#define CONSUME_CRLF_NO_FILL(parser) { \
|
259
|
+
INC_BUFFER_POS(parser); \
|
260
|
+
if (BUFFER_CUR(parser) != '\n') goto bad_request; \
|
261
|
+
INC_BUFFER_POS_NO_FILL(parser); \
|
231
262
|
}
|
232
263
|
|
233
264
|
#define GLOBAL_STR(v, s) v = rb_str_new_literal(s); rb_global_variable(&v); rb_obj_freeze(v)
|
234
265
|
|
235
|
-
|
236
|
-
|
237
|
-
char *ptr;
|
238
|
-
int len;
|
239
|
-
};
|
266
|
+
// case-insensitive compare
|
267
|
+
#define CMP_CI(parser, down, up) ((BUFFER_CUR(parser) == down) || (BUFFER_CUR(parser) == up))
|
240
268
|
|
241
269
|
////////////////////////////////////////////////////////////////////////////////
|
242
270
|
|
@@ -270,9 +298,9 @@ static inline VALUE parser_io_read(Parser_t *parser, VALUE maxlen, VALUE buf, VA
|
|
270
298
|
return rb_funcall(mPolyphony, ID_backend_read, 5, parser->io, buf, maxlen, Qfalse, buf_pos);
|
271
299
|
case method_backend_recv:
|
272
300
|
return rb_funcall(mPolyphony, ID_backend_recv, 4, parser->io, buf, maxlen, buf_pos);
|
273
|
-
case method_readpartial:
|
301
|
+
case method_readpartial:
|
274
302
|
return rb_funcall(parser-> io, ID_readpartial, 4, maxlen, buf, buf_pos, Qfalse);
|
275
|
-
case method_call:
|
303
|
+
case method_call:
|
276
304
|
return io_call(parser ->io, maxlen, buf, buf_pos);
|
277
305
|
case method_stock_readpartial:
|
278
306
|
return io_stock_readpartial(parser->io, maxlen, buf, buf_pos);
|
@@ -281,37 +309,37 @@ static inline VALUE parser_io_read(Parser_t *parser, VALUE maxlen, VALUE buf, VA
|
|
281
309
|
}
|
282
310
|
}
|
283
311
|
|
284
|
-
static inline int fill_buffer(
|
285
|
-
VALUE ret = parser_io_read(
|
312
|
+
static inline int fill_buffer(Parser_t *parser) {
|
313
|
+
VALUE ret = parser_io_read(parser, NUM_max_headers_read_length, parser->buffer, NUM_buffer_end);
|
286
314
|
if (ret == Qnil) return 0;
|
287
315
|
|
288
|
-
|
289
|
-
int len = RSTRING_LEN(
|
290
|
-
int read_bytes = len -
|
316
|
+
parser->buffer = ret;
|
317
|
+
int len = RSTRING_LEN(parser->buffer);
|
318
|
+
int read_bytes = len - parser->buf_len;
|
291
319
|
if (!read_bytes) return 0;
|
292
|
-
|
293
|
-
|
294
|
-
|
320
|
+
|
321
|
+
parser->buf_ptr = RSTRING_PTR(parser->buffer);
|
322
|
+
parser->buf_len = len;
|
295
323
|
return read_bytes;
|
296
324
|
}
|
297
325
|
|
298
|
-
static inline void buffer_trim(
|
299
|
-
int len = RSTRING_LEN(
|
300
|
-
int pos =
|
326
|
+
static inline void buffer_trim(Parser_t *parser) {
|
327
|
+
int len = RSTRING_LEN(parser->buffer);
|
328
|
+
int pos = parser->buf_pos;
|
301
329
|
int left = len - pos;
|
302
330
|
|
303
331
|
// The buffer is trimmed only if length and position thresholds are passed,
|
304
|
-
// *and* position is past the halfway point.
|
305
|
-
if (len < BUFFER_TRIM_MIN_LEN ||
|
332
|
+
// *and* position is past the halfway point.
|
333
|
+
if (len < BUFFER_TRIM_MIN_LEN ||
|
306
334
|
pos < BUFFER_TRIM_MIN_POS ||
|
307
335
|
left >= pos) return;
|
308
336
|
|
309
337
|
if (left > 0) {
|
310
|
-
char *ptr = RSTRING_PTR(
|
338
|
+
char *ptr = RSTRING_PTR(parser->buffer);
|
311
339
|
memcpy(ptr, ptr + pos, left);
|
312
340
|
}
|
313
|
-
rb_str_set_len(
|
314
|
-
|
341
|
+
rb_str_set_len(parser->buffer, left);
|
342
|
+
parser->buf_pos = 0;
|
315
343
|
}
|
316
344
|
|
317
345
|
static inline void str_append_from_buffer(VALUE str, char *ptr, int len) {
|
@@ -323,28 +351,28 @@ static inline void str_append_from_buffer(VALUE str, char *ptr, int len) {
|
|
323
351
|
|
324
352
|
////////////////////////////////////////////////////////////////////////////////
|
325
353
|
|
326
|
-
static inline int
|
327
|
-
int pos = BUFFER_POS(
|
354
|
+
static inline int parse_request_line_method(Parser_t *parser) {
|
355
|
+
int pos = BUFFER_POS(parser);
|
328
356
|
int len = 0;
|
329
357
|
|
330
358
|
while (1) {
|
331
|
-
switch (BUFFER_CUR(
|
359
|
+
switch (BUFFER_CUR(parser)) {
|
332
360
|
case ' ':
|
333
361
|
if (len < 1 || len > MAX_METHOD_LENGTH) goto bad_request;
|
334
|
-
INC_BUFFER_POS(
|
362
|
+
INC_BUFFER_POS(parser);
|
335
363
|
goto done;
|
336
364
|
case '\r':
|
337
365
|
case '\n':
|
338
366
|
goto bad_request;
|
339
367
|
default:
|
340
|
-
INC_BUFFER_POS(
|
368
|
+
INC_BUFFER_POS(parser);
|
341
369
|
len++;
|
342
|
-
// INC_BUFFER_POS_UTF8(
|
370
|
+
// INC_BUFFER_POS_UTF8(parser, len);
|
343
371
|
if (len > MAX_METHOD_LENGTH) goto bad_request;
|
344
372
|
}
|
345
373
|
}
|
346
374
|
done:
|
347
|
-
SET_HEADER_UPCASE_VALUE_FROM_BUFFER(
|
375
|
+
SET_HEADER_UPCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_method, pos, len);
|
348
376
|
return 1;
|
349
377
|
bad_request:
|
350
378
|
RAISE_BAD_REQUEST("Invalid method");
|
@@ -352,28 +380,28 @@ eof:
|
|
352
380
|
return 0;
|
353
381
|
}
|
354
382
|
|
355
|
-
static int
|
356
|
-
while (BUFFER_CUR(
|
357
|
-
int pos = BUFFER_POS(
|
383
|
+
static int parse_request_line_target(Parser_t *parser) {
|
384
|
+
while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
|
385
|
+
int pos = BUFFER_POS(parser);
|
358
386
|
int len = 0;
|
359
387
|
while (1) {
|
360
|
-
switch (BUFFER_CUR(
|
388
|
+
switch (BUFFER_CUR(parser)) {
|
361
389
|
case ' ':
|
362
390
|
if (len < 1 || len > MAX_PATH_LENGTH) goto bad_request;
|
363
|
-
INC_BUFFER_POS(
|
391
|
+
INC_BUFFER_POS(parser);
|
364
392
|
goto done;
|
365
393
|
case '\r':
|
366
394
|
case '\n':
|
367
395
|
goto bad_request;
|
368
396
|
default:
|
369
|
-
INC_BUFFER_POS(
|
397
|
+
INC_BUFFER_POS(parser);
|
370
398
|
len++;
|
371
|
-
// INC_BUFFER_POS_UTF8(
|
399
|
+
// INC_BUFFER_POS_UTF8(parser, len);
|
372
400
|
if (len > MAX_PATH_LENGTH) goto bad_request;
|
373
401
|
}
|
374
402
|
}
|
375
403
|
done:
|
376
|
-
SET_HEADER_VALUE_FROM_BUFFER(
|
404
|
+
SET_HEADER_VALUE_FROM_BUFFER(parser, STR_pseudo_path, pos, len);
|
377
405
|
return 1;
|
378
406
|
bad_request:
|
379
407
|
RAISE_BAD_REQUEST("Invalid request target");
|
@@ -381,34 +409,31 @@ eof:
|
|
381
409
|
return 0;
|
382
410
|
}
|
383
411
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
static int parse_protocol(struct parser_state *state, VALUE headers) {
|
388
|
-
while (BUFFER_CUR(state) == ' ') INC_BUFFER_POS(state);
|
389
|
-
int pos = BUFFER_POS(state);
|
412
|
+
static int parse_request_line_protocol(Parser_t *parser) {
|
413
|
+
while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
|
414
|
+
int pos = BUFFER_POS(parser);
|
390
415
|
int len = 0;
|
391
416
|
|
392
|
-
if (CMP_CI(
|
393
|
-
if (CMP_CI(
|
394
|
-
if (CMP_CI(
|
395
|
-
if (CMP_CI(
|
396
|
-
if (BUFFER_CUR(
|
397
|
-
if (BUFFER_CUR(
|
417
|
+
if (CMP_CI(parser, 'H', 'h')) INC_BUFFER_POS(parser) else goto bad_request;
|
418
|
+
if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
|
419
|
+
if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
|
420
|
+
if (CMP_CI(parser, 'P', 'p')) INC_BUFFER_POS(parser) else goto bad_request;
|
421
|
+
if (BUFFER_CUR(parser) == '/') INC_BUFFER_POS(parser) else goto bad_request;
|
422
|
+
if (BUFFER_CUR(parser) == '1') INC_BUFFER_POS(parser) else goto bad_request;
|
398
423
|
len = 6;
|
399
424
|
while (1) {
|
400
|
-
switch (BUFFER_CUR(
|
425
|
+
switch (BUFFER_CUR(parser)) {
|
401
426
|
case '\r':
|
402
|
-
CONSUME_CRLF(
|
427
|
+
CONSUME_CRLF(parser);
|
403
428
|
goto done;
|
404
429
|
case '\n':
|
405
|
-
INC_BUFFER_POS(
|
430
|
+
INC_BUFFER_POS(parser);
|
406
431
|
goto done;
|
407
432
|
case '.':
|
408
|
-
INC_BUFFER_POS(
|
409
|
-
char c = BUFFER_CUR(
|
433
|
+
INC_BUFFER_POS(parser);
|
434
|
+
char c = BUFFER_CUR(parser);
|
410
435
|
if (c == '0' || c == '1') {
|
411
|
-
INC_BUFFER_POS(
|
436
|
+
INC_BUFFER_POS(parser);
|
412
437
|
len += 2;
|
413
438
|
continue;
|
414
439
|
}
|
@@ -419,7 +444,7 @@ static int parse_protocol(struct parser_state *state, VALUE headers) {
|
|
419
444
|
}
|
420
445
|
done:
|
421
446
|
if (len < 6 || len > 8) goto bad_request;
|
422
|
-
SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(
|
447
|
+
SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_protocol, pos, len);
|
423
448
|
return 1;
|
424
449
|
bad_request:
|
425
450
|
RAISE_BAD_REQUEST("Invalid protocol");
|
@@ -427,48 +452,159 @@ eof:
|
|
427
452
|
return 0;
|
428
453
|
}
|
429
454
|
|
430
|
-
int parse_request_line(
|
431
|
-
if (!
|
432
|
-
if (!
|
433
|
-
if (!
|
455
|
+
static inline int parse_request_line(Parser_t *parser) {
|
456
|
+
if (!parse_request_line_method(parser)) goto eof;
|
457
|
+
if (!parse_request_line_target(parser)) goto eof;
|
458
|
+
if (!parse_request_line_protocol(parser)) goto eof;
|
459
|
+
|
460
|
+
return 1;
|
461
|
+
eof:
|
462
|
+
return 0;
|
463
|
+
}
|
464
|
+
|
465
|
+
static inline int parse_status_line_protocol(Parser_t *parser) {
|
466
|
+
int pos = BUFFER_POS(parser);
|
467
|
+
int len = 0;
|
468
|
+
|
469
|
+
if (CMP_CI(parser, 'H', 'h')) INC_BUFFER_POS(parser) else goto bad_request;
|
470
|
+
if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
|
471
|
+
if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
|
472
|
+
if (CMP_CI(parser, 'P', 'p')) INC_BUFFER_POS(parser) else goto bad_request;
|
473
|
+
if (BUFFER_CUR(parser) == '/') INC_BUFFER_POS(parser) else goto bad_request;
|
474
|
+
if (BUFFER_CUR(parser) == '1') INC_BUFFER_POS(parser) else goto bad_request;
|
475
|
+
len = 6;
|
476
|
+
while (1) {
|
477
|
+
switch (BUFFER_CUR(parser)) {
|
478
|
+
case '.':
|
479
|
+
INC_BUFFER_POS(parser);
|
480
|
+
char c = BUFFER_CUR(parser);
|
481
|
+
if (c == '0' || c == '1') {
|
482
|
+
INC_BUFFER_POS(parser);
|
483
|
+
len += 2;
|
484
|
+
continue;
|
485
|
+
}
|
486
|
+
goto bad_request;
|
487
|
+
case ' ':
|
488
|
+
INC_BUFFER_POS(parser);
|
489
|
+
goto done;
|
490
|
+
default:
|
491
|
+
goto bad_request;
|
492
|
+
}
|
493
|
+
}
|
494
|
+
done:
|
495
|
+
if (len < 6 || len > 8) goto bad_request;
|
496
|
+
SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_protocol, pos, len);
|
497
|
+
return 1;
|
498
|
+
bad_request:
|
499
|
+
RAISE_BAD_REQUEST("Invalid protocol");
|
500
|
+
eof:
|
501
|
+
return 0;
|
502
|
+
}
|
503
|
+
|
504
|
+
static inline int parse_status_line_status(Parser_t *parser) {
|
505
|
+
while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
|
506
|
+
int len = 0;
|
507
|
+
int status = 0;
|
508
|
+
while (1) {
|
509
|
+
if (len > 4) goto bad_request;
|
510
|
+
|
511
|
+
char c = BUFFER_CUR(parser);
|
512
|
+
if (c >= '0' && c <= '9') {
|
513
|
+
status = status * 10 + (c - '0');
|
514
|
+
len += 1;
|
515
|
+
INC_BUFFER_POS(parser);
|
516
|
+
continue;
|
517
|
+
}
|
518
|
+
switch (c) {
|
519
|
+
case ' ':
|
520
|
+
INC_BUFFER_POS(parser);
|
521
|
+
goto done;
|
522
|
+
case '\r':
|
523
|
+
case '\n':
|
524
|
+
goto done;
|
525
|
+
default:
|
526
|
+
goto bad_request;
|
527
|
+
}
|
528
|
+
}
|
529
|
+
done:
|
530
|
+
SET_HEADER_VALUE_INT(parser, STR_pseudo_status, status);
|
531
|
+
return 1;
|
532
|
+
bad_request:
|
533
|
+
RAISE_BAD_REQUEST("Invalid response status");
|
534
|
+
eof:
|
535
|
+
return 0;
|
536
|
+
}
|
537
|
+
|
538
|
+
static inline int parse_status_line_status_message(Parser_t *parser) {
|
539
|
+
while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
|
540
|
+
int pos = BUFFER_POS(parser);
|
541
|
+
int len = 0;
|
542
|
+
while (1) {
|
543
|
+
switch (BUFFER_CUR(parser)) {
|
544
|
+
case '\r':
|
545
|
+
CONSUME_CRLF(parser);
|
546
|
+
goto done;
|
547
|
+
case '\n':
|
548
|
+
INC_BUFFER_POS(parser);
|
549
|
+
goto done;
|
550
|
+
default:
|
551
|
+
INC_BUFFER_POS(parser);
|
552
|
+
len++;
|
553
|
+
if (len > MAX_STATUS_MESSAGE_LENGTH) goto bad_request;
|
554
|
+
}
|
555
|
+
}
|
556
|
+
done:
|
557
|
+
SET_HEADER_VALUE_FROM_BUFFER(parser, STR_pseudo_status_message, pos, len);
|
558
|
+
return 1;
|
559
|
+
bad_request:
|
560
|
+
RAISE_BAD_REQUEST("Invalid request target");
|
561
|
+
eof:
|
562
|
+
return 0;
|
563
|
+
}
|
564
|
+
|
565
|
+
|
566
|
+
static inline int parse_status_line(Parser_t *parser) {
|
567
|
+
if (!parse_status_line_protocol(parser)) goto eof;
|
568
|
+
if (!parse_status_line_status(parser)) goto eof;
|
569
|
+
if (!parse_status_line_status_message(parser)) goto eof;
|
434
570
|
|
435
571
|
return 1;
|
436
572
|
eof:
|
437
573
|
return 0;
|
438
574
|
}
|
439
575
|
|
440
|
-
static inline int parse_header_key(
|
441
|
-
int pos = BUFFER_POS(
|
576
|
+
static inline int parse_header_key(Parser_t *parser, VALUE *key) {
|
577
|
+
int pos = BUFFER_POS(parser);
|
442
578
|
int len = 0;
|
443
579
|
|
444
580
|
while (1) {
|
445
|
-
switch (BUFFER_CUR(
|
581
|
+
switch (BUFFER_CUR(parser)) {
|
446
582
|
case ' ':
|
447
583
|
goto bad_request;
|
448
584
|
case ':':
|
449
585
|
if (len < 1 || len > MAX_HEADER_KEY_LENGTH)
|
450
586
|
goto bad_request;
|
451
|
-
INC_BUFFER_POS(
|
587
|
+
INC_BUFFER_POS(parser);
|
452
588
|
goto done;
|
453
589
|
case '\r':
|
454
|
-
if (BUFFER_POS(
|
455
|
-
CONSUME_CRLF_NO_FILL(
|
590
|
+
if (BUFFER_POS(parser) > pos) goto bad_request;
|
591
|
+
CONSUME_CRLF_NO_FILL(parser);
|
456
592
|
goto done;
|
457
593
|
case '\n':
|
458
|
-
if (BUFFER_POS(
|
594
|
+
if (BUFFER_POS(parser) > pos) goto bad_request;
|
459
595
|
|
460
|
-
INC_BUFFER_POS_NO_FILL(
|
596
|
+
INC_BUFFER_POS_NO_FILL(parser);
|
461
597
|
goto done;
|
462
598
|
default:
|
463
|
-
INC_BUFFER_POS(
|
599
|
+
INC_BUFFER_POS(parser);
|
464
600
|
len++;
|
465
|
-
// INC_BUFFER_POS_UTF8(
|
601
|
+
// INC_BUFFER_POS_UTF8(parser, len);
|
466
602
|
if (len > MAX_HEADER_KEY_LENGTH) goto bad_request;
|
467
603
|
}
|
468
604
|
}
|
469
605
|
done:
|
470
606
|
if (len == 0) return -1;
|
471
|
-
(*key) = BUFFER_STR_DOWNCASE(
|
607
|
+
(*key) = BUFFER_STR_DOWNCASE(parser, pos, len);
|
472
608
|
return 1;
|
473
609
|
bad_request:
|
474
610
|
RAISE_BAD_REQUEST("Invalid header key");
|
@@ -476,28 +612,28 @@ eof:
|
|
476
612
|
return 0;
|
477
613
|
}
|
478
614
|
|
479
|
-
static inline int parse_header_value(
|
480
|
-
while (BUFFER_CUR(
|
615
|
+
static inline int parse_header_value(Parser_t *parser, VALUE *value) {
|
616
|
+
while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
|
481
617
|
|
482
|
-
int pos = BUFFER_POS(
|
618
|
+
int pos = BUFFER_POS(parser);
|
483
619
|
int len = 0;
|
484
620
|
|
485
621
|
while (1) {
|
486
|
-
switch (BUFFER_CUR(
|
622
|
+
switch (BUFFER_CUR(parser)) {
|
487
623
|
case '\r':
|
488
|
-
CONSUME_CRLF(
|
624
|
+
CONSUME_CRLF(parser);
|
489
625
|
goto done;
|
490
626
|
case '\n':
|
491
|
-
INC_BUFFER_POS(
|
627
|
+
INC_BUFFER_POS(parser);
|
492
628
|
goto done;
|
493
629
|
default:
|
494
|
-
INC_BUFFER_POS_UTF8(
|
630
|
+
INC_BUFFER_POS_UTF8(parser, len);
|
495
631
|
if (len > MAX_HEADER_VALUE_LENGTH) goto bad_request;
|
496
632
|
}
|
497
633
|
}
|
498
634
|
done:
|
499
635
|
if (len < 1 || len > MAX_HEADER_VALUE_LENGTH) goto bad_request;
|
500
|
-
(*value) = BUFFER_STR(
|
636
|
+
(*value) = BUFFER_STR(parser, pos, len);
|
501
637
|
return 1;
|
502
638
|
bad_request:
|
503
639
|
RAISE_BAD_REQUEST("Invalid header value");
|
@@ -505,27 +641,27 @@ eof:
|
|
505
641
|
return 0;
|
506
642
|
}
|
507
643
|
|
508
|
-
static inline int parse_header(
|
644
|
+
static inline int parse_header(Parser_t *parser) {
|
509
645
|
VALUE key, value;
|
510
646
|
|
511
|
-
switch (parse_header_key(
|
647
|
+
switch (parse_header_key(parser, &key)) {
|
512
648
|
case -1: return -1;
|
513
649
|
case 0: goto eof;
|
514
650
|
}
|
515
651
|
|
516
|
-
if (!parse_header_value(
|
652
|
+
if (!parse_header_value(parser, &value)) goto eof;
|
517
653
|
|
518
|
-
VALUE existing = rb_hash_aref(headers, key);
|
654
|
+
VALUE existing = rb_hash_aref(parser->headers, key);
|
519
655
|
if (existing != Qnil) {
|
520
656
|
if (TYPE(existing) != T_ARRAY) {
|
521
657
|
existing = rb_ary_new3(2, existing, value);
|
522
|
-
rb_hash_aset(headers, key, existing);
|
658
|
+
rb_hash_aset(parser->headers, key, existing);
|
523
659
|
}
|
524
660
|
else
|
525
661
|
rb_ary_push(existing, value);
|
526
662
|
}
|
527
663
|
else
|
528
|
-
rb_hash_aset(headers, key, value);
|
664
|
+
rb_hash_aset(parser->headers, key, value);
|
529
665
|
|
530
666
|
RB_GC_GUARD(existing);
|
531
667
|
RB_GC_GUARD(key);
|
@@ -536,36 +672,41 @@ eof:
|
|
536
672
|
}
|
537
673
|
|
538
674
|
VALUE Parser_parse_headers(VALUE self) {
|
539
|
-
|
540
|
-
GetParser(self,
|
541
|
-
|
675
|
+
Parser_t *parser;
|
676
|
+
GetParser(self, parser);
|
677
|
+
parser->headers = rb_hash_new();
|
542
678
|
|
543
|
-
buffer_trim(
|
544
|
-
int initial_pos =
|
545
|
-
INIT_PARSER_STATE(
|
546
|
-
|
679
|
+
buffer_trim(parser);
|
680
|
+
int initial_pos = parser->buf_pos;
|
681
|
+
INIT_PARSER_STATE(parser);
|
682
|
+
parser->current_request_rx = 0;
|
547
683
|
|
548
|
-
if (
|
684
|
+
if (parser->mode == mode_server) {
|
685
|
+
if (!parse_request_line(parser)) goto eof;
|
686
|
+
}
|
687
|
+
else {
|
688
|
+
if (!parse_status_line(parser)) goto eof;
|
689
|
+
}
|
549
690
|
|
550
691
|
int header_count = 0;
|
551
692
|
while (1) {
|
552
693
|
if (header_count > MAX_HEADER_COUNT) RAISE_BAD_REQUEST("Too many headers");
|
553
|
-
switch (parse_header(
|
694
|
+
switch (parse_header(parser)) {
|
554
695
|
case -1: goto done; // empty header => end of headers
|
555
696
|
case 0: goto eof;
|
556
697
|
}
|
557
698
|
header_count++;
|
558
699
|
}
|
559
700
|
eof:
|
560
|
-
|
701
|
+
parser->headers = Qnil;
|
561
702
|
done:
|
562
|
-
|
563
|
-
int read_bytes = BUFFER_POS(
|
703
|
+
parser->body_read_mode = BODY_READ_MODE_UNKNOWN;
|
704
|
+
int read_bytes = BUFFER_POS(parser) - initial_pos;
|
564
705
|
|
565
|
-
|
566
|
-
if (
|
567
|
-
rb_hash_aset(
|
568
|
-
return
|
706
|
+
parser->current_request_rx += read_bytes;
|
707
|
+
if (parser->headers != Qnil)
|
708
|
+
rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(read_bytes));
|
709
|
+
return parser->headers;
|
569
710
|
}
|
570
711
|
|
571
712
|
////////////////////////////////////////////////////////////////////////////////
|
@@ -594,13 +735,13 @@ VALUE read_body_with_content_length(Parser_t *parser, int read_entire_body, int
|
|
594
735
|
VALUE body = Qnil;
|
595
736
|
|
596
737
|
int len = RSTRING_LEN(parser->buffer);
|
597
|
-
int pos = parser
|
738
|
+
int pos = BUFFER_POS(parser);
|
598
739
|
|
599
740
|
if (pos < len) {
|
600
741
|
int available = len - pos;
|
601
742
|
if (available > parser->body_left) available = parser->body_left;
|
602
743
|
body = rb_str_new(RSTRING_PTR(parser->buffer) + pos, available);
|
603
|
-
parser
|
744
|
+
BUFFER_POS(parser) += available;
|
604
745
|
parser->current_request_rx += available;
|
605
746
|
parser->body_left -= available;
|
606
747
|
if (!parser->body_left) parser->request_completed = 1;
|
@@ -610,7 +751,7 @@ VALUE read_body_with_content_length(Parser_t *parser, int read_entire_body, int
|
|
610
751
|
len = 0;
|
611
752
|
}
|
612
753
|
if (buffered_only) return body;
|
613
|
-
|
754
|
+
|
614
755
|
while (parser->body_left) {
|
615
756
|
int maxlen = parser->body_left <= MAX_BODY_READ_LENGTH ? parser->body_left : MAX_BODY_READ_LENGTH;
|
616
757
|
VALUE tmp_buf = parser_io_read(parser, INT2NUM(maxlen), Qnil, NUM_buffer_start);
|
@@ -639,34 +780,34 @@ int chunked_encoding_p(VALUE transfer_encoding) {
|
|
639
780
|
return rb_funcall(str_downcase(transfer_encoding), ID_eq, 1, STR_chunked) == Qtrue;
|
640
781
|
}
|
641
782
|
|
642
|
-
int parse_chunk_size(
|
783
|
+
int parse_chunk_size(Parser_t *parser, int *chunk_size) {
|
643
784
|
int len = 0;
|
644
785
|
int value = 0;
|
645
|
-
int initial_pos = BUFFER_POS(
|
786
|
+
int initial_pos = BUFFER_POS(parser);
|
646
787
|
|
647
788
|
while (1) {
|
648
|
-
char c = BUFFER_CUR(
|
789
|
+
char c = BUFFER_CUR(parser);
|
649
790
|
if ((c >= '0') && (c <= '9')) value = (value << 4) + (c - '0');
|
650
791
|
else if ((c >= 'a') && (c <= 'f')) value = (value << 4) + (c - 'a' + 10);
|
651
792
|
else if ((c >= 'A') && (c <= 'F')) value = (value << 4) + (c - 'A' + 10);
|
652
793
|
else switch (c) {
|
653
794
|
case '\r':
|
654
|
-
CONSUME_CRLF_NO_FILL(
|
795
|
+
CONSUME_CRLF_NO_FILL(parser);
|
655
796
|
goto done;
|
656
797
|
case '\n':
|
657
|
-
INC_BUFFER_POS_NO_FILL(
|
798
|
+
INC_BUFFER_POS_NO_FILL(parser);
|
658
799
|
goto done;
|
659
800
|
default:
|
660
801
|
goto bad_request;
|
661
802
|
}
|
662
|
-
INC_BUFFER_POS(
|
803
|
+
INC_BUFFER_POS(parser);
|
663
804
|
len++;
|
664
805
|
if (len >= MAX_CHUNKED_ENCODING_CHUNK_SIZE_LENGTH) goto bad_request;
|
665
806
|
}
|
666
807
|
done:
|
667
808
|
if (len == 0) goto bad_request;
|
668
809
|
(*chunk_size) = value;
|
669
|
-
|
810
|
+
parser->current_request_rx += BUFFER_POS(parser) - initial_pos;
|
670
811
|
return 1;
|
671
812
|
bad_request:
|
672
813
|
RAISE_BAD_REQUEST("Invalid chunk size");
|
@@ -674,20 +815,20 @@ eof:
|
|
674
815
|
return 0;
|
675
816
|
}
|
676
817
|
|
677
|
-
int read_body_chunk_with_chunked_encoding(
|
678
|
-
int len = RSTRING_LEN(
|
679
|
-
int pos =
|
818
|
+
int read_body_chunk_with_chunked_encoding(Parser_t *parser, VALUE *body, int chunk_size, int buffered_only) {
|
819
|
+
int len = RSTRING_LEN(parser->buffer);
|
820
|
+
int pos = BUFFER_POS(parser);
|
680
821
|
int left = chunk_size;
|
681
822
|
|
682
823
|
if (pos < len) {
|
683
824
|
int available = len - pos;
|
684
825
|
if (available > left) available = left;
|
685
826
|
if (*body != Qnil)
|
686
|
-
str_append_from_buffer(*body, RSTRING_PTR(
|
827
|
+
str_append_from_buffer(*body, RSTRING_PTR(parser->buffer) + pos, available);
|
687
828
|
else
|
688
|
-
*body = rb_str_new(RSTRING_PTR(
|
689
|
-
|
690
|
-
|
829
|
+
*body = rb_str_new(RSTRING_PTR(parser->buffer) + pos, available);
|
830
|
+
BUFFER_POS(parser) += available;
|
831
|
+
parser->current_request_rx += available;
|
691
832
|
left -= available;
|
692
833
|
}
|
693
834
|
if (buffered_only) return 1;
|
@@ -695,14 +836,14 @@ int read_body_chunk_with_chunked_encoding(struct parser_state *state, VALUE *bod
|
|
695
836
|
while (left) {
|
696
837
|
int maxlen = left <= MAX_BODY_READ_LENGTH ? left : MAX_BODY_READ_LENGTH;
|
697
838
|
|
698
|
-
VALUE tmp_buf = parser_io_read(
|
839
|
+
VALUE tmp_buf = parser_io_read(parser, INT2NUM(maxlen), Qnil, NUM_buffer_start);
|
699
840
|
if (tmp_buf == Qnil) goto eof;
|
700
841
|
if (*body != Qnil)
|
701
842
|
rb_str_append(*body, tmp_buf);
|
702
843
|
else
|
703
844
|
*body = tmp_buf;
|
704
845
|
int read_bytes = RSTRING_LEN(tmp_buf);
|
705
|
-
|
846
|
+
parser->current_request_rx += read_bytes;
|
706
847
|
left -= read_bytes;
|
707
848
|
RB_GC_GUARD(tmp_buf);
|
708
849
|
}
|
@@ -711,46 +852,44 @@ eof:
|
|
711
852
|
return 0;
|
712
853
|
}
|
713
854
|
|
714
|
-
static inline int parse_chunk_postfix(
|
715
|
-
int initial_pos = BUFFER_POS(
|
716
|
-
if (initial_pos == BUFFER_LEN(
|
717
|
-
switch (BUFFER_CUR(
|
855
|
+
static inline int parse_chunk_postfix(Parser_t *parser) {
|
856
|
+
int initial_pos = BUFFER_POS(parser);
|
857
|
+
if (initial_pos == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser);
|
858
|
+
switch (BUFFER_CUR(parser)) {
|
718
859
|
case '\r':
|
719
|
-
CONSUME_CRLF_NO_FILL(
|
860
|
+
CONSUME_CRLF_NO_FILL(parser);
|
720
861
|
goto done;
|
721
862
|
case '\n':
|
722
|
-
INC_BUFFER_POS_NO_FILL(
|
863
|
+
INC_BUFFER_POS_NO_FILL(parser);
|
723
864
|
goto done;
|
724
865
|
default:
|
725
866
|
goto bad_request;
|
726
867
|
}
|
727
868
|
done:
|
728
|
-
|
869
|
+
parser->current_request_rx += BUFFER_POS(parser) - initial_pos;
|
729
870
|
return 1;
|
730
871
|
bad_request:
|
731
|
-
RAISE_BAD_REQUEST("Invalid
|
872
|
+
RAISE_BAD_REQUEST("Invalid chunk");
|
732
873
|
eof:
|
733
874
|
return 0;
|
734
875
|
}
|
735
876
|
|
736
877
|
VALUE read_body_with_chunked_encoding(Parser_t *parser, int read_entire_body, int buffered_only) {
|
737
|
-
|
738
|
-
|
739
|
-
buffer_trim(&state);
|
740
|
-
INIT_PARSER_STATE(&state);
|
878
|
+
buffer_trim(parser);
|
879
|
+
INIT_PARSER_STATE(parser);
|
741
880
|
VALUE body = Qnil;
|
742
881
|
|
743
882
|
while (1) {
|
744
883
|
int chunk_size = 0;
|
745
|
-
if (BUFFER_POS(
|
746
|
-
if (!parse_chunk_size(
|
747
|
-
|
884
|
+
if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser);
|
885
|
+
if (!parse_chunk_size(parser, &chunk_size)) goto bad_request;
|
886
|
+
|
748
887
|
if (chunk_size) {
|
749
|
-
if (!read_body_chunk_with_chunked_encoding(
|
888
|
+
if (!read_body_chunk_with_chunked_encoding(parser, &body, chunk_size, buffered_only)) goto bad_request;
|
750
889
|
}
|
751
890
|
else parser->request_completed = 1;
|
752
891
|
|
753
|
-
if (!parse_chunk_postfix(
|
892
|
+
if (!parse_chunk_postfix(parser)) goto bad_request;
|
754
893
|
if (!chunk_size || !read_entire_body) goto done;
|
755
894
|
}
|
756
895
|
bad_request:
|
@@ -758,7 +897,7 @@ bad_request:
|
|
758
897
|
eof:
|
759
898
|
RAISE_BAD_REQUEST("Incomplete request body");
|
760
899
|
done:
|
761
|
-
rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(
|
900
|
+
rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(parser->current_request_rx));
|
762
901
|
RB_GC_GUARD(body);
|
763
902
|
return body;
|
764
903
|
}
|
@@ -772,7 +911,7 @@ static inline void detect_body_read_mode(Parser_t *parser) {
|
|
772
911
|
parser->request_completed = 0;
|
773
912
|
return;
|
774
913
|
}
|
775
|
-
|
914
|
+
|
776
915
|
VALUE transfer_encoding = rb_hash_aref(parser->headers, STR_transfer_encoding);
|
777
916
|
if (chunked_encoding_p(transfer_encoding)) {
|
778
917
|
parser->body_read_mode = BODY_READ_MODE_CHUNKED;
|
@@ -826,7 +965,7 @@ void Init_H1P() {
|
|
826
965
|
rb_gc_register_mark_object(cError);
|
827
966
|
|
828
967
|
// backend methods
|
829
|
-
rb_define_method(cParser, "initialize", Parser_initialize,
|
968
|
+
rb_define_method(cParser, "initialize", Parser_initialize, 2);
|
830
969
|
rb_define_method(cParser, "parse_headers", Parser_parse_headers, 0);
|
831
970
|
rb_define_method(cParser, "read_body", Parser_read_body, 0);
|
832
971
|
rb_define_method(cParser, "read_body_chunk", Parser_read_body_chunk, 1);
|
@@ -849,18 +988,23 @@ void Init_H1P() {
|
|
849
988
|
NUM_buffer_start = INT2NUM(0);
|
850
989
|
NUM_buffer_end = INT2NUM(-1);
|
851
990
|
|
852
|
-
GLOBAL_STR(STR_pseudo_method,
|
853
|
-
GLOBAL_STR(STR_pseudo_path,
|
854
|
-
GLOBAL_STR(STR_pseudo_protocol,
|
855
|
-
GLOBAL_STR(STR_pseudo_rx,
|
991
|
+
GLOBAL_STR(STR_pseudo_method, ":method");
|
992
|
+
GLOBAL_STR(STR_pseudo_path, ":path");
|
993
|
+
GLOBAL_STR(STR_pseudo_protocol, ":protocol");
|
994
|
+
GLOBAL_STR(STR_pseudo_rx, ":rx");
|
995
|
+
GLOBAL_STR(STR_pseudo_status, ":status");
|
996
|
+
GLOBAL_STR(STR_pseudo_status_message, ":status_message");
|
856
997
|
|
857
|
-
GLOBAL_STR(STR_chunked,
|
858
|
-
GLOBAL_STR(STR_content_length,
|
859
|
-
GLOBAL_STR(STR_transfer_encoding,
|
998
|
+
GLOBAL_STR(STR_chunked, "chunked");
|
999
|
+
GLOBAL_STR(STR_content_length, "content-length");
|
1000
|
+
GLOBAL_STR(STR_transfer_encoding, "transfer-encoding");
|
860
1001
|
|
861
1002
|
SYM_backend_read = ID2SYM(ID_backend_read);
|
862
1003
|
SYM_backend_recv = ID2SYM(ID_backend_recv);
|
863
1004
|
SYM_stock_readpartial = ID2SYM(rb_intern("stock_readpartial"));
|
1005
|
+
|
1006
|
+
SYM_client = ID2SYM(rb_intern("client"));
|
1007
|
+
SYM_server = ID2SYM(rb_intern("server"));
|
864
1008
|
|
865
1009
|
rb_global_variable(&mH1P);
|
866
1010
|
}
|