unicorn 3.6.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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