unicorn 3.6.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.document +1 -0
  2. data/.manifest +13 -0
  3. data/ChangeLog +783 -1
  4. data/DESIGN +0 -8
  5. data/Documentation/GNUmakefile +1 -1
  6. data/GIT-VERSION-FILE +1 -1
  7. data/GIT-VERSION-GEN +1 -1
  8. data/GNUmakefile +2 -2
  9. data/HACKING +11 -0
  10. data/KNOWN_ISSUES +2 -2
  11. data/LATEST +24 -24
  12. data/Links +53 -0
  13. data/NEWS +66 -0
  14. data/PHILOSOPHY +49 -49
  15. data/Sandbox +13 -4
  16. data/TODO +0 -2
  17. data/TUNING +31 -9
  18. data/bin/unicorn +2 -1
  19. data/bin/unicorn_rails +2 -1
  20. data/examples/big_app_gc.rb +2 -33
  21. data/examples/nginx.conf +17 -4
  22. data/ext/unicorn_http/ext_help.h +16 -0
  23. data/ext/unicorn_http/extconf.rb +1 -0
  24. data/ext/unicorn_http/global_variables.h +9 -3
  25. data/ext/unicorn_http/unicorn_http.c +357 -259
  26. data/ext/unicorn_http/unicorn_http.rl +148 -50
  27. data/lib/unicorn/configurator.rb +36 -8
  28. data/lib/unicorn/const.rb +5 -3
  29. data/lib/unicorn/http_request.rb +1 -3
  30. data/lib/unicorn/http_server.rb +82 -95
  31. data/lib/unicorn/oob_gc.rb +61 -50
  32. data/lib/unicorn/socket_helper.rb +23 -8
  33. data/lib/unicorn/worker.rb +45 -4
  34. data/lib/unicorn.rb +8 -6
  35. data/script/isolate_for_tests +4 -2
  36. data/t/broken-app.ru +12 -0
  37. data/t/heartbeat-timeout.ru +12 -0
  38. data/t/oob_gc.ru +21 -0
  39. data/t/oob_gc_path.ru +21 -0
  40. data/t/t0001-reload-bad-config.sh +1 -0
  41. data/t/t0002-parser-error.sh +64 -1
  42. data/t/t0004-heartbeat-timeout.sh +69 -0
  43. data/t/t0009-broken-app.sh +56 -0
  44. data/t/t0019-max_header_len.sh +49 -0
  45. data/t/t0020-at_exit-handler.sh +49 -0
  46. data/t/t9001-oob_gc.sh +47 -0
  47. data/t/t9002-oob_gc-path.sh +75 -0
  48. data/test/benchmark/stack.ru +8 -0
  49. data/test/unit/test_droplet.rb +28 -0
  50. data/test/unit/test_http_parser.rb +60 -4
  51. data/test/unit/test_http_parser_ng.rb +54 -0
  52. data/test/unit/test_response.rb +1 -1
  53. data/test/unit/test_server.rb +1 -1
  54. data/test/unit/test_signals.rb +1 -1
  55. data/test/unit/test_socket_helper.rb +8 -0
  56. data/test/unit/test_upload.rb +1 -1
  57. data/unicorn.gemspec +3 -2
  58. 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 parser_error(const char *msg)
123
+ static void parser_raise(VALUE klass, const char *msg)
116
124
  {
117
- VALUE exc = rb_exc_new2(eHttpParserError, msg);
125
+ VALUE exc = rb_exc_new2(klass, msg);
118
126
  VALUE bt = rb_ary_new();
119
127
 
120
- rb_funcall(exc, rb_intern("set_backtrace"), 1, bt);
121
- rb_exc_raise(exc);
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
- parser_error("invalid Trailer");
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
- parser_error("invalid continuation line");
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 (LEN(mark, p) == 0)
233
+ if (len == 0)
208
234
  return;
209
235
 
210
- if (RSTRING_LEN(hp->cont) > 0)
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
- if (RSTRING_LEN(hp->cont) > 0) {
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
- rb_str_buf_cat(hp->cont, vptr, LEN(mark, p));
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) : STR_NEW(mark, p);
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
- parser_error("invalid Content-Length");
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 391 "unicorn_http.rl"
318
+ #line 422 "unicorn_http.rl"
288
319
 
289
320
 
290
321
  /** Data **/
291
322
 
292
- #line 293 "unicorn_http.c"
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 395 "unicorn_http.rl"
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 317 "unicorn_http.c"
347
+ #line 348 "unicorn_http.c"
317
348
  {
318
349
  cs = http_parser_start;
319
350
  }
320
351
 
321
- #line 407 "unicorn_http.rl"
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 350 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 392 "unicorn_http.c"
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 296 "unicorn_http.rl"
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 425 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 441 "unicorn_http.c"
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 301 "unicorn_http.rl"
478
+ #line 332 "unicorn_http.rl"
448
479
  {
449
480
  VALUE str;
450
481
 
451
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 287 "unicorn_http.rl"
496
+ #line 318 "unicorn_http.rl"
466
497
  {MARK(mark, p); }
467
- #line 316 "unicorn_http.rl"
498
+ #line 347 "unicorn_http.rl"
468
499
  {
469
- VALIDATE_MAX_LENGTH(LEN(mark, p), FRAGMENT);
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 316 "unicorn_http.rl"
505
+ #line 347 "unicorn_http.rl"
475
506
  {
476
- VALIDATE_MAX_LENGTH(LEN(mark, p), FRAGMENT);
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 326 "unicorn_http.rl"
512
+ #line 357 "unicorn_http.rl"
482
513
  {
483
514
  VALUE val;
484
515
 
485
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 301 "unicorn_http.rl"
523
+ #line 332 "unicorn_http.rl"
493
524
  {
494
525
  VALUE str;
495
526
 
496
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 320 "unicorn_http.rl"
541
+ #line 351 "unicorn_http.rl"
511
542
  {MARK(start.query, p); }
512
- #line 321 "unicorn_http.rl"
543
+ #line 352 "unicorn_http.rl"
513
544
  {
514
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
548
+ #line 332 "unicorn_http.rl"
518
549
  {
519
550
  VALUE str;
520
551
 
521
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 321 "unicorn_http.rl"
566
+ #line 352 "unicorn_http.rl"
536
567
  {
537
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
571
+ #line 332 "unicorn_http.rl"
541
572
  {
542
573
  VALUE str;
543
574
 
544
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 562 "unicorn_http.c"
592
+ #line 593 "unicorn_http.c"
562
593
  if ( (*p) == 72 )
563
594
  goto tr10;
564
595
  goto st0;
565
596
  tr10:
566
- #line 287 "unicorn_http.rl"
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 574 "unicorn_http.c"
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 325 "unicorn_http.rl"
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 293 "unicorn_http.rl"
666
+ #line 324 "unicorn_http.rl"
636
667
  { MARK(mark, p); }
637
- #line 295 "unicorn_http.rl"
668
+ #line 326 "unicorn_http.rl"
638
669
  { write_cont_value(hp, buffer, p); }
639
670
  goto st14;
640
671
  tr27:
641
- #line 295 "unicorn_http.rl"
672
+ #line 326 "unicorn_http.rl"
642
673
  { write_cont_value(hp, buffer, p); }
643
674
  goto st14;
644
675
  tr33:
645
- #line 293 "unicorn_http.rl"
676
+ #line 324 "unicorn_http.rl"
646
677
  { MARK(mark, p); }
647
- #line 294 "unicorn_http.rl"
678
+ #line 325 "unicorn_http.rl"
648
679
  { write_value(hp, buffer, p); }
649
680
  goto st14;
650
681
  tr35:
651
- #line 294 "unicorn_http.rl"
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 659 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 701 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 716 "unicorn_http.c"
746
+ #line 747 "unicorn_http.c"
716
747
  if ( (*p) == 13 )
717
748
  goto tr27;
718
749
  goto st17;
719
750
  tr99:
720
- #line 301 "unicorn_http.rl"
751
+ #line 332 "unicorn_http.rl"
721
752
  {
722
753
  VALUE str;
723
754
 
724
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 287 "unicorn_http.rl"
769
+ #line 318 "unicorn_http.rl"
739
770
  {MARK(mark, p); }
740
- #line 316 "unicorn_http.rl"
771
+ #line 347 "unicorn_http.rl"
741
772
  {
742
- VALIDATE_MAX_LENGTH(LEN(mark, p), FRAGMENT);
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 316 "unicorn_http.rl"
778
+ #line 347 "unicorn_http.rl"
748
779
  {
749
- VALIDATE_MAX_LENGTH(LEN(mark, p), FRAGMENT);
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 326 "unicorn_http.rl"
785
+ #line 357 "unicorn_http.rl"
755
786
  {
756
787
  VALUE val;
757
788
 
758
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 301 "unicorn_http.rl"
796
+ #line 332 "unicorn_http.rl"
766
797
  {
767
798
  VALUE str;
768
799
 
769
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 320 "unicorn_http.rl"
814
+ #line 351 "unicorn_http.rl"
784
815
  {MARK(start.query, p); }
785
- #line 321 "unicorn_http.rl"
816
+ #line 352 "unicorn_http.rl"
786
817
  {
787
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
821
+ #line 332 "unicorn_http.rl"
791
822
  {
792
823
  VALUE str;
793
824
 
794
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 321 "unicorn_http.rl"
839
+ #line 352 "unicorn_http.rl"
809
840
  {
810
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
844
+ #line 332 "unicorn_http.rl"
814
845
  {
815
846
  VALUE str;
816
847
 
817
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 835 "unicorn_http.c"
865
+ #line 866 "unicorn_http.c"
835
866
  if ( (*p) == 10 )
836
867
  goto tr28;
837
868
  goto st0;
838
869
  tr28:
839
- #line 341 "unicorn_http.rl"
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 864 "unicorn_http.c"
894
+ #line 895 "unicorn_http.c"
864
895
  goto st0;
865
896
  tr22:
866
- #line 289 "unicorn_http.rl"
897
+ #line 320 "unicorn_http.rl"
867
898
  { MARK(start.field, p); }
868
- #line 290 "unicorn_http.rl"
899
+ #line 321 "unicorn_http.rl"
869
900
  { snake_upcase_char(deconst(p)); }
870
901
  goto st19;
871
902
  tr29:
872
- #line 290 "unicorn_http.rl"
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 880 "unicorn_http.c"
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 293 "unicorn_http.rl"
936
+ #line 324 "unicorn_http.rl"
906
937
  { MARK(mark, p); }
907
938
  goto st20;
908
939
  tr30:
909
- #line 292 "unicorn_http.rl"
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 917 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 932 "unicorn_http.c"
962
+ #line 963 "unicorn_http.c"
932
963
  if ( (*p) == 13 )
933
964
  goto tr35;
934
965
  goto st21;
935
966
  tr9:
936
- #line 301 "unicorn_http.rl"
967
+ #line 332 "unicorn_http.rl"
937
968
  {
938
969
  VALUE str;
939
970
 
940
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 326 "unicorn_http.rl"
985
+ #line 357 "unicorn_http.rl"
955
986
  {
956
987
  VALUE val;
957
988
 
958
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 301 "unicorn_http.rl"
996
+ #line 332 "unicorn_http.rl"
966
997
  {
967
998
  VALUE str;
968
999
 
969
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 320 "unicorn_http.rl"
1014
+ #line 351 "unicorn_http.rl"
984
1015
  {MARK(start.query, p); }
985
- #line 321 "unicorn_http.rl"
1016
+ #line 352 "unicorn_http.rl"
986
1017
  {
987
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
1021
+ #line 332 "unicorn_http.rl"
991
1022
  {
992
1023
  VALUE str;
993
1024
 
994
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 321 "unicorn_http.rl"
1039
+ #line 352 "unicorn_http.rl"
1009
1040
  {
1010
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
1044
+ #line 332 "unicorn_http.rl"
1014
1045
  {
1015
1046
  VALUE str;
1016
1047
 
1017
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 1035 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 1053 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 1071 "unicorn_http.c"
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 287 "unicorn_http.rl"
1125
+ #line 318 "unicorn_http.rl"
1095
1126
  {MARK(mark, p); }
1096
1127
  goto st26;
1097
1128
  tr71:
1098
- #line 300 "unicorn_http.rl"
1129
+ #line 331 "unicorn_http.rl"
1099
1130
  { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
1100
- #line 287 "unicorn_http.rl"
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 1108 "unicorn_http.c"
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 326 "unicorn_http.rl"
1176
+ #line 357 "unicorn_http.rl"
1146
1177
  {
1147
1178
  VALUE val;
1148
1179
 
1149
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 1162 "unicorn_http.c"
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 320 "unicorn_http.rl"
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 1180 "unicorn_http.c"
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 320 "unicorn_http.rl"
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 1198 "unicorn_http.c"
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 287 "unicorn_http.rl"
1252
+ #line 318 "unicorn_http.rl"
1222
1253
  {MARK(mark, p); }
1223
- #line 291 "unicorn_http.rl"
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 1231 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 1245 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 1259 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 1273 "unicorn_http.c"
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 297 "unicorn_http.rl"
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 1290 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 1385 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 1444 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 1529 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2052 "unicorn_http.c"
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 296 "unicorn_http.rl"
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 2143 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2159 "unicorn_http.c"
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 301 "unicorn_http.rl"
2197
+ #line 332 "unicorn_http.rl"
2167
2198
  {
2168
2199
  VALUE str;
2169
2200
 
2170
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 326 "unicorn_http.rl"
2215
+ #line 357 "unicorn_http.rl"
2185
2216
  {
2186
2217
  VALUE val;
2187
2218
 
2188
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 301 "unicorn_http.rl"
2226
+ #line 332 "unicorn_http.rl"
2196
2227
  {
2197
2228
  VALUE str;
2198
2229
 
2199
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 320 "unicorn_http.rl"
2244
+ #line 351 "unicorn_http.rl"
2214
2245
  {MARK(start.query, p); }
2215
- #line 321 "unicorn_http.rl"
2246
+ #line 352 "unicorn_http.rl"
2216
2247
  {
2217
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
2251
+ #line 332 "unicorn_http.rl"
2221
2252
  {
2222
2253
  VALUE str;
2223
2254
 
2224
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 321 "unicorn_http.rl"
2269
+ #line 352 "unicorn_http.rl"
2239
2270
  {
2240
- VALIDATE_MAX_LENGTH(LEN(start.query, p), QUERY_STRING);
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 301 "unicorn_http.rl"
2274
+ #line 332 "unicorn_http.rl"
2244
2275
  {
2245
2276
  VALUE str;
2246
2277
 
2247
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_URI);
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 2265 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2284 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2303 "unicorn_http.c"
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 287 "unicorn_http.rl"
2357
+ #line 318 "unicorn_http.rl"
2327
2358
  {MARK(mark, p); }
2328
2359
  goto st77;
2329
2360
  tr136:
2330
- #line 300 "unicorn_http.rl"
2361
+ #line 331 "unicorn_http.rl"
2331
2362
  { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
2332
- #line 287 "unicorn_http.rl"
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 2340 "unicorn_http.c"
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 326 "unicorn_http.rl"
2409
+ #line 357 "unicorn_http.rl"
2379
2410
  {
2380
2411
  VALUE val;
2381
2412
 
2382
- VALIDATE_MAX_LENGTH(LEN(mark, p), REQUEST_PATH);
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 2395 "unicorn_http.c"
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 320 "unicorn_http.rl"
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 2414 "unicorn_http.c"
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 320 "unicorn_http.rl"
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 2433 "unicorn_http.c"
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 287 "unicorn_http.rl"
2487
+ #line 318 "unicorn_http.rl"
2457
2488
  {MARK(mark, p); }
2458
- #line 291 "unicorn_http.rl"
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 2466 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 2480 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 2494 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 2508 "unicorn_http.c"
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 297 "unicorn_http.rl"
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 2525 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2620 "unicorn_http.c"
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 287 "unicorn_http.rl"
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 2679 "unicorn_http.c"
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 291 "unicorn_http.rl"
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 2764 "unicorn_http.c"
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 336 "unicorn_http.rl"
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
- parser_error("invalid chunk size");
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 2795 "unicorn_http.c"
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 365 "unicorn_http.rl"
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 2831 "unicorn_http.c"
2861
+ #line 2862 "unicorn_http.c"
2831
2862
  goto st0;
2832
2863
  tr141:
2833
- #line 336 "unicorn_http.rl"
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
- parser_error("invalid chunk size");
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 2845 "unicorn_http.c"
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 373 "unicorn_http.rl"
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 2894 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 3123 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 3138 "unicorn_http.c"
3168
+ #line 3169 "unicorn_http.c"
3138
3169
  if ( (*p) == 13 )
3139
3170
  goto tr162;
3140
3171
  goto st116;
3141
3172
  tr160:
3142
- #line 293 "unicorn_http.rl"
3173
+ #line 324 "unicorn_http.rl"
3143
3174
  { MARK(mark, p); }
3144
- #line 295 "unicorn_http.rl"
3175
+ #line 326 "unicorn_http.rl"
3145
3176
  { write_cont_value(hp, buffer, p); }
3146
3177
  goto st117;
3147
3178
  tr162:
3148
- #line 295 "unicorn_http.rl"
3179
+ #line 326 "unicorn_http.rl"
3149
3180
  { write_cont_value(hp, buffer, p); }
3150
3181
  goto st117;
3151
3182
  tr169:
3152
- #line 293 "unicorn_http.rl"
3183
+ #line 324 "unicorn_http.rl"
3153
3184
  { MARK(mark, p); }
3154
- #line 294 "unicorn_http.rl"
3185
+ #line 325 "unicorn_http.rl"
3155
3186
  { write_value(hp, buffer, p); }
3156
3187
  goto st117;
3157
3188
  tr171:
3158
- #line 294 "unicorn_http.rl"
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 3166 "unicorn_http.c"
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 360 "unicorn_http.rl"
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 3188 "unicorn_http.c"
3218
+ #line 3219 "unicorn_http.c"
3188
3219
  goto st0;
3189
3220
  tr157:
3190
- #line 289 "unicorn_http.rl"
3221
+ #line 320 "unicorn_http.rl"
3191
3222
  { MARK(start.field, p); }
3192
- #line 290 "unicorn_http.rl"
3223
+ #line 321 "unicorn_http.rl"
3193
3224
  { snake_upcase_char(deconst(p)); }
3194
3225
  goto st119;
3195
3226
  tr165:
3196
- #line 290 "unicorn_http.rl"
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 3204 "unicorn_http.c"
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 293 "unicorn_http.rl"
3260
+ #line 324 "unicorn_http.rl"
3230
3261
  { MARK(mark, p); }
3231
3262
  goto st120;
3232
3263
  tr166:
3233
- #line 292 "unicorn_http.rl"
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 3241 "unicorn_http.c"
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 293 "unicorn_http.rl"
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 3256 "unicorn_http.c"
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 434 "unicorn_http.rl"
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
- VALIDATE_MAX_LENGTH(hp->offset, HEADER);
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
- parser_error("Invalid HTTP format, parsing fails.");
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(buf, data) => nil/data
3842
+ * parser.filter_body(dst, src) => nil/src
3762
3843
  *
3763
- * Takes a String of +data+, will modify data if dechunking is done.
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
- * +data+ if body processing is complete. When returning +data+,
3766
- * it may modify +data+ so the start of the string points to where
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 +data+
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 buf, VALUE data)
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 *dptr;
3777
- long dlen;
3857
+ char *srcptr;
3858
+ long srclen;
3778
3859
 
3779
- dptr = RSTRING_PTR(data);
3780
- dlen = RSTRING_LEN(data);
3860
+ srcptr = RSTRING_PTR(src);
3861
+ srclen = RSTRING_LEN(src);
3781
3862
 
3782
- StringValue(buf);
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 = buf;
3790
- hp->buf = data;
3791
- http_parser_execute(hp, dptr, dlen);
3871
+ hp->cont = dst;
3872
+ hp->buf = src;
3873
+ http_parser_execute(hp, srcptr, srclen);
3792
3874
  if (hp->cs == http_parser_error)
3793
- parser_error("Invalid HTTP format, parsing fails.");
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(data, hp->offset);
3798
- rb_str_set_len(buf, hp->s.dest_offset);
3879
+ advance_str(src, hp->offset);
3880
+ rb_str_set_len(dst, hp->s.dest_offset);
3799
3881
 
3800
- if (RSTRING_LEN(buf) == 0 && chunked_eof(hp)) {
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
- data = Qnil;
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(dlen, hp->len.content);
3811
-
3812
- hp->buf = data;
3813
- memcpy(RSTRING_PTR(buf), dptr, nr);
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(data, nr);
3820
- rb_str_set_len(buf, nr);
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 data;
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