unicorn 3.6.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/.manifest +13 -0
- data/ChangeLog +783 -1
- data/DESIGN +0 -8
- data/Documentation/GNUmakefile +1 -1
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -2
- data/HACKING +11 -0
- data/KNOWN_ISSUES +2 -2
- data/LATEST +24 -24
- data/Links +53 -0
- data/NEWS +66 -0
- data/PHILOSOPHY +49 -49
- data/Sandbox +13 -4
- data/TODO +0 -2
- data/TUNING +31 -9
- data/bin/unicorn +2 -1
- data/bin/unicorn_rails +2 -1
- data/examples/big_app_gc.rb +2 -33
- data/examples/nginx.conf +17 -4
- data/ext/unicorn_http/ext_help.h +16 -0
- data/ext/unicorn_http/extconf.rb +1 -0
- data/ext/unicorn_http/global_variables.h +9 -3
- data/ext/unicorn_http/unicorn_http.c +357 -259
- data/ext/unicorn_http/unicorn_http.rl +148 -50
- data/lib/unicorn/configurator.rb +36 -8
- data/lib/unicorn/const.rb +5 -3
- data/lib/unicorn/http_request.rb +1 -3
- data/lib/unicorn/http_server.rb +82 -95
- data/lib/unicorn/oob_gc.rb +61 -50
- data/lib/unicorn/socket_helper.rb +23 -8
- data/lib/unicorn/worker.rb +45 -4
- data/lib/unicorn.rb +8 -6
- data/script/isolate_for_tests +4 -2
- data/t/broken-app.ru +12 -0
- data/t/heartbeat-timeout.ru +12 -0
- data/t/oob_gc.ru +21 -0
- data/t/oob_gc_path.ru +21 -0
- data/t/t0001-reload-bad-config.sh +1 -0
- data/t/t0002-parser-error.sh +64 -1
- data/t/t0004-heartbeat-timeout.sh +69 -0
- data/t/t0009-broken-app.sh +56 -0
- data/t/t0019-max_header_len.sh +49 -0
- data/t/t0020-at_exit-handler.sh +49 -0
- data/t/t9001-oob_gc.sh +47 -0
- data/t/t9002-oob_gc-path.sh +75 -0
- data/test/benchmark/stack.ru +8 -0
- data/test/unit/test_droplet.rb +28 -0
- data/test/unit/test_http_parser.rb +60 -4
- data/test/unit/test_http_parser_ng.rb +54 -0
- data/test/unit/test_response.rb +1 -1
- data/test/unit/test_server.rb +1 -1
- data/test/unit/test_signals.rb +1 -1
- data/test/unit/test_socket_helper.rb +8 -0
- data/test/unit/test_upload.rb +1 -1
- data/unicorn.gemspec +3 -2
- metadata +44 -16
@@ -84,6 +84,14 @@ static VALUE xftrust(VALUE self)
|
|
84
84
|
return trust_x_forward;
|
85
85
|
}
|
86
86
|
|
87
|
+
static size_t MAX_HEADER_LEN = 1024 * (80 + 32); /* same as Mongrel */
|
88
|
+
|
89
|
+
/* this is only intended for use with Rainbows! */
|
90
|
+
static VALUE set_maxhdrlen(VALUE self, VALUE len)
|
91
|
+
{
|
92
|
+
return SIZET2NUM(MAX_HEADER_LEN = NUM2SIZET(len));
|
93
|
+
}
|
94
|
+
|
87
95
|
/* keep this small for Rainbows! since every client has one */
|
88
96
|
struct http_parser {
|
89
97
|
int cs; /* Ragel internal state */
|
@@ -108,17 +116,17 @@ struct http_parser {
|
|
108
116
|
} len;
|
109
117
|
};
|
110
118
|
|
111
|
-
static ID id_clear;
|
119
|
+
static ID id_clear, id_set_backtrace;
|
112
120
|
|
113
121
|
static void finalize_header(struct http_parser *hp);
|
114
122
|
|
115
|
-
static void
|
123
|
+
static void parser_raise(VALUE klass, const char *msg)
|
116
124
|
{
|
117
|
-
VALUE exc = rb_exc_new2(
|
125
|
+
VALUE exc = rb_exc_new2(klass, msg);
|
118
126
|
VALUE bt = rb_ary_new();
|
119
127
|
|
120
|
-
|
121
|
-
|
128
|
+
rb_funcall(exc, id_set_backtrace, 1, bt);
|
129
|
+
rb_exc_raise(exc);
|
122
130
|
}
|
123
131
|
|
124
132
|
#define REMAINING (unsigned long)(pe - p)
|
@@ -126,12 +134,27 @@ static void parser_error(const char *msg)
|
|
126
134
|
#define MARK(M,FPC) (hp->M = (FPC) - buffer)
|
127
135
|
#define PTR_TO(F) (buffer + hp->F)
|
128
136
|
#define STR_NEW(M,FPC) rb_str_new(PTR_TO(M), LEN(M, FPC))
|
137
|
+
#define STRIPPED_STR_NEW(M,FPC) stripped_str_new(PTR_TO(M), LEN(M, FPC))
|
129
138
|
|
130
139
|
#define HP_FL_TEST(hp,fl) ((hp)->flags & (UH_FL_##fl))
|
131
140
|
#define HP_FL_SET(hp,fl) ((hp)->flags |= (UH_FL_##fl))
|
132
141
|
#define HP_FL_UNSET(hp,fl) ((hp)->flags &= ~(UH_FL_##fl))
|
133
142
|
#define HP_FL_ALL(hp,fl) (HP_FL_TEST(hp, fl) == (UH_FL_##fl))
|
134
143
|
|
144
|
+
static int is_lws(char c)
|
145
|
+
{
|
146
|
+
return (c == ' ' || c == '\t');
|
147
|
+
}
|
148
|
+
|
149
|
+
static VALUE stripped_str_new(const char *str, long len)
|
150
|
+
{
|
151
|
+
long end;
|
152
|
+
|
153
|
+
for (end = len - 1; end >= 0 && is_lws(str[end]); end--);
|
154
|
+
|
155
|
+
return rb_str_new(str, end + 1);
|
156
|
+
}
|
157
|
+
|
135
158
|
/*
|
136
159
|
* handles values of the "Connection:" header, keepalive is implied
|
137
160
|
* for HTTP/1.1 but needs to be explicitly enabled with HTTP/1.0
|
@@ -188,35 +211,43 @@ http_version(struct http_parser *hp, const char *ptr, size_t len)
|
|
188
211
|
static inline void hp_invalid_if_trailer(struct http_parser *hp)
|
189
212
|
{
|
190
213
|
if (HP_FL_TEST(hp, INTRAILER))
|
191
|
-
|
214
|
+
parser_raise(eHttpParserError, "invalid Trailer");
|
192
215
|
}
|
193
216
|
|
194
217
|
static void write_cont_value(struct http_parser *hp,
|
195
218
|
char *buffer, const char *p)
|
196
219
|
{
|
197
220
|
char *vptr;
|
221
|
+
long end;
|
222
|
+
long len = LEN(mark, p);
|
223
|
+
long cont_len;
|
198
224
|
|
199
225
|
if (hp->cont == Qfalse)
|
200
|
-
|
226
|
+
parser_raise(eHttpParserError, "invalid continuation line");
|
201
227
|
if (NIL_P(hp->cont))
|
202
228
|
return; /* we're ignoring this header (probably Host:) */
|
203
229
|
|
204
230
|
assert(TYPE(hp->cont) == T_STRING && "continuation line is not a string");
|
205
231
|
assert(hp->mark > 0 && "impossible continuation line offset");
|
206
232
|
|
207
|
-
if (
|
233
|
+
if (len == 0)
|
208
234
|
return;
|
209
235
|
|
210
|
-
|
236
|
+
cont_len = RSTRING_LEN(hp->cont);
|
237
|
+
if (cont_len > 0) {
|
211
238
|
--hp->mark;
|
212
|
-
|
239
|
+
len = LEN(mark, p);
|
240
|
+
}
|
213
241
|
vptr = PTR_TO(mark);
|
214
242
|
|
215
|
-
|
243
|
+
/* normalize tab to space */
|
244
|
+
if (cont_len > 0) {
|
216
245
|
assert((' ' == *vptr || '\t' == *vptr) && "invalid leading white space");
|
217
246
|
*vptr = ' ';
|
218
247
|
}
|
219
|
-
|
248
|
+
|
249
|
+
for (end = len - 1; end >= 0 && is_lws(vptr[end]); end--);
|
250
|
+
rb_str_buf_cat(hp->cont, vptr, end + 1);
|
220
251
|
}
|
221
252
|
|
222
253
|
static void write_value(struct http_parser *hp,
|
@@ -227,7 +258,7 @@ static void write_value(struct http_parser *hp,
|
|
227
258
|
VALUE e;
|
228
259
|
|
229
260
|
VALIDATE_MAX_LENGTH(LEN(mark, p), FIELD_VALUE);
|
230
|
-
v = LEN(mark, p) == 0 ? rb_str_buf_new(128) :
|
261
|
+
v = LEN(mark, p) == 0 ? rb_str_buf_new(128) : STRIPPED_STR_NEW(mark, p);
|
231
262
|
if (NIL_P(f)) {
|
232
263
|
const char *field = PTR_TO(start.field);
|
233
264
|
size_t flen = hp->s.field_len;
|
@@ -248,7 +279,7 @@ static void write_value(struct http_parser *hp,
|
|
248
279
|
} else if (f == g_content_length) {
|
249
280
|
hp->len.content = parse_length(RSTRING_PTR(v), RSTRING_LEN(v));
|
250
281
|
if (hp->len.content < 0)
|
251
|
-
|
282
|
+
parser_raise(eHttpParserError, "invalid Content-Length");
|
252
283
|
if (hp->len.content != 0)
|
253
284
|
HP_FL_SET(hp, HASBODY);
|
254
285
|
hp_invalid_if_trailer(hp);
|
@@ -284,12 +315,12 @@ static void write_value(struct http_parser *hp,
|
|
284
315
|
/** Machine **/
|
285
316
|
|
286
317
|
|
287
|
-
#line
|
318
|
+
#line 422 "unicorn_http.rl"
|
288
319
|
|
289
320
|
|
290
321
|
/** Data **/
|
291
322
|
|
292
|
-
#line
|
323
|
+
#line 324 "unicorn_http.c"
|
293
324
|
static const int http_parser_start = 1;
|
294
325
|
static const int http_parser_first_final = 122;
|
295
326
|
static const int http_parser_error = 0;
|
@@ -300,7 +331,7 @@ static const int http_parser_en_Trailers = 114;
|
|
300
331
|
static const int http_parser_en_main = 1;
|
301
332
|
|
302
333
|
|
303
|
-
#line
|
334
|
+
#line 426 "unicorn_http.rl"
|
304
335
|
|
305
336
|
static void http_parser_init(struct http_parser *hp)
|
306
337
|
{
|
@@ -313,12 +344,12 @@ static void http_parser_init(struct http_parser *hp)
|
|
313
344
|
hp->len.content = 0;
|
314
345
|
hp->cont = Qfalse; /* zero on MRI, should be optimized away by above */
|
315
346
|
|
316
|
-
#line
|
347
|
+
#line 348 "unicorn_http.c"
|
317
348
|
{
|
318
349
|
cs = http_parser_start;
|
319
350
|
}
|
320
351
|
|
321
|
-
#line
|
352
|
+
#line 438 "unicorn_http.rl"
|
322
353
|
hp->cs = cs;
|
323
354
|
}
|
324
355
|
|
@@ -346,7 +377,7 @@ http_parser_execute(struct http_parser *hp, char *buffer, size_t len)
|
|
346
377
|
goto skip_chunk_data_hack;
|
347
378
|
}
|
348
379
|
|
349
|
-
#line
|
380
|
+
#line 381 "unicorn_http.c"
|
350
381
|
{
|
351
382
|
if ( p == pe )
|
352
383
|
goto _test_eof;
|
@@ -381,14 +412,14 @@ st0:
|
|
381
412
|
cs = 0;
|
382
413
|
goto _out;
|
383
414
|
tr0:
|
384
|
-
#line
|
415
|
+
#line 318 "unicorn_http.rl"
|
385
416
|
{MARK(mark, p); }
|
386
417
|
goto st2;
|
387
418
|
st2:
|
388
419
|
if ( ++p == pe )
|
389
420
|
goto _test_eof2;
|
390
421
|
case 2:
|
391
|
-
#line
|
422
|
+
#line 423 "unicorn_http.c"
|
392
423
|
switch( (*p) ) {
|
393
424
|
case 32: goto tr3;
|
394
425
|
case 33: goto st49;
|
@@ -414,14 +445,14 @@ case 2:
|
|
414
445
|
goto st49;
|
415
446
|
goto st0;
|
416
447
|
tr3:
|
417
|
-
#line
|
448
|
+
#line 327 "unicorn_http.rl"
|
418
449
|
{ request_method(hp, PTR_TO(mark), LEN(mark, p)); }
|
419
450
|
goto st3;
|
420
451
|
st3:
|
421
452
|
if ( ++p == pe )
|
422
453
|
goto _test_eof3;
|
423
454
|
case 3:
|
424
|
-
#line
|
455
|
+
#line 456 "unicorn_http.c"
|
425
456
|
switch( (*p) ) {
|
426
457
|
case 42: goto tr5;
|
427
458
|
case 47: goto tr6;
|
@@ -430,25 +461,25 @@ case 3:
|
|
430
461
|
}
|
431
462
|
goto st0;
|
432
463
|
tr5:
|
433
|
-
#line
|
464
|
+
#line 318 "unicorn_http.rl"
|
434
465
|
{MARK(mark, p); }
|
435
466
|
goto st4;
|
436
467
|
st4:
|
437
468
|
if ( ++p == pe )
|
438
469
|
goto _test_eof4;
|
439
470
|
case 4:
|
440
|
-
#line
|
471
|
+
#line 472 "unicorn_http.c"
|
441
472
|
switch( (*p) ) {
|
442
473
|
case 32: goto tr8;
|
443
474
|
case 35: goto tr9;
|
444
475
|
}
|
445
476
|
goto st0;
|
446
477
|
tr8:
|
447
|
-
#line
|
478
|
+
#line 332 "unicorn_http.rl"
|
448
479
|
{
|
449
480
|
VALUE str;
|
450
481
|
|
451
|
-
|
482
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
452
483
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
453
484
|
/*
|
454
485
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -462,38 +493,38 @@ tr8:
|
|
462
493
|
}
|
463
494
|
goto st5;
|
464
495
|
tr37:
|
465
|
-
#line
|
496
|
+
#line 318 "unicorn_http.rl"
|
466
497
|
{MARK(mark, p); }
|
467
|
-
#line
|
498
|
+
#line 347 "unicorn_http.rl"
|
468
499
|
{
|
469
|
-
|
500
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
|
470
501
|
rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
|
471
502
|
}
|
472
503
|
goto st5;
|
473
504
|
tr40:
|
474
|
-
#line
|
505
|
+
#line 347 "unicorn_http.rl"
|
475
506
|
{
|
476
|
-
|
507
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
|
477
508
|
rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
|
478
509
|
}
|
479
510
|
goto st5;
|
480
511
|
tr44:
|
481
|
-
#line
|
512
|
+
#line 357 "unicorn_http.rl"
|
482
513
|
{
|
483
514
|
VALUE val;
|
484
515
|
|
485
|
-
|
516
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
486
517
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
487
518
|
|
488
519
|
/* rack says PATH_INFO must start with "/" or be empty */
|
489
520
|
if (!STR_CSTR_EQ(val, "*"))
|
490
521
|
rb_hash_aset(hp->env, g_path_info, val);
|
491
522
|
}
|
492
|
-
#line
|
523
|
+
#line 332 "unicorn_http.rl"
|
493
524
|
{
|
494
525
|
VALUE str;
|
495
526
|
|
496
|
-
|
527
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
497
528
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
498
529
|
/*
|
499
530
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -507,18 +538,18 @@ tr44:
|
|
507
538
|
}
|
508
539
|
goto st5;
|
509
540
|
tr50:
|
510
|
-
#line
|
541
|
+
#line 351 "unicorn_http.rl"
|
511
542
|
{MARK(start.query, p); }
|
512
|
-
#line
|
543
|
+
#line 352 "unicorn_http.rl"
|
513
544
|
{
|
514
|
-
|
545
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
515
546
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
516
547
|
}
|
517
|
-
#line
|
548
|
+
#line 332 "unicorn_http.rl"
|
518
549
|
{
|
519
550
|
VALUE str;
|
520
551
|
|
521
|
-
|
552
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
522
553
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
523
554
|
/*
|
524
555
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -532,16 +563,16 @@ tr50:
|
|
532
563
|
}
|
533
564
|
goto st5;
|
534
565
|
tr54:
|
535
|
-
#line
|
566
|
+
#line 352 "unicorn_http.rl"
|
536
567
|
{
|
537
|
-
|
568
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
538
569
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
539
570
|
}
|
540
|
-
#line
|
571
|
+
#line 332 "unicorn_http.rl"
|
541
572
|
{
|
542
573
|
VALUE str;
|
543
574
|
|
544
|
-
|
575
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
545
576
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
546
577
|
/*
|
547
578
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -558,19 +589,19 @@ st5:
|
|
558
589
|
if ( ++p == pe )
|
559
590
|
goto _test_eof5;
|
560
591
|
case 5:
|
561
|
-
#line
|
592
|
+
#line 593 "unicorn_http.c"
|
562
593
|
if ( (*p) == 72 )
|
563
594
|
goto tr10;
|
564
595
|
goto st0;
|
565
596
|
tr10:
|
566
|
-
#line
|
597
|
+
#line 318 "unicorn_http.rl"
|
567
598
|
{MARK(mark, p); }
|
568
599
|
goto st6;
|
569
600
|
st6:
|
570
601
|
if ( ++p == pe )
|
571
602
|
goto _test_eof6;
|
572
603
|
case 6:
|
573
|
-
#line
|
604
|
+
#line 605 "unicorn_http.c"
|
574
605
|
if ( (*p) == 84 )
|
575
606
|
goto st7;
|
576
607
|
goto st0;
|
@@ -628,34 +659,34 @@ case 13:
|
|
628
659
|
goto st13;
|
629
660
|
goto st0;
|
630
661
|
tr18:
|
631
|
-
#line
|
662
|
+
#line 356 "unicorn_http.rl"
|
632
663
|
{ http_version(hp, PTR_TO(mark), LEN(mark, p)); }
|
633
664
|
goto st14;
|
634
665
|
tr25:
|
635
|
-
#line
|
666
|
+
#line 324 "unicorn_http.rl"
|
636
667
|
{ MARK(mark, p); }
|
637
|
-
#line
|
668
|
+
#line 326 "unicorn_http.rl"
|
638
669
|
{ write_cont_value(hp, buffer, p); }
|
639
670
|
goto st14;
|
640
671
|
tr27:
|
641
|
-
#line
|
672
|
+
#line 326 "unicorn_http.rl"
|
642
673
|
{ write_cont_value(hp, buffer, p); }
|
643
674
|
goto st14;
|
644
675
|
tr33:
|
645
|
-
#line
|
676
|
+
#line 324 "unicorn_http.rl"
|
646
677
|
{ MARK(mark, p); }
|
647
|
-
#line
|
678
|
+
#line 325 "unicorn_http.rl"
|
648
679
|
{ write_value(hp, buffer, p); }
|
649
680
|
goto st14;
|
650
681
|
tr35:
|
651
|
-
#line
|
682
|
+
#line 325 "unicorn_http.rl"
|
652
683
|
{ write_value(hp, buffer, p); }
|
653
684
|
goto st14;
|
654
685
|
st14:
|
655
686
|
if ( ++p == pe )
|
656
687
|
goto _test_eof14;
|
657
688
|
case 14:
|
658
|
-
#line
|
689
|
+
#line 690 "unicorn_http.c"
|
659
690
|
if ( (*p) == 10 )
|
660
691
|
goto st15;
|
661
692
|
goto st0;
|
@@ -690,14 +721,14 @@ case 15:
|
|
690
721
|
goto tr22;
|
691
722
|
goto st0;
|
692
723
|
tr24:
|
693
|
-
#line
|
724
|
+
#line 324 "unicorn_http.rl"
|
694
725
|
{ MARK(mark, p); }
|
695
726
|
goto st16;
|
696
727
|
st16:
|
697
728
|
if ( ++p == pe )
|
698
729
|
goto _test_eof16;
|
699
730
|
case 16:
|
700
|
-
#line
|
731
|
+
#line 732 "unicorn_http.c"
|
701
732
|
switch( (*p) ) {
|
702
733
|
case 9: goto tr24;
|
703
734
|
case 13: goto tr25;
|
@@ -705,23 +736,23 @@ case 16:
|
|
705
736
|
}
|
706
737
|
goto tr23;
|
707
738
|
tr23:
|
708
|
-
#line
|
739
|
+
#line 324 "unicorn_http.rl"
|
709
740
|
{ MARK(mark, p); }
|
710
741
|
goto st17;
|
711
742
|
st17:
|
712
743
|
if ( ++p == pe )
|
713
744
|
goto _test_eof17;
|
714
745
|
case 17:
|
715
|
-
#line
|
746
|
+
#line 747 "unicorn_http.c"
|
716
747
|
if ( (*p) == 13 )
|
717
748
|
goto tr27;
|
718
749
|
goto st17;
|
719
750
|
tr99:
|
720
|
-
#line
|
751
|
+
#line 332 "unicorn_http.rl"
|
721
752
|
{
|
722
753
|
VALUE str;
|
723
754
|
|
724
|
-
|
755
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
725
756
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
726
757
|
/*
|
727
758
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -735,38 +766,38 @@ tr99:
|
|
735
766
|
}
|
736
767
|
goto st18;
|
737
768
|
tr102:
|
738
|
-
#line
|
769
|
+
#line 318 "unicorn_http.rl"
|
739
770
|
{MARK(mark, p); }
|
740
|
-
#line
|
771
|
+
#line 347 "unicorn_http.rl"
|
741
772
|
{
|
742
|
-
|
773
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
|
743
774
|
rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
|
744
775
|
}
|
745
776
|
goto st18;
|
746
777
|
tr105:
|
747
|
-
#line
|
778
|
+
#line 347 "unicorn_http.rl"
|
748
779
|
{
|
749
|
-
|
780
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
|
750
781
|
rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
|
751
782
|
}
|
752
783
|
goto st18;
|
753
784
|
tr109:
|
754
|
-
#line
|
785
|
+
#line 357 "unicorn_http.rl"
|
755
786
|
{
|
756
787
|
VALUE val;
|
757
788
|
|
758
|
-
|
789
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
759
790
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
760
791
|
|
761
792
|
/* rack says PATH_INFO must start with "/" or be empty */
|
762
793
|
if (!STR_CSTR_EQ(val, "*"))
|
763
794
|
rb_hash_aset(hp->env, g_path_info, val);
|
764
795
|
}
|
765
|
-
#line
|
796
|
+
#line 332 "unicorn_http.rl"
|
766
797
|
{
|
767
798
|
VALUE str;
|
768
799
|
|
769
|
-
|
800
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
770
801
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
771
802
|
/*
|
772
803
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -780,18 +811,18 @@ tr109:
|
|
780
811
|
}
|
781
812
|
goto st18;
|
782
813
|
tr115:
|
783
|
-
#line
|
814
|
+
#line 351 "unicorn_http.rl"
|
784
815
|
{MARK(start.query, p); }
|
785
|
-
#line
|
816
|
+
#line 352 "unicorn_http.rl"
|
786
817
|
{
|
787
|
-
|
818
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
788
819
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
789
820
|
}
|
790
|
-
#line
|
821
|
+
#line 332 "unicorn_http.rl"
|
791
822
|
{
|
792
823
|
VALUE str;
|
793
824
|
|
794
|
-
|
825
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
795
826
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
796
827
|
/*
|
797
828
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -805,16 +836,16 @@ tr115:
|
|
805
836
|
}
|
806
837
|
goto st18;
|
807
838
|
tr119:
|
808
|
-
#line
|
839
|
+
#line 352 "unicorn_http.rl"
|
809
840
|
{
|
810
|
-
|
841
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
811
842
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
812
843
|
}
|
813
|
-
#line
|
844
|
+
#line 332 "unicorn_http.rl"
|
814
845
|
{
|
815
846
|
VALUE str;
|
816
847
|
|
817
|
-
|
848
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
818
849
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
819
850
|
/*
|
820
851
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -831,12 +862,12 @@ st18:
|
|
831
862
|
if ( ++p == pe )
|
832
863
|
goto _test_eof18;
|
833
864
|
case 18:
|
834
|
-
#line
|
865
|
+
#line 866 "unicorn_http.c"
|
835
866
|
if ( (*p) == 10 )
|
836
867
|
goto tr28;
|
837
868
|
goto st0;
|
838
869
|
tr28:
|
839
|
-
#line
|
870
|
+
#line 372 "unicorn_http.rl"
|
840
871
|
{
|
841
872
|
finalize_header(hp);
|
842
873
|
|
@@ -860,23 +891,23 @@ st122:
|
|
860
891
|
if ( ++p == pe )
|
861
892
|
goto _test_eof122;
|
862
893
|
case 122:
|
863
|
-
#line
|
894
|
+
#line 895 "unicorn_http.c"
|
864
895
|
goto st0;
|
865
896
|
tr22:
|
866
|
-
#line
|
897
|
+
#line 320 "unicorn_http.rl"
|
867
898
|
{ MARK(start.field, p); }
|
868
|
-
#line
|
899
|
+
#line 321 "unicorn_http.rl"
|
869
900
|
{ snake_upcase_char(deconst(p)); }
|
870
901
|
goto st19;
|
871
902
|
tr29:
|
872
|
-
#line
|
903
|
+
#line 321 "unicorn_http.rl"
|
873
904
|
{ snake_upcase_char(deconst(p)); }
|
874
905
|
goto st19;
|
875
906
|
st19:
|
876
907
|
if ( ++p == pe )
|
877
908
|
goto _test_eof19;
|
878
909
|
case 19:
|
879
|
-
#line
|
910
|
+
#line 911 "unicorn_http.c"
|
880
911
|
switch( (*p) ) {
|
881
912
|
case 33: goto tr29;
|
882
913
|
case 58: goto tr30;
|
@@ -902,18 +933,18 @@ case 19:
|
|
902
933
|
goto tr29;
|
903
934
|
goto st0;
|
904
935
|
tr32:
|
905
|
-
#line
|
936
|
+
#line 324 "unicorn_http.rl"
|
906
937
|
{ MARK(mark, p); }
|
907
938
|
goto st20;
|
908
939
|
tr30:
|
909
|
-
#line
|
940
|
+
#line 323 "unicorn_http.rl"
|
910
941
|
{ hp->s.field_len = LEN(start.field, p); }
|
911
942
|
goto st20;
|
912
943
|
st20:
|
913
944
|
if ( ++p == pe )
|
914
945
|
goto _test_eof20;
|
915
946
|
case 20:
|
916
|
-
#line
|
947
|
+
#line 948 "unicorn_http.c"
|
917
948
|
switch( (*p) ) {
|
918
949
|
case 9: goto tr32;
|
919
950
|
case 13: goto tr33;
|
@@ -921,23 +952,23 @@ case 20:
|
|
921
952
|
}
|
922
953
|
goto tr31;
|
923
954
|
tr31:
|
924
|
-
#line
|
955
|
+
#line 324 "unicorn_http.rl"
|
925
956
|
{ MARK(mark, p); }
|
926
957
|
goto st21;
|
927
958
|
st21:
|
928
959
|
if ( ++p == pe )
|
929
960
|
goto _test_eof21;
|
930
961
|
case 21:
|
931
|
-
#line
|
962
|
+
#line 963 "unicorn_http.c"
|
932
963
|
if ( (*p) == 13 )
|
933
964
|
goto tr35;
|
934
965
|
goto st21;
|
935
966
|
tr9:
|
936
|
-
#line
|
967
|
+
#line 332 "unicorn_http.rl"
|
937
968
|
{
|
938
969
|
VALUE str;
|
939
970
|
|
940
|
-
|
971
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
941
972
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
942
973
|
/*
|
943
974
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -951,22 +982,22 @@ tr9:
|
|
951
982
|
}
|
952
983
|
goto st22;
|
953
984
|
tr45:
|
954
|
-
#line
|
985
|
+
#line 357 "unicorn_http.rl"
|
955
986
|
{
|
956
987
|
VALUE val;
|
957
988
|
|
958
|
-
|
989
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
959
990
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
960
991
|
|
961
992
|
/* rack says PATH_INFO must start with "/" or be empty */
|
962
993
|
if (!STR_CSTR_EQ(val, "*"))
|
963
994
|
rb_hash_aset(hp->env, g_path_info, val);
|
964
995
|
}
|
965
|
-
#line
|
996
|
+
#line 332 "unicorn_http.rl"
|
966
997
|
{
|
967
998
|
VALUE str;
|
968
999
|
|
969
|
-
|
1000
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
970
1001
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
971
1002
|
/*
|
972
1003
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -980,18 +1011,18 @@ tr45:
|
|
980
1011
|
}
|
981
1012
|
goto st22;
|
982
1013
|
tr51:
|
983
|
-
#line
|
1014
|
+
#line 351 "unicorn_http.rl"
|
984
1015
|
{MARK(start.query, p); }
|
985
|
-
#line
|
1016
|
+
#line 352 "unicorn_http.rl"
|
986
1017
|
{
|
987
|
-
|
1018
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
988
1019
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
989
1020
|
}
|
990
|
-
#line
|
1021
|
+
#line 332 "unicorn_http.rl"
|
991
1022
|
{
|
992
1023
|
VALUE str;
|
993
1024
|
|
994
|
-
|
1025
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
995
1026
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
996
1027
|
/*
|
997
1028
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -1005,16 +1036,16 @@ tr51:
|
|
1005
1036
|
}
|
1006
1037
|
goto st22;
|
1007
1038
|
tr55:
|
1008
|
-
#line
|
1039
|
+
#line 352 "unicorn_http.rl"
|
1009
1040
|
{
|
1010
|
-
|
1041
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
1011
1042
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
1012
1043
|
}
|
1013
|
-
#line
|
1044
|
+
#line 332 "unicorn_http.rl"
|
1014
1045
|
{
|
1015
1046
|
VALUE str;
|
1016
1047
|
|
1017
|
-
|
1048
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
1018
1049
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
1019
1050
|
/*
|
1020
1051
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -1031,7 +1062,7 @@ st22:
|
|
1031
1062
|
if ( ++p == pe )
|
1032
1063
|
goto _test_eof22;
|
1033
1064
|
case 22:
|
1034
|
-
#line
|
1065
|
+
#line 1066 "unicorn_http.c"
|
1035
1066
|
switch( (*p) ) {
|
1036
1067
|
case 32: goto tr37;
|
1037
1068
|
case 35: goto st0;
|
@@ -1042,14 +1073,14 @@ case 22:
|
|
1042
1073
|
goto st0;
|
1043
1074
|
goto tr36;
|
1044
1075
|
tr36:
|
1045
|
-
#line
|
1076
|
+
#line 318 "unicorn_http.rl"
|
1046
1077
|
{MARK(mark, p); }
|
1047
1078
|
goto st23;
|
1048
1079
|
st23:
|
1049
1080
|
if ( ++p == pe )
|
1050
1081
|
goto _test_eof23;
|
1051
1082
|
case 23:
|
1052
|
-
#line
|
1083
|
+
#line 1084 "unicorn_http.c"
|
1053
1084
|
switch( (*p) ) {
|
1054
1085
|
case 32: goto tr40;
|
1055
1086
|
case 35: goto st0;
|
@@ -1060,14 +1091,14 @@ case 23:
|
|
1060
1091
|
goto st0;
|
1061
1092
|
goto st23;
|
1062
1093
|
tr38:
|
1063
|
-
#line
|
1094
|
+
#line 318 "unicorn_http.rl"
|
1064
1095
|
{MARK(mark, p); }
|
1065
1096
|
goto st24;
|
1066
1097
|
st24:
|
1067
1098
|
if ( ++p == pe )
|
1068
1099
|
goto _test_eof24;
|
1069
1100
|
case 24:
|
1070
|
-
#line
|
1101
|
+
#line 1102 "unicorn_http.c"
|
1071
1102
|
if ( (*p) < 65 ) {
|
1072
1103
|
if ( 48 <= (*p) && (*p) <= 57 )
|
1073
1104
|
goto st25;
|
@@ -1091,20 +1122,20 @@ case 25:
|
|
1091
1122
|
goto st23;
|
1092
1123
|
goto st0;
|
1093
1124
|
tr6:
|
1094
|
-
#line
|
1125
|
+
#line 318 "unicorn_http.rl"
|
1095
1126
|
{MARK(mark, p); }
|
1096
1127
|
goto st26;
|
1097
1128
|
tr71:
|
1098
|
-
#line
|
1129
|
+
#line 331 "unicorn_http.rl"
|
1099
1130
|
{ rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
|
1100
|
-
#line
|
1131
|
+
#line 318 "unicorn_http.rl"
|
1101
1132
|
{MARK(mark, p); }
|
1102
1133
|
goto st26;
|
1103
1134
|
st26:
|
1104
1135
|
if ( ++p == pe )
|
1105
1136
|
goto _test_eof26;
|
1106
1137
|
case 26:
|
1107
|
-
#line
|
1138
|
+
#line 1139 "unicorn_http.c"
|
1108
1139
|
switch( (*p) ) {
|
1109
1140
|
case 32: goto tr44;
|
1110
1141
|
case 35: goto tr45;
|
@@ -1142,11 +1173,11 @@ case 28:
|
|
1142
1173
|
goto st26;
|
1143
1174
|
goto st0;
|
1144
1175
|
tr47:
|
1145
|
-
#line
|
1176
|
+
#line 357 "unicorn_http.rl"
|
1146
1177
|
{
|
1147
1178
|
VALUE val;
|
1148
1179
|
|
1149
|
-
|
1180
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
1150
1181
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
1151
1182
|
|
1152
1183
|
/* rack says PATH_INFO must start with "/" or be empty */
|
@@ -1158,7 +1189,7 @@ st29:
|
|
1158
1189
|
if ( ++p == pe )
|
1159
1190
|
goto _test_eof29;
|
1160
1191
|
case 29:
|
1161
|
-
#line
|
1192
|
+
#line 1193 "unicorn_http.c"
|
1162
1193
|
switch( (*p) ) {
|
1163
1194
|
case 32: goto tr50;
|
1164
1195
|
case 35: goto tr51;
|
@@ -1169,14 +1200,14 @@ case 29:
|
|
1169
1200
|
goto st0;
|
1170
1201
|
goto tr49;
|
1171
1202
|
tr49:
|
1172
|
-
#line
|
1203
|
+
#line 351 "unicorn_http.rl"
|
1173
1204
|
{MARK(start.query, p); }
|
1174
1205
|
goto st30;
|
1175
1206
|
st30:
|
1176
1207
|
if ( ++p == pe )
|
1177
1208
|
goto _test_eof30;
|
1178
1209
|
case 30:
|
1179
|
-
#line
|
1210
|
+
#line 1211 "unicorn_http.c"
|
1180
1211
|
switch( (*p) ) {
|
1181
1212
|
case 32: goto tr54;
|
1182
1213
|
case 35: goto tr55;
|
@@ -1187,14 +1218,14 @@ case 30:
|
|
1187
1218
|
goto st0;
|
1188
1219
|
goto st30;
|
1189
1220
|
tr52:
|
1190
|
-
#line
|
1221
|
+
#line 351 "unicorn_http.rl"
|
1191
1222
|
{MARK(start.query, p); }
|
1192
1223
|
goto st31;
|
1193
1224
|
st31:
|
1194
1225
|
if ( ++p == pe )
|
1195
1226
|
goto _test_eof31;
|
1196
1227
|
case 31:
|
1197
|
-
#line
|
1228
|
+
#line 1229 "unicorn_http.c"
|
1198
1229
|
if ( (*p) < 65 ) {
|
1199
1230
|
if ( 48 <= (*p) && (*p) <= 57 )
|
1200
1231
|
goto st32;
|
@@ -1218,58 +1249,58 @@ case 32:
|
|
1218
1249
|
goto st30;
|
1219
1250
|
goto st0;
|
1220
1251
|
tr7:
|
1221
|
-
#line
|
1252
|
+
#line 318 "unicorn_http.rl"
|
1222
1253
|
{MARK(mark, p); }
|
1223
|
-
#line
|
1254
|
+
#line 322 "unicorn_http.rl"
|
1224
1255
|
{ downcase_char(deconst(p)); }
|
1225
1256
|
goto st33;
|
1226
1257
|
st33:
|
1227
1258
|
if ( ++p == pe )
|
1228
1259
|
goto _test_eof33;
|
1229
1260
|
case 33:
|
1230
|
-
#line
|
1261
|
+
#line 1262 "unicorn_http.c"
|
1231
1262
|
switch( (*p) ) {
|
1232
1263
|
case 84: goto tr58;
|
1233
1264
|
case 116: goto tr58;
|
1234
1265
|
}
|
1235
1266
|
goto st0;
|
1236
1267
|
tr58:
|
1237
|
-
#line
|
1268
|
+
#line 322 "unicorn_http.rl"
|
1238
1269
|
{ downcase_char(deconst(p)); }
|
1239
1270
|
goto st34;
|
1240
1271
|
st34:
|
1241
1272
|
if ( ++p == pe )
|
1242
1273
|
goto _test_eof34;
|
1243
1274
|
case 34:
|
1244
|
-
#line
|
1275
|
+
#line 1276 "unicorn_http.c"
|
1245
1276
|
switch( (*p) ) {
|
1246
1277
|
case 84: goto tr59;
|
1247
1278
|
case 116: goto tr59;
|
1248
1279
|
}
|
1249
1280
|
goto st0;
|
1250
1281
|
tr59:
|
1251
|
-
#line
|
1282
|
+
#line 322 "unicorn_http.rl"
|
1252
1283
|
{ downcase_char(deconst(p)); }
|
1253
1284
|
goto st35;
|
1254
1285
|
st35:
|
1255
1286
|
if ( ++p == pe )
|
1256
1287
|
goto _test_eof35;
|
1257
1288
|
case 35:
|
1258
|
-
#line
|
1289
|
+
#line 1290 "unicorn_http.c"
|
1259
1290
|
switch( (*p) ) {
|
1260
1291
|
case 80: goto tr60;
|
1261
1292
|
case 112: goto tr60;
|
1262
1293
|
}
|
1263
1294
|
goto st0;
|
1264
1295
|
tr60:
|
1265
|
-
#line
|
1296
|
+
#line 322 "unicorn_http.rl"
|
1266
1297
|
{ downcase_char(deconst(p)); }
|
1267
1298
|
goto st36;
|
1268
1299
|
st36:
|
1269
1300
|
if ( ++p == pe )
|
1270
1301
|
goto _test_eof36;
|
1271
1302
|
case 36:
|
1272
|
-
#line
|
1303
|
+
#line 1304 "unicorn_http.c"
|
1273
1304
|
switch( (*p) ) {
|
1274
1305
|
case 58: goto tr61;
|
1275
1306
|
case 83: goto tr62;
|
@@ -1277,7 +1308,7 @@ case 36:
|
|
1277
1308
|
}
|
1278
1309
|
goto st0;
|
1279
1310
|
tr61:
|
1280
|
-
#line
|
1311
|
+
#line 328 "unicorn_http.rl"
|
1281
1312
|
{
|
1282
1313
|
rb_hash_aset(hp->env, g_rack_url_scheme, STR_NEW(mark, p));
|
1283
1314
|
}
|
@@ -1286,7 +1317,7 @@ st37:
|
|
1286
1317
|
if ( ++p == pe )
|
1287
1318
|
goto _test_eof37;
|
1288
1319
|
case 37:
|
1289
|
-
#line
|
1320
|
+
#line 1321 "unicorn_http.c"
|
1290
1321
|
if ( (*p) == 47 )
|
1291
1322
|
goto st38;
|
1292
1323
|
goto st0;
|
@@ -1374,14 +1405,14 @@ case 42:
|
|
1374
1405
|
goto st40;
|
1375
1406
|
goto st0;
|
1376
1407
|
tr67:
|
1377
|
-
#line
|
1408
|
+
#line 318 "unicorn_http.rl"
|
1378
1409
|
{MARK(mark, p); }
|
1379
1410
|
goto st43;
|
1380
1411
|
st43:
|
1381
1412
|
if ( ++p == pe )
|
1382
1413
|
goto _test_eof43;
|
1383
1414
|
case 43:
|
1384
|
-
#line
|
1415
|
+
#line 1416 "unicorn_http.c"
|
1385
1416
|
switch( (*p) ) {
|
1386
1417
|
case 37: goto st41;
|
1387
1418
|
case 47: goto tr71;
|
@@ -1433,14 +1464,14 @@ case 44:
|
|
1433
1464
|
goto st0;
|
1434
1465
|
goto st40;
|
1435
1466
|
tr68:
|
1436
|
-
#line
|
1467
|
+
#line 318 "unicorn_http.rl"
|
1437
1468
|
{MARK(mark, p); }
|
1438
1469
|
goto st45;
|
1439
1470
|
st45:
|
1440
1471
|
if ( ++p == pe )
|
1441
1472
|
goto _test_eof45;
|
1442
1473
|
case 45:
|
1443
|
-
#line
|
1474
|
+
#line 1475 "unicorn_http.c"
|
1444
1475
|
switch( (*p) ) {
|
1445
1476
|
case 37: goto st41;
|
1446
1477
|
case 47: goto st0;
|
@@ -1518,14 +1549,14 @@ case 47:
|
|
1518
1549
|
goto st0;
|
1519
1550
|
goto st40;
|
1520
1551
|
tr62:
|
1521
|
-
#line
|
1552
|
+
#line 322 "unicorn_http.rl"
|
1522
1553
|
{ downcase_char(deconst(p)); }
|
1523
1554
|
goto st48;
|
1524
1555
|
st48:
|
1525
1556
|
if ( ++p == pe )
|
1526
1557
|
goto _test_eof48;
|
1527
1558
|
case 48:
|
1528
|
-
#line
|
1559
|
+
#line 1560 "unicorn_http.c"
|
1529
1560
|
if ( (*p) == 58 )
|
1530
1561
|
goto tr61;
|
1531
1562
|
goto st0;
|
@@ -2041,14 +2072,14 @@ case 67:
|
|
2041
2072
|
goto tr3;
|
2042
2073
|
goto st0;
|
2043
2074
|
tr2:
|
2044
|
-
#line
|
2075
|
+
#line 318 "unicorn_http.rl"
|
2045
2076
|
{MARK(mark, p); }
|
2046
2077
|
goto st68;
|
2047
2078
|
st68:
|
2048
2079
|
if ( ++p == pe )
|
2049
2080
|
goto _test_eof68;
|
2050
2081
|
case 68:
|
2051
|
-
#line
|
2082
|
+
#line 2083 "unicorn_http.c"
|
2052
2083
|
switch( (*p) ) {
|
2053
2084
|
case 32: goto tr3;
|
2054
2085
|
case 33: goto st49;
|
@@ -2132,14 +2163,14 @@ case 70:
|
|
2132
2163
|
goto st51;
|
2133
2164
|
goto st0;
|
2134
2165
|
tr95:
|
2135
|
-
#line
|
2166
|
+
#line 327 "unicorn_http.rl"
|
2136
2167
|
{ request_method(hp, PTR_TO(mark), LEN(mark, p)); }
|
2137
2168
|
goto st71;
|
2138
2169
|
st71:
|
2139
2170
|
if ( ++p == pe )
|
2140
2171
|
goto _test_eof71;
|
2141
2172
|
case 71:
|
2142
|
-
#line
|
2173
|
+
#line 2174 "unicorn_http.c"
|
2143
2174
|
switch( (*p) ) {
|
2144
2175
|
case 42: goto tr96;
|
2145
2176
|
case 47: goto tr97;
|
@@ -2148,14 +2179,14 @@ case 71:
|
|
2148
2179
|
}
|
2149
2180
|
goto st0;
|
2150
2181
|
tr96:
|
2151
|
-
#line
|
2182
|
+
#line 318 "unicorn_http.rl"
|
2152
2183
|
{MARK(mark, p); }
|
2153
2184
|
goto st72;
|
2154
2185
|
st72:
|
2155
2186
|
if ( ++p == pe )
|
2156
2187
|
goto _test_eof72;
|
2157
2188
|
case 72:
|
2158
|
-
#line
|
2189
|
+
#line 2190 "unicorn_http.c"
|
2159
2190
|
switch( (*p) ) {
|
2160
2191
|
case 13: goto tr99;
|
2161
2192
|
case 32: goto tr8;
|
@@ -2163,11 +2194,11 @@ case 72:
|
|
2163
2194
|
}
|
2164
2195
|
goto st0;
|
2165
2196
|
tr100:
|
2166
|
-
#line
|
2197
|
+
#line 332 "unicorn_http.rl"
|
2167
2198
|
{
|
2168
2199
|
VALUE str;
|
2169
2200
|
|
2170
|
-
|
2201
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
2171
2202
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
2172
2203
|
/*
|
2173
2204
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -2181,22 +2212,22 @@ tr100:
|
|
2181
2212
|
}
|
2182
2213
|
goto st73;
|
2183
2214
|
tr110:
|
2184
|
-
#line
|
2215
|
+
#line 357 "unicorn_http.rl"
|
2185
2216
|
{
|
2186
2217
|
VALUE val;
|
2187
2218
|
|
2188
|
-
|
2219
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
2189
2220
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
2190
2221
|
|
2191
2222
|
/* rack says PATH_INFO must start with "/" or be empty */
|
2192
2223
|
if (!STR_CSTR_EQ(val, "*"))
|
2193
2224
|
rb_hash_aset(hp->env, g_path_info, val);
|
2194
2225
|
}
|
2195
|
-
#line
|
2226
|
+
#line 332 "unicorn_http.rl"
|
2196
2227
|
{
|
2197
2228
|
VALUE str;
|
2198
2229
|
|
2199
|
-
|
2230
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
2200
2231
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
2201
2232
|
/*
|
2202
2233
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -2210,18 +2241,18 @@ tr110:
|
|
2210
2241
|
}
|
2211
2242
|
goto st73;
|
2212
2243
|
tr116:
|
2213
|
-
#line
|
2244
|
+
#line 351 "unicorn_http.rl"
|
2214
2245
|
{MARK(start.query, p); }
|
2215
|
-
#line
|
2246
|
+
#line 352 "unicorn_http.rl"
|
2216
2247
|
{
|
2217
|
-
|
2248
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
2218
2249
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
2219
2250
|
}
|
2220
|
-
#line
|
2251
|
+
#line 332 "unicorn_http.rl"
|
2221
2252
|
{
|
2222
2253
|
VALUE str;
|
2223
2254
|
|
2224
|
-
|
2255
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
2225
2256
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
2226
2257
|
/*
|
2227
2258
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -2235,16 +2266,16 @@ tr116:
|
|
2235
2266
|
}
|
2236
2267
|
goto st73;
|
2237
2268
|
tr120:
|
2238
|
-
#line
|
2269
|
+
#line 352 "unicorn_http.rl"
|
2239
2270
|
{
|
2240
|
-
|
2271
|
+
VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
|
2241
2272
|
rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
|
2242
2273
|
}
|
2243
|
-
#line
|
2274
|
+
#line 332 "unicorn_http.rl"
|
2244
2275
|
{
|
2245
2276
|
VALUE str;
|
2246
2277
|
|
2247
|
-
|
2278
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
|
2248
2279
|
str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
|
2249
2280
|
/*
|
2250
2281
|
* "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
|
@@ -2261,7 +2292,7 @@ st73:
|
|
2261
2292
|
if ( ++p == pe )
|
2262
2293
|
goto _test_eof73;
|
2263
2294
|
case 73:
|
2264
|
-
#line
|
2295
|
+
#line 2296 "unicorn_http.c"
|
2265
2296
|
switch( (*p) ) {
|
2266
2297
|
case 13: goto tr102;
|
2267
2298
|
case 32: goto tr37;
|
@@ -2273,14 +2304,14 @@ case 73:
|
|
2273
2304
|
goto st0;
|
2274
2305
|
goto tr101;
|
2275
2306
|
tr101:
|
2276
|
-
#line
|
2307
|
+
#line 318 "unicorn_http.rl"
|
2277
2308
|
{MARK(mark, p); }
|
2278
2309
|
goto st74;
|
2279
2310
|
st74:
|
2280
2311
|
if ( ++p == pe )
|
2281
2312
|
goto _test_eof74;
|
2282
2313
|
case 74:
|
2283
|
-
#line
|
2314
|
+
#line 2315 "unicorn_http.c"
|
2284
2315
|
switch( (*p) ) {
|
2285
2316
|
case 13: goto tr105;
|
2286
2317
|
case 32: goto tr40;
|
@@ -2292,14 +2323,14 @@ case 74:
|
|
2292
2323
|
goto st0;
|
2293
2324
|
goto st74;
|
2294
2325
|
tr103:
|
2295
|
-
#line
|
2326
|
+
#line 318 "unicorn_http.rl"
|
2296
2327
|
{MARK(mark, p); }
|
2297
2328
|
goto st75;
|
2298
2329
|
st75:
|
2299
2330
|
if ( ++p == pe )
|
2300
2331
|
goto _test_eof75;
|
2301
2332
|
case 75:
|
2302
|
-
#line
|
2333
|
+
#line 2334 "unicorn_http.c"
|
2303
2334
|
if ( (*p) < 65 ) {
|
2304
2335
|
if ( 48 <= (*p) && (*p) <= 57 )
|
2305
2336
|
goto st76;
|
@@ -2323,20 +2354,20 @@ case 76:
|
|
2323
2354
|
goto st74;
|
2324
2355
|
goto st0;
|
2325
2356
|
tr97:
|
2326
|
-
#line
|
2357
|
+
#line 318 "unicorn_http.rl"
|
2327
2358
|
{MARK(mark, p); }
|
2328
2359
|
goto st77;
|
2329
2360
|
tr136:
|
2330
|
-
#line
|
2361
|
+
#line 331 "unicorn_http.rl"
|
2331
2362
|
{ rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
|
2332
|
-
#line
|
2363
|
+
#line 318 "unicorn_http.rl"
|
2333
2364
|
{MARK(mark, p); }
|
2334
2365
|
goto st77;
|
2335
2366
|
st77:
|
2336
2367
|
if ( ++p == pe )
|
2337
2368
|
goto _test_eof77;
|
2338
2369
|
case 77:
|
2339
|
-
#line
|
2370
|
+
#line 2371 "unicorn_http.c"
|
2340
2371
|
switch( (*p) ) {
|
2341
2372
|
case 13: goto tr109;
|
2342
2373
|
case 32: goto tr44;
|
@@ -2375,11 +2406,11 @@ case 79:
|
|
2375
2406
|
goto st77;
|
2376
2407
|
goto st0;
|
2377
2408
|
tr112:
|
2378
|
-
#line
|
2409
|
+
#line 357 "unicorn_http.rl"
|
2379
2410
|
{
|
2380
2411
|
VALUE val;
|
2381
2412
|
|
2382
|
-
|
2413
|
+
VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
|
2383
2414
|
val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
|
2384
2415
|
|
2385
2416
|
/* rack says PATH_INFO must start with "/" or be empty */
|
@@ -2391,7 +2422,7 @@ st80:
|
|
2391
2422
|
if ( ++p == pe )
|
2392
2423
|
goto _test_eof80;
|
2393
2424
|
case 80:
|
2394
|
-
#line
|
2425
|
+
#line 2426 "unicorn_http.c"
|
2395
2426
|
switch( (*p) ) {
|
2396
2427
|
case 13: goto tr115;
|
2397
2428
|
case 32: goto tr50;
|
@@ -2403,14 +2434,14 @@ case 80:
|
|
2403
2434
|
goto st0;
|
2404
2435
|
goto tr114;
|
2405
2436
|
tr114:
|
2406
|
-
#line
|
2437
|
+
#line 351 "unicorn_http.rl"
|
2407
2438
|
{MARK(start.query, p); }
|
2408
2439
|
goto st81;
|
2409
2440
|
st81:
|
2410
2441
|
if ( ++p == pe )
|
2411
2442
|
goto _test_eof81;
|
2412
2443
|
case 81:
|
2413
|
-
#line
|
2444
|
+
#line 2445 "unicorn_http.c"
|
2414
2445
|
switch( (*p) ) {
|
2415
2446
|
case 13: goto tr119;
|
2416
2447
|
case 32: goto tr54;
|
@@ -2422,14 +2453,14 @@ case 81:
|
|
2422
2453
|
goto st0;
|
2423
2454
|
goto st81;
|
2424
2455
|
tr117:
|
2425
|
-
#line
|
2456
|
+
#line 351 "unicorn_http.rl"
|
2426
2457
|
{MARK(start.query, p); }
|
2427
2458
|
goto st82;
|
2428
2459
|
st82:
|
2429
2460
|
if ( ++p == pe )
|
2430
2461
|
goto _test_eof82;
|
2431
2462
|
case 82:
|
2432
|
-
#line
|
2463
|
+
#line 2464 "unicorn_http.c"
|
2433
2464
|
if ( (*p) < 65 ) {
|
2434
2465
|
if ( 48 <= (*p) && (*p) <= 57 )
|
2435
2466
|
goto st83;
|
@@ -2453,58 +2484,58 @@ case 83:
|
|
2453
2484
|
goto st81;
|
2454
2485
|
goto st0;
|
2455
2486
|
tr98:
|
2456
|
-
#line
|
2487
|
+
#line 318 "unicorn_http.rl"
|
2457
2488
|
{MARK(mark, p); }
|
2458
|
-
#line
|
2489
|
+
#line 322 "unicorn_http.rl"
|
2459
2490
|
{ downcase_char(deconst(p)); }
|
2460
2491
|
goto st84;
|
2461
2492
|
st84:
|
2462
2493
|
if ( ++p == pe )
|
2463
2494
|
goto _test_eof84;
|
2464
2495
|
case 84:
|
2465
|
-
#line
|
2496
|
+
#line 2497 "unicorn_http.c"
|
2466
2497
|
switch( (*p) ) {
|
2467
2498
|
case 84: goto tr123;
|
2468
2499
|
case 116: goto tr123;
|
2469
2500
|
}
|
2470
2501
|
goto st0;
|
2471
2502
|
tr123:
|
2472
|
-
#line
|
2503
|
+
#line 322 "unicorn_http.rl"
|
2473
2504
|
{ downcase_char(deconst(p)); }
|
2474
2505
|
goto st85;
|
2475
2506
|
st85:
|
2476
2507
|
if ( ++p == pe )
|
2477
2508
|
goto _test_eof85;
|
2478
2509
|
case 85:
|
2479
|
-
#line
|
2510
|
+
#line 2511 "unicorn_http.c"
|
2480
2511
|
switch( (*p) ) {
|
2481
2512
|
case 84: goto tr124;
|
2482
2513
|
case 116: goto tr124;
|
2483
2514
|
}
|
2484
2515
|
goto st0;
|
2485
2516
|
tr124:
|
2486
|
-
#line
|
2517
|
+
#line 322 "unicorn_http.rl"
|
2487
2518
|
{ downcase_char(deconst(p)); }
|
2488
2519
|
goto st86;
|
2489
2520
|
st86:
|
2490
2521
|
if ( ++p == pe )
|
2491
2522
|
goto _test_eof86;
|
2492
2523
|
case 86:
|
2493
|
-
#line
|
2524
|
+
#line 2525 "unicorn_http.c"
|
2494
2525
|
switch( (*p) ) {
|
2495
2526
|
case 80: goto tr125;
|
2496
2527
|
case 112: goto tr125;
|
2497
2528
|
}
|
2498
2529
|
goto st0;
|
2499
2530
|
tr125:
|
2500
|
-
#line
|
2531
|
+
#line 322 "unicorn_http.rl"
|
2501
2532
|
{ downcase_char(deconst(p)); }
|
2502
2533
|
goto st87;
|
2503
2534
|
st87:
|
2504
2535
|
if ( ++p == pe )
|
2505
2536
|
goto _test_eof87;
|
2506
2537
|
case 87:
|
2507
|
-
#line
|
2538
|
+
#line 2539 "unicorn_http.c"
|
2508
2539
|
switch( (*p) ) {
|
2509
2540
|
case 58: goto tr126;
|
2510
2541
|
case 83: goto tr127;
|
@@ -2512,7 +2543,7 @@ case 87:
|
|
2512
2543
|
}
|
2513
2544
|
goto st0;
|
2514
2545
|
tr126:
|
2515
|
-
#line
|
2546
|
+
#line 328 "unicorn_http.rl"
|
2516
2547
|
{
|
2517
2548
|
rb_hash_aset(hp->env, g_rack_url_scheme, STR_NEW(mark, p));
|
2518
2549
|
}
|
@@ -2521,7 +2552,7 @@ st88:
|
|
2521
2552
|
if ( ++p == pe )
|
2522
2553
|
goto _test_eof88;
|
2523
2554
|
case 88:
|
2524
|
-
#line
|
2555
|
+
#line 2556 "unicorn_http.c"
|
2525
2556
|
if ( (*p) == 47 )
|
2526
2557
|
goto st89;
|
2527
2558
|
goto st0;
|
@@ -2609,14 +2640,14 @@ case 93:
|
|
2609
2640
|
goto st91;
|
2610
2641
|
goto st0;
|
2611
2642
|
tr132:
|
2612
|
-
#line
|
2643
|
+
#line 318 "unicorn_http.rl"
|
2613
2644
|
{MARK(mark, p); }
|
2614
2645
|
goto st94;
|
2615
2646
|
st94:
|
2616
2647
|
if ( ++p == pe )
|
2617
2648
|
goto _test_eof94;
|
2618
2649
|
case 94:
|
2619
|
-
#line
|
2650
|
+
#line 2651 "unicorn_http.c"
|
2620
2651
|
switch( (*p) ) {
|
2621
2652
|
case 37: goto st92;
|
2622
2653
|
case 47: goto tr136;
|
@@ -2668,14 +2699,14 @@ case 95:
|
|
2668
2699
|
goto st0;
|
2669
2700
|
goto st91;
|
2670
2701
|
tr133:
|
2671
|
-
#line
|
2702
|
+
#line 318 "unicorn_http.rl"
|
2672
2703
|
{MARK(mark, p); }
|
2673
2704
|
goto st96;
|
2674
2705
|
st96:
|
2675
2706
|
if ( ++p == pe )
|
2676
2707
|
goto _test_eof96;
|
2677
2708
|
case 96:
|
2678
|
-
#line
|
2709
|
+
#line 2710 "unicorn_http.c"
|
2679
2710
|
switch( (*p) ) {
|
2680
2711
|
case 37: goto st92;
|
2681
2712
|
case 47: goto st0;
|
@@ -2753,14 +2784,14 @@ case 98:
|
|
2753
2784
|
goto st0;
|
2754
2785
|
goto st91;
|
2755
2786
|
tr127:
|
2756
|
-
#line
|
2787
|
+
#line 322 "unicorn_http.rl"
|
2757
2788
|
{ downcase_char(deconst(p)); }
|
2758
2789
|
goto st99;
|
2759
2790
|
st99:
|
2760
2791
|
if ( ++p == pe )
|
2761
2792
|
goto _test_eof99;
|
2762
2793
|
case 99:
|
2763
|
-
#line
|
2794
|
+
#line 2795 "unicorn_http.c"
|
2764
2795
|
if ( (*p) == 58 )
|
2765
2796
|
goto tr126;
|
2766
2797
|
goto st0;
|
@@ -2780,18 +2811,18 @@ case 100:
|
|
2780
2811
|
goto tr141;
|
2781
2812
|
goto st0;
|
2782
2813
|
tr140:
|
2783
|
-
#line
|
2814
|
+
#line 367 "unicorn_http.rl"
|
2784
2815
|
{
|
2785
2816
|
hp->len.chunk = step_incr(hp->len.chunk, (*p), 16);
|
2786
2817
|
if (hp->len.chunk < 0)
|
2787
|
-
|
2818
|
+
parser_raise(eHttpParserError, "invalid chunk size");
|
2788
2819
|
}
|
2789
2820
|
goto st101;
|
2790
2821
|
st101:
|
2791
2822
|
if ( ++p == pe )
|
2792
2823
|
goto _test_eof101;
|
2793
2824
|
case 101:
|
2794
|
-
#line
|
2825
|
+
#line 2826 "unicorn_http.c"
|
2795
2826
|
switch( (*p) ) {
|
2796
2827
|
case 13: goto st102;
|
2797
2828
|
case 48: goto tr140;
|
@@ -2814,7 +2845,7 @@ case 102:
|
|
2814
2845
|
goto tr144;
|
2815
2846
|
goto st0;
|
2816
2847
|
tr144:
|
2817
|
-
#line
|
2848
|
+
#line 396 "unicorn_http.rl"
|
2818
2849
|
{
|
2819
2850
|
HP_FL_SET(hp, INTRAILER);
|
2820
2851
|
cs = http_parser_en_Trailers;
|
@@ -2827,21 +2858,21 @@ st123:
|
|
2827
2858
|
if ( ++p == pe )
|
2828
2859
|
goto _test_eof123;
|
2829
2860
|
case 123:
|
2830
|
-
#line
|
2861
|
+
#line 2862 "unicorn_http.c"
|
2831
2862
|
goto st0;
|
2832
2863
|
tr141:
|
2833
|
-
#line
|
2864
|
+
#line 367 "unicorn_http.rl"
|
2834
2865
|
{
|
2835
2866
|
hp->len.chunk = step_incr(hp->len.chunk, (*p), 16);
|
2836
2867
|
if (hp->len.chunk < 0)
|
2837
|
-
|
2868
|
+
parser_raise(eHttpParserError, "invalid chunk size");
|
2838
2869
|
}
|
2839
2870
|
goto st103;
|
2840
2871
|
st103:
|
2841
2872
|
if ( ++p == pe )
|
2842
2873
|
goto _test_eof103;
|
2843
2874
|
case 103:
|
2844
|
-
#line
|
2875
|
+
#line 2876 "unicorn_http.c"
|
2845
2876
|
switch( (*p) ) {
|
2846
2877
|
case 13: goto st104;
|
2847
2878
|
case 59: goto st108;
|
@@ -2868,7 +2899,7 @@ st105:
|
|
2868
2899
|
case 105:
|
2869
2900
|
goto tr148;
|
2870
2901
|
tr148:
|
2871
|
-
#line
|
2902
|
+
#line 404 "unicorn_http.rl"
|
2872
2903
|
{
|
2873
2904
|
skip_chunk_data_hack: {
|
2874
2905
|
size_t nr = MIN((size_t)hp->len.chunk, REMAINING);
|
@@ -2890,7 +2921,7 @@ st106:
|
|
2890
2921
|
if ( ++p == pe )
|
2891
2922
|
goto _test_eof106;
|
2892
2923
|
case 106:
|
2893
|
-
#line
|
2924
|
+
#line 2925 "unicorn_http.c"
|
2894
2925
|
if ( (*p) == 13 )
|
2895
2926
|
goto st107;
|
2896
2927
|
goto st0;
|
@@ -3112,14 +3143,14 @@ case 114:
|
|
3112
3143
|
goto tr157;
|
3113
3144
|
goto st0;
|
3114
3145
|
tr159:
|
3115
|
-
#line
|
3146
|
+
#line 324 "unicorn_http.rl"
|
3116
3147
|
{ MARK(mark, p); }
|
3117
3148
|
goto st115;
|
3118
3149
|
st115:
|
3119
3150
|
if ( ++p == pe )
|
3120
3151
|
goto _test_eof115;
|
3121
3152
|
case 115:
|
3122
|
-
#line
|
3153
|
+
#line 3154 "unicorn_http.c"
|
3123
3154
|
switch( (*p) ) {
|
3124
3155
|
case 9: goto tr159;
|
3125
3156
|
case 13: goto tr160;
|
@@ -3127,42 +3158,42 @@ case 115:
|
|
3127
3158
|
}
|
3128
3159
|
goto tr158;
|
3129
3160
|
tr158:
|
3130
|
-
#line
|
3161
|
+
#line 324 "unicorn_http.rl"
|
3131
3162
|
{ MARK(mark, p); }
|
3132
3163
|
goto st116;
|
3133
3164
|
st116:
|
3134
3165
|
if ( ++p == pe )
|
3135
3166
|
goto _test_eof116;
|
3136
3167
|
case 116:
|
3137
|
-
#line
|
3168
|
+
#line 3169 "unicorn_http.c"
|
3138
3169
|
if ( (*p) == 13 )
|
3139
3170
|
goto tr162;
|
3140
3171
|
goto st116;
|
3141
3172
|
tr160:
|
3142
|
-
#line
|
3173
|
+
#line 324 "unicorn_http.rl"
|
3143
3174
|
{ MARK(mark, p); }
|
3144
|
-
#line
|
3175
|
+
#line 326 "unicorn_http.rl"
|
3145
3176
|
{ write_cont_value(hp, buffer, p); }
|
3146
3177
|
goto st117;
|
3147
3178
|
tr162:
|
3148
|
-
#line
|
3179
|
+
#line 326 "unicorn_http.rl"
|
3149
3180
|
{ write_cont_value(hp, buffer, p); }
|
3150
3181
|
goto st117;
|
3151
3182
|
tr169:
|
3152
|
-
#line
|
3183
|
+
#line 324 "unicorn_http.rl"
|
3153
3184
|
{ MARK(mark, p); }
|
3154
|
-
#line
|
3185
|
+
#line 325 "unicorn_http.rl"
|
3155
3186
|
{ write_value(hp, buffer, p); }
|
3156
3187
|
goto st117;
|
3157
3188
|
tr171:
|
3158
|
-
#line
|
3189
|
+
#line 325 "unicorn_http.rl"
|
3159
3190
|
{ write_value(hp, buffer, p); }
|
3160
3191
|
goto st117;
|
3161
3192
|
st117:
|
3162
3193
|
if ( ++p == pe )
|
3163
3194
|
goto _test_eof117;
|
3164
3195
|
case 117:
|
3165
|
-
#line
|
3196
|
+
#line 3197 "unicorn_http.c"
|
3166
3197
|
if ( (*p) == 10 )
|
3167
3198
|
goto st114;
|
3168
3199
|
goto st0;
|
@@ -3174,7 +3205,7 @@ case 118:
|
|
3174
3205
|
goto tr164;
|
3175
3206
|
goto st0;
|
3176
3207
|
tr164:
|
3177
|
-
#line
|
3208
|
+
#line 391 "unicorn_http.rl"
|
3178
3209
|
{
|
3179
3210
|
cs = http_parser_first_final;
|
3180
3211
|
goto post_exec;
|
@@ -3184,23 +3215,23 @@ st124:
|
|
3184
3215
|
if ( ++p == pe )
|
3185
3216
|
goto _test_eof124;
|
3186
3217
|
case 124:
|
3187
|
-
#line
|
3218
|
+
#line 3219 "unicorn_http.c"
|
3188
3219
|
goto st0;
|
3189
3220
|
tr157:
|
3190
|
-
#line
|
3221
|
+
#line 320 "unicorn_http.rl"
|
3191
3222
|
{ MARK(start.field, p); }
|
3192
|
-
#line
|
3223
|
+
#line 321 "unicorn_http.rl"
|
3193
3224
|
{ snake_upcase_char(deconst(p)); }
|
3194
3225
|
goto st119;
|
3195
3226
|
tr165:
|
3196
|
-
#line
|
3227
|
+
#line 321 "unicorn_http.rl"
|
3197
3228
|
{ snake_upcase_char(deconst(p)); }
|
3198
3229
|
goto st119;
|
3199
3230
|
st119:
|
3200
3231
|
if ( ++p == pe )
|
3201
3232
|
goto _test_eof119;
|
3202
3233
|
case 119:
|
3203
|
-
#line
|
3234
|
+
#line 3235 "unicorn_http.c"
|
3204
3235
|
switch( (*p) ) {
|
3205
3236
|
case 33: goto tr165;
|
3206
3237
|
case 58: goto tr166;
|
@@ -3226,18 +3257,18 @@ case 119:
|
|
3226
3257
|
goto tr165;
|
3227
3258
|
goto st0;
|
3228
3259
|
tr168:
|
3229
|
-
#line
|
3260
|
+
#line 324 "unicorn_http.rl"
|
3230
3261
|
{ MARK(mark, p); }
|
3231
3262
|
goto st120;
|
3232
3263
|
tr166:
|
3233
|
-
#line
|
3264
|
+
#line 323 "unicorn_http.rl"
|
3234
3265
|
{ hp->s.field_len = LEN(start.field, p); }
|
3235
3266
|
goto st120;
|
3236
3267
|
st120:
|
3237
3268
|
if ( ++p == pe )
|
3238
3269
|
goto _test_eof120;
|
3239
3270
|
case 120:
|
3240
|
-
#line
|
3271
|
+
#line 3272 "unicorn_http.c"
|
3241
3272
|
switch( (*p) ) {
|
3242
3273
|
case 9: goto tr168;
|
3243
3274
|
case 13: goto tr169;
|
@@ -3245,14 +3276,14 @@ case 120:
|
|
3245
3276
|
}
|
3246
3277
|
goto tr167;
|
3247
3278
|
tr167:
|
3248
|
-
#line
|
3279
|
+
#line 324 "unicorn_http.rl"
|
3249
3280
|
{ MARK(mark, p); }
|
3250
3281
|
goto st121;
|
3251
3282
|
st121:
|
3252
3283
|
if ( ++p == pe )
|
3253
3284
|
goto _test_eof121;
|
3254
3285
|
case 121:
|
3255
|
-
#line
|
3286
|
+
#line 3287 "unicorn_http.c"
|
3256
3287
|
if ( (*p) == 13 )
|
3257
3288
|
goto tr171;
|
3258
3289
|
goto st121;
|
@@ -3385,7 +3416,7 @@ case 121:
|
|
3385
3416
|
_out: {}
|
3386
3417
|
}
|
3387
3418
|
|
3388
|
-
#line
|
3419
|
+
#line 465 "unicorn_http.rl"
|
3389
3420
|
post_exec: /* "_out:" also goes here */
|
3390
3421
|
if (hp->cs != http_parser_error)
|
3391
3422
|
hp->cs = cs;
|
@@ -3553,6 +3584,34 @@ static VALUE HttpParser_clear(VALUE self)
|
|
3553
3584
|
return self;
|
3554
3585
|
}
|
3555
3586
|
|
3587
|
+
/**
|
3588
|
+
* call-seq:
|
3589
|
+
* parser.dechunk! => parser
|
3590
|
+
*
|
3591
|
+
* Resets the parser to a state suitable for dechunking response bodies
|
3592
|
+
*
|
3593
|
+
*/
|
3594
|
+
static VALUE HttpParser_dechunk_bang(VALUE self)
|
3595
|
+
{
|
3596
|
+
struct http_parser *hp = data_get(self);
|
3597
|
+
|
3598
|
+
http_parser_init(hp);
|
3599
|
+
|
3600
|
+
/*
|
3601
|
+
* we don't care about trailers in dechunk-only mode,
|
3602
|
+
* but if we did we'd set UH_FL_HASTRAILER and clear hp->env
|
3603
|
+
*/
|
3604
|
+
if (0) {
|
3605
|
+
rb_funcall(hp->env, id_clear, 0);
|
3606
|
+
hp->flags = UH_FL_HASTRAILER;
|
3607
|
+
}
|
3608
|
+
|
3609
|
+
hp->flags |= UH_FL_HASBODY | UH_FL_INBODY | UH_FL_CHUNKED;
|
3610
|
+
hp->cs = http_parser_en_ChunkedBody;
|
3611
|
+
|
3612
|
+
return self;
|
3613
|
+
}
|
3614
|
+
|
3556
3615
|
/**
|
3557
3616
|
* call-seq:
|
3558
3617
|
* parser.reset => nil
|
@@ -3632,7 +3691,8 @@ static VALUE HttpParser_parse(VALUE self)
|
|
3632
3691
|
}
|
3633
3692
|
|
3634
3693
|
http_parser_execute(hp, RSTRING_PTR(data), RSTRING_LEN(data));
|
3635
|
-
|
3694
|
+
if (hp->offset > MAX_HEADER_LEN)
|
3695
|
+
parser_raise(e413, "HTTP header is too large");
|
3636
3696
|
|
3637
3697
|
if (hp->cs == http_parser_first_final ||
|
3638
3698
|
hp->cs == http_parser_en_ChunkedBody) {
|
@@ -3645,11 +3705,32 @@ static VALUE HttpParser_parse(VALUE self)
|
|
3645
3705
|
}
|
3646
3706
|
|
3647
3707
|
if (hp->cs == http_parser_error)
|
3648
|
-
|
3708
|
+
parser_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
|
3649
3709
|
|
3650
3710
|
return Qnil;
|
3651
3711
|
}
|
3652
3712
|
|
3713
|
+
/**
|
3714
|
+
* Document-method: parse
|
3715
|
+
* call-seq:
|
3716
|
+
* parser.add_parse(buffer) => env or nil
|
3717
|
+
*
|
3718
|
+
* adds the contents of +buffer+ to the internal buffer and attempts to
|
3719
|
+
* continue parsing. Returns the +env+ Hash on success or nil if more
|
3720
|
+
* data is needed.
|
3721
|
+
*
|
3722
|
+
* Raises HttpParserError if there are parsing errors.
|
3723
|
+
*/
|
3724
|
+
static VALUE HttpParser_add_parse(VALUE self, VALUE buffer)
|
3725
|
+
{
|
3726
|
+
struct http_parser *hp = data_get(self);
|
3727
|
+
|
3728
|
+
Check_Type(buffer, T_STRING);
|
3729
|
+
rb_str_buf_append(hp->buf, buffer);
|
3730
|
+
|
3731
|
+
return HttpParser_parse(self);
|
3732
|
+
}
|
3733
|
+
|
3653
3734
|
/**
|
3654
3735
|
* Document-method: trailers
|
3655
3736
|
* call-seq:
|
@@ -3758,71 +3839,80 @@ static VALUE HttpParser_env(VALUE self)
|
|
3758
3839
|
|
3759
3840
|
/**
|
3760
3841
|
* call-seq:
|
3761
|
-
* parser.filter_body(
|
3842
|
+
* parser.filter_body(dst, src) => nil/src
|
3762
3843
|
*
|
3763
|
-
* Takes a String of +
|
3844
|
+
* Takes a String of +src+, will modify data if dechunking is done.
|
3764
3845
|
* Returns +nil+ if there is more data left to process. Returns
|
3765
|
-
* +
|
3766
|
-
* it may modify +
|
3846
|
+
* +src+ if body processing is complete. When returning +src+,
|
3847
|
+
* it may modify +src+ so the start of the string points to where
|
3767
3848
|
* the body ended so that trailer processing can begin.
|
3768
3849
|
*
|
3769
3850
|
* Raises HttpParserError if there are dechunking errors.
|
3770
|
-
* Basically this is a glorified memcpy(3) that copies +
|
3851
|
+
* Basically this is a glorified memcpy(3) that copies +src+
|
3771
3852
|
* into +buf+ while filtering it through the dechunker.
|
3772
3853
|
*/
|
3773
|
-
static VALUE HttpParser_filter_body(VALUE self, VALUE
|
3854
|
+
static VALUE HttpParser_filter_body(VALUE self, VALUE dst, VALUE src)
|
3774
3855
|
{
|
3775
3856
|
struct http_parser *hp = data_get(self);
|
3776
|
-
char *
|
3777
|
-
long
|
3857
|
+
char *srcptr;
|
3858
|
+
long srclen;
|
3778
3859
|
|
3779
|
-
|
3780
|
-
|
3860
|
+
srcptr = RSTRING_PTR(src);
|
3861
|
+
srclen = RSTRING_LEN(src);
|
3781
3862
|
|
3782
|
-
StringValue(
|
3783
|
-
rb_str_resize(buf, dlen); /* we can never copy more than dlen bytes */
|
3784
|
-
OBJ_TAINT(buf); /* keep weirdo $SAFE users happy */
|
3863
|
+
StringValue(dst);
|
3785
3864
|
|
3786
3865
|
if (HP_FL_TEST(hp, CHUNKED)) {
|
3787
3866
|
if (!chunked_eof(hp)) {
|
3867
|
+
rb_str_modify(dst);
|
3868
|
+
rb_str_resize(dst, srclen); /* we can never copy more than srclen bytes */
|
3869
|
+
|
3788
3870
|
hp->s.dest_offset = 0;
|
3789
|
-
hp->cont =
|
3790
|
-
hp->buf =
|
3791
|
-
http_parser_execute(hp,
|
3871
|
+
hp->cont = dst;
|
3872
|
+
hp->buf = src;
|
3873
|
+
http_parser_execute(hp, srcptr, srclen);
|
3792
3874
|
if (hp->cs == http_parser_error)
|
3793
|
-
|
3875
|
+
parser_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
|
3794
3876
|
|
3795
3877
|
assert(hp->s.dest_offset <= hp->offset &&
|
3796
3878
|
"destination buffer overflow");
|
3797
|
-
advance_str(
|
3798
|
-
rb_str_set_len(
|
3879
|
+
advance_str(src, hp->offset);
|
3880
|
+
rb_str_set_len(dst, hp->s.dest_offset);
|
3799
3881
|
|
3800
|
-
if (RSTRING_LEN(
|
3882
|
+
if (RSTRING_LEN(dst) == 0 && chunked_eof(hp)) {
|
3801
3883
|
assert(hp->len.chunk == 0 && "chunk at EOF but more to parse");
|
3802
3884
|
} else {
|
3803
|
-
|
3885
|
+
src = Qnil;
|
3804
3886
|
}
|
3805
3887
|
}
|
3806
3888
|
} else {
|
3807
3889
|
/* no need to enter the Ragel machine for unchunked transfers */
|
3808
3890
|
assert(hp->len.content >= 0 && "negative Content-Length");
|
3809
3891
|
if (hp->len.content > 0) {
|
3810
|
-
long nr = MIN(
|
3811
|
-
|
3812
|
-
|
3813
|
-
|
3892
|
+
long nr = MIN(srclen, hp->len.content);
|
3893
|
+
|
3894
|
+
rb_str_modify(dst);
|
3895
|
+
rb_str_resize(dst, nr);
|
3896
|
+
/*
|
3897
|
+
* using rb_str_replace() to avoid memcpy() doesn't help in
|
3898
|
+
* most cases because a GC-aware programmer will pass an explicit
|
3899
|
+
* buffer to env["rack.input"].read and reuse the buffer in a loop.
|
3900
|
+
* This causes copy-on-write behavior to be triggered anyways
|
3901
|
+
* when the +src+ buffer is modified (when reading off the socket).
|
3902
|
+
*/
|
3903
|
+
hp->buf = src;
|
3904
|
+
memcpy(RSTRING_PTR(dst), srcptr, nr);
|
3814
3905
|
hp->len.content -= nr;
|
3815
3906
|
if (hp->len.content == 0) {
|
3816
3907
|
HP_FL_SET(hp, REQEOF);
|
3817
3908
|
hp->cs = http_parser_first_final;
|
3818
3909
|
}
|
3819
|
-
advance_str(
|
3820
|
-
|
3821
|
-
data = Qnil;
|
3910
|
+
advance_str(src, nr);
|
3911
|
+
src = Qnil;
|
3822
3912
|
}
|
3823
3913
|
}
|
3824
3914
|
hp->offset = 0; /* for trailer parsing */
|
3825
|
-
return
|
3915
|
+
return src;
|
3826
3916
|
}
|
3827
3917
|
|
3828
3918
|
#define SET_GLOBAL(var,str) do { \
|
@@ -3838,13 +3928,19 @@ void Init_unicorn_http(void)
|
|
3838
3928
|
cHttpParser = rb_define_class_under(mUnicorn, "HttpParser", rb_cObject);
|
3839
3929
|
eHttpParserError =
|
3840
3930
|
rb_define_class_under(mUnicorn, "HttpParserError", rb_eIOError);
|
3931
|
+
e413 = rb_define_class_under(mUnicorn, "RequestEntityTooLargeError",
|
3932
|
+
eHttpParserError);
|
3933
|
+
e414 = rb_define_class_under(mUnicorn, "RequestURITooLongError",
|
3934
|
+
eHttpParserError);
|
3841
3935
|
|
3842
3936
|
init_globals();
|
3843
3937
|
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
|
3844
3938
|
rb_define_method(cHttpParser, "initialize", HttpParser_init, 0);
|
3845
3939
|
rb_define_method(cHttpParser, "clear", HttpParser_clear, 0);
|
3846
3940
|
rb_define_method(cHttpParser, "reset", HttpParser_reset, 0);
|
3941
|
+
rb_define_method(cHttpParser, "dechunk!", HttpParser_dechunk_bang, 0);
|
3847
3942
|
rb_define_method(cHttpParser, "parse", HttpParser_parse, 0);
|
3943
|
+
rb_define_method(cHttpParser, "add_parse", HttpParser_add_parse, 1);
|
3848
3944
|
rb_define_method(cHttpParser, "headers", HttpParser_headers, 2);
|
3849
3945
|
rb_define_method(cHttpParser, "trailers", HttpParser_headers, 2);
|
3850
3946
|
rb_define_method(cHttpParser, "filter_body", HttpParser_filter_body, 2);
|
@@ -3879,6 +3975,7 @@ void Init_unicorn_http(void)
|
|
3879
3975
|
rb_define_singleton_method(cHttpParser, "keepalive_requests=", set_ka_req, 1);
|
3880
3976
|
rb_define_singleton_method(cHttpParser, "trust_x_forwarded=", set_xftrust, 1);
|
3881
3977
|
rb_define_singleton_method(cHttpParser, "trust_x_forwarded?", xftrust, 0);
|
3978
|
+
rb_define_singleton_method(cHttpParser, "max_header_len=", set_maxhdrlen, 1);
|
3882
3979
|
|
3883
3980
|
init_common_fields();
|
3884
3981
|
SET_GLOBAL(g_http_host, "HOST");
|
@@ -3887,6 +3984,7 @@ void Init_unicorn_http(void)
|
|
3887
3984
|
SET_GLOBAL(g_content_length, "CONTENT_LENGTH");
|
3888
3985
|
SET_GLOBAL(g_http_connection, "CONNECTION");
|
3889
3986
|
id_clear = rb_intern("clear");
|
3987
|
+
id_set_backtrace = rb_intern("set_backtrace");
|
3890
3988
|
init_unicorn_httpdate();
|
3891
3989
|
}
|
3892
3990
|
#undef SET_GLOBAL
|