unicorn-maintained 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.CHANGELOG.old +25 -0
  3. data/.document +28 -0
  4. data/.gitattributes +5 -0
  5. data/.gitignore +25 -0
  6. data/.mailmap +26 -0
  7. data/.manifest +149 -0
  8. data/.olddoc.yml +25 -0
  9. data/Application_Timeouts +77 -0
  10. data/CONTRIBUTORS +39 -0
  11. data/COPYING +674 -0
  12. data/DESIGN +99 -0
  13. data/Documentation/.gitignore +3 -0
  14. data/Documentation/unicorn.1 +222 -0
  15. data/Documentation/unicorn_rails.1 +207 -0
  16. data/FAQ +70 -0
  17. data/GIT-VERSION-FILE +1 -0
  18. data/GIT-VERSION-GEN +39 -0
  19. data/GNUmakefile +317 -0
  20. data/HACKING +112 -0
  21. data/ISSUES +102 -0
  22. data/KNOWN_ISSUES +79 -0
  23. data/LATEST +1 -0
  24. data/LICENSE +67 -0
  25. data/Links +58 -0
  26. data/NEWS +1 -0
  27. data/PHILOSOPHY +139 -0
  28. data/README +156 -0
  29. data/Rakefile +16 -0
  30. data/SIGNALS +123 -0
  31. data/Sandbox +104 -0
  32. data/TODO +3 -0
  33. data/TUNING +119 -0
  34. data/archive/.gitignore +3 -0
  35. data/archive/slrnpull.conf +4 -0
  36. data/bin/unicorn +128 -0
  37. data/bin/unicorn_rails +209 -0
  38. data/examples/big_app_gc.rb +2 -0
  39. data/examples/echo.ru +26 -0
  40. data/examples/init.sh +102 -0
  41. data/examples/logger_mp_safe.rb +25 -0
  42. data/examples/logrotate.conf +44 -0
  43. data/examples/nginx.conf +156 -0
  44. data/examples/unicorn.conf.minimal.rb +13 -0
  45. data/examples/unicorn.conf.rb +110 -0
  46. data/examples/unicorn.socket +11 -0
  47. data/examples/unicorn@.service +40 -0
  48. data/ext/unicorn_http/CFLAGS +13 -0
  49. data/ext/unicorn_http/c_util.h +116 -0
  50. data/ext/unicorn_http/common_field_optimization.h +128 -0
  51. data/ext/unicorn_http/epollexclusive.h +128 -0
  52. data/ext/unicorn_http/ext_help.h +38 -0
  53. data/ext/unicorn_http/extconf.rb +39 -0
  54. data/ext/unicorn_http/global_variables.h +97 -0
  55. data/ext/unicorn_http/httpdate.c +91 -0
  56. data/ext/unicorn_http/unicorn_http.c +4334 -0
  57. data/ext/unicorn_http/unicorn_http.rl +1040 -0
  58. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  59. data/lib/unicorn/app/old_rails/static.rb +59 -0
  60. data/lib/unicorn/app/old_rails.rb +35 -0
  61. data/lib/unicorn/cgi_wrapper.rb +147 -0
  62. data/lib/unicorn/configurator.rb +748 -0
  63. data/lib/unicorn/const.rb +21 -0
  64. data/lib/unicorn/http_request.rb +201 -0
  65. data/lib/unicorn/http_response.rb +93 -0
  66. data/lib/unicorn/http_server.rb +859 -0
  67. data/lib/unicorn/launcher.rb +62 -0
  68. data/lib/unicorn/oob_gc.rb +81 -0
  69. data/lib/unicorn/preread_input.rb +33 -0
  70. data/lib/unicorn/select_waiter.rb +6 -0
  71. data/lib/unicorn/socket_helper.rb +185 -0
  72. data/lib/unicorn/stream_input.rb +151 -0
  73. data/lib/unicorn/tee_input.rb +131 -0
  74. data/lib/unicorn/tmpio.rb +33 -0
  75. data/lib/unicorn/util.rb +90 -0
  76. data/lib/unicorn/version.rb +1 -0
  77. data/lib/unicorn/worker.rb +165 -0
  78. data/lib/unicorn.rb +136 -0
  79. data/man/man1/unicorn.1 +222 -0
  80. data/man/man1/unicorn_rails.1 +207 -0
  81. data/setup.rb +1586 -0
  82. data/t/.gitignore +4 -0
  83. data/t/GNUmakefile +5 -0
  84. data/t/README +49 -0
  85. data/t/active-unix-socket.t +117 -0
  86. data/t/bin/unused_listen +40 -0
  87. data/t/broken-app.ru +12 -0
  88. data/t/client_body_buffer_size.ru +14 -0
  89. data/t/client_body_buffer_size.t +80 -0
  90. data/t/detach.ru +11 -0
  91. data/t/env.ru +3 -0
  92. data/t/fails-rack-lint.ru +5 -0
  93. data/t/heartbeat-timeout.ru +12 -0
  94. data/t/heartbeat-timeout.t +62 -0
  95. data/t/integration.ru +115 -0
  96. data/t/integration.t +356 -0
  97. data/t/lib.perl +258 -0
  98. data/t/listener_names.ru +4 -0
  99. data/t/my-tap-lib.sh +201 -0
  100. data/t/oob_gc.ru +17 -0
  101. data/t/oob_gc_path.ru +17 -0
  102. data/t/pid.ru +3 -0
  103. data/t/preread_input.ru +22 -0
  104. data/t/reload-bad-config.t +54 -0
  105. data/t/reopen-logs.ru +13 -0
  106. data/t/reopen-logs.t +39 -0
  107. data/t/t0008-back_out_of_upgrade.sh +110 -0
  108. data/t/t0009-broken-app.sh +56 -0
  109. data/t/t0010-reap-logging.sh +55 -0
  110. data/t/t0012-reload-empty-config.sh +86 -0
  111. data/t/t0013-rewindable-input-false.sh +24 -0
  112. data/t/t0013.ru +12 -0
  113. data/t/t0014-rewindable-input-true.sh +24 -0
  114. data/t/t0014.ru +12 -0
  115. data/t/t0015-configurator-internals.sh +25 -0
  116. data/t/t0020-at_exit-handler.sh +49 -0
  117. data/t/t0021-process_detach.sh +29 -0
  118. data/t/t0022-listener_names-preload_app.sh +32 -0
  119. data/t/t0300-no-default-middleware.sh +20 -0
  120. data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
  121. data/t/t0301.ru +13 -0
  122. data/t/t9001-oob_gc.sh +47 -0
  123. data/t/t9002-oob_gc-path.sh +75 -0
  124. data/t/test-lib.sh +125 -0
  125. data/t/winch_ttin.t +67 -0
  126. data/t/working_directory.t +94 -0
  127. data/test/aggregate.rb +15 -0
  128. data/test/benchmark/README +60 -0
  129. data/test/benchmark/dd.ru +18 -0
  130. data/test/benchmark/ddstream.ru +50 -0
  131. data/test/benchmark/readinput.ru +40 -0
  132. data/test/benchmark/stack.ru +8 -0
  133. data/test/benchmark/uconnect.perl +66 -0
  134. data/test/exec/README +5 -0
  135. data/test/exec/test_exec.rb +1029 -0
  136. data/test/test_helper.rb +306 -0
  137. data/test/unit/test_ccc.rb +91 -0
  138. data/test/unit/test_configurator.rb +175 -0
  139. data/test/unit/test_droplet.rb +28 -0
  140. data/test/unit/test_http_parser.rb +884 -0
  141. data/test/unit/test_http_parser_ng.rb +714 -0
  142. data/test/unit/test_request.rb +169 -0
  143. data/test/unit/test_server.rb +244 -0
  144. data/test/unit/test_signals.rb +188 -0
  145. data/test/unit/test_socket_helper.rb +159 -0
  146. data/test/unit/test_stream_input.rb +210 -0
  147. data/test/unit/test_tee_input.rb +303 -0
  148. data/test/unit/test_util.rb +131 -0
  149. data/test/unit/test_waiter.rb +34 -0
  150. data/unicorn.gemspec +48 -0
  151. metadata +275 -0
@@ -0,0 +1,4334 @@
1
+
2
+ #line 1 "unicorn_http.rl"
3
+ /**
4
+ * Copyright (c) 2009 Eric Wong (all bugs are Eric's fault)
5
+ * Copyright (c) 2005 Zed A. Shaw
6
+ * You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
7
+ * the GPLv2+ (GPLv3+ preferred)
8
+ */
9
+ #include "ruby.h"
10
+ #include "ext_help.h"
11
+ #include <assert.h>
12
+ #include <string.h>
13
+ #include <sys/types.h>
14
+ #include "common_field_optimization.h"
15
+ #include "global_variables.h"
16
+ #include "c_util.h"
17
+ #include "epollexclusive.h"
18
+
19
+ void init_unicorn_httpdate(void);
20
+
21
+ #define UH_FL_CHUNKED 0x1
22
+ #define UH_FL_HASBODY 0x2
23
+ #define UH_FL_INBODY 0x4
24
+ #define UH_FL_HASTRAILER 0x8
25
+ #define UH_FL_INTRAILER 0x10
26
+ #define UH_FL_INCHUNK 0x20
27
+ #define UH_FL_REQEOF 0x40
28
+ #define UH_FL_KAVERSION 0x80
29
+ #define UH_FL_HASHEADER 0x100
30
+ #define UH_FL_TO_CLEAR 0x200
31
+ #define UH_FL_RESSTART 0x400 /* for check_client_connection */
32
+ #define UH_FL_HIJACK 0x800
33
+ #define UH_FL_RES_CHUNK_VER (1U << 12)
34
+ #define UH_FL_RES_CHUNK_METHOD (1U << 13)
35
+
36
+ /* all of these flags need to be set for keepalive to be supported */
37
+ #define UH_FL_KEEPALIVE (UH_FL_KAVERSION | UH_FL_REQEOF | UH_FL_HASHEADER)
38
+
39
+ /* we can only chunk responses for non-HEAD HTTP/1.1 requests */
40
+ #define UH_FL_RES_CHUNKABLE (UH_FL_RES_CHUNK_VER | UH_FL_RES_CHUNK_METHOD)
41
+
42
+ static unsigned int MAX_HEADER_LEN = 1024 * (80 + 32); /* same as Mongrel */
43
+
44
+ /* this is only intended for use with Rainbows! */
45
+ static VALUE set_maxhdrlen(VALUE self, VALUE len)
46
+ {
47
+ return UINT2NUM(MAX_HEADER_LEN = NUM2UINT(len));
48
+ }
49
+
50
+ /* keep this small for other servers (e.g. yahns) since every client has one */
51
+ struct http_parser {
52
+ int cs; /* Ragel internal state */
53
+ unsigned int flags;
54
+ unsigned int mark;
55
+ unsigned int offset;
56
+ union { /* these 2 fields don't nest */
57
+ unsigned int field;
58
+ unsigned int query;
59
+ } start;
60
+ union {
61
+ unsigned int field_len; /* only used during header processing */
62
+ unsigned int dest_offset; /* only used during body processing */
63
+ } s;
64
+ VALUE buf;
65
+ VALUE env;
66
+ VALUE cont; /* Qfalse: unset, Qnil: ignored header, T_STRING: append */
67
+ union {
68
+ off_t content;
69
+ off_t chunk;
70
+ } len;
71
+ };
72
+
73
+ static ID id_set_backtrace, id_is_chunked_p;
74
+ static VALUE cHttpParser;
75
+
76
+ static void finalize_header(struct http_parser *hp);
77
+
78
+ static void parser_raise(VALUE klass, const char *msg)
79
+ {
80
+ VALUE exc = rb_exc_new2(klass, msg);
81
+ VALUE bt = rb_ary_new();
82
+
83
+ rb_funcall(exc, id_set_backtrace, 1, bt);
84
+ rb_exc_raise(exc);
85
+ }
86
+
87
+ static inline unsigned int ulong2uint(unsigned long n)
88
+ {
89
+ unsigned int i = (unsigned int)n;
90
+
91
+ if (sizeof(unsigned int) != sizeof(unsigned long)) {
92
+ if ((unsigned long)i != n) {
93
+ rb_raise(rb_eRangeError, "too large to be 32-bit uint: %lu", n);
94
+ }
95
+ }
96
+ return i;
97
+ }
98
+
99
+ #define REMAINING (unsigned long)(pe - p)
100
+ #define LEN(AT, FPC) (ulong2uint(FPC - buffer) - hp->AT)
101
+ #define MARK(M,FPC) (hp->M = ulong2uint((FPC) - buffer))
102
+ #define PTR_TO(F) (buffer + hp->F)
103
+ #define STR_NEW(M,FPC) rb_str_new(PTR_TO(M), LEN(M, FPC))
104
+ #define STRIPPED_STR_NEW(M,FPC) stripped_str_new(PTR_TO(M), LEN(M, FPC))
105
+
106
+ #define HP_FL_TEST(hp,fl) ((hp)->flags & (UH_FL_##fl))
107
+ #define HP_FL_SET(hp,fl) ((hp)->flags |= (UH_FL_##fl))
108
+ #define HP_FL_UNSET(hp,fl) ((hp)->flags &= ~(UH_FL_##fl))
109
+ #define HP_FL_ALL(hp,fl) (HP_FL_TEST(hp, fl) == (UH_FL_##fl))
110
+
111
+ static int is_lws(char c)
112
+ {
113
+ return (c == ' ' || c == '\t');
114
+ }
115
+
116
+ static VALUE stripped_str_new(const char *str, long len)
117
+ {
118
+ long end;
119
+
120
+ for (end = len - 1; end >= 0 && is_lws(str[end]); end--);
121
+
122
+ return rb_str_new(str, end + 1);
123
+ }
124
+
125
+ /*
126
+ * handles values of the "Connection:" header, keepalive is implied
127
+ * for HTTP/1.1 but needs to be explicitly enabled with HTTP/1.0
128
+ * Additionally, we require GET/HEAD requests to support keepalive.
129
+ */
130
+ static void hp_keepalive_connection(struct http_parser *hp, VALUE val)
131
+ {
132
+ if (STR_CSTR_CASE_EQ(val, "keep-alive")) {
133
+ /* basically have HTTP/1.0 masquerade as HTTP/1.1+ */
134
+ HP_FL_SET(hp, KAVERSION);
135
+ } else if (STR_CSTR_CASE_EQ(val, "close")) {
136
+ /*
137
+ * it doesn't matter what HTTP version or request method we have,
138
+ * if a client says "Connection: close", we disable keepalive
139
+ */
140
+ HP_FL_UNSET(hp, KAVERSION);
141
+ } else {
142
+ /*
143
+ * client could've sent anything, ignore it for now. Maybe
144
+ * "HP_FL_UNSET(hp, KAVERSION);" just in case?
145
+ * Raising an exception might be too mean...
146
+ */
147
+ }
148
+ }
149
+
150
+ static void
151
+ request_method(struct http_parser *hp, const char *ptr, size_t len)
152
+ {
153
+ VALUE v = rb_str_new(ptr, len);
154
+
155
+ if (len != 4 || memcmp(ptr, "HEAD", 4))
156
+ HP_FL_SET(hp, RES_CHUNK_METHOD);
157
+
158
+ rb_hash_aset(hp->env, g_request_method, v);
159
+ }
160
+
161
+ static void
162
+ http_version(struct http_parser *hp, const char *ptr, size_t len)
163
+ {
164
+ VALUE v;
165
+
166
+ HP_FL_SET(hp, HASHEADER);
167
+
168
+ if (CONST_MEM_EQ("HTTP/1.1", ptr, len)) {
169
+ /* HTTP/1.1 implies keepalive unless "Connection: close" is set */
170
+ HP_FL_SET(hp, KAVERSION);
171
+ HP_FL_SET(hp, RES_CHUNK_VER);
172
+ v = g_http_11;
173
+ } else if (CONST_MEM_EQ("HTTP/1.0", ptr, len)) {
174
+ v = g_http_10;
175
+ } else {
176
+ v = rb_str_new(ptr, len);
177
+ }
178
+ rb_hash_aset(hp->env, g_server_protocol, v);
179
+ rb_hash_aset(hp->env, g_http_version, v);
180
+ }
181
+
182
+ static inline void hp_invalid_if_trailer(struct http_parser *hp)
183
+ {
184
+ if (HP_FL_TEST(hp, INTRAILER))
185
+ parser_raise(eHttpParserError, "invalid Trailer");
186
+ }
187
+
188
+ static void write_cont_value(struct http_parser *hp,
189
+ char *buffer, const char *p)
190
+ {
191
+ char *vptr;
192
+ long end;
193
+ long len = LEN(mark, p);
194
+ long cont_len;
195
+
196
+ if (hp->cont == Qfalse)
197
+ parser_raise(eHttpParserError, "invalid continuation line");
198
+ if (NIL_P(hp->cont))
199
+ return; /* we're ignoring this header (probably Host:) */
200
+
201
+ assert(TYPE(hp->cont) == T_STRING && "continuation line is not a string");
202
+ assert(hp->mark > 0 && "impossible continuation line offset");
203
+
204
+ if (len == 0)
205
+ return;
206
+
207
+ cont_len = RSTRING_LEN(hp->cont);
208
+ if (cont_len > 0) {
209
+ --hp->mark;
210
+ len = LEN(mark, p);
211
+ }
212
+ vptr = PTR_TO(mark);
213
+
214
+ /* normalize tab to space */
215
+ if (cont_len > 0) {
216
+ assert((' ' == *vptr || '\t' == *vptr) && "invalid leading white space");
217
+ *vptr = ' ';
218
+ }
219
+
220
+ for (end = len - 1; end >= 0 && is_lws(vptr[end]); end--);
221
+ rb_str_buf_cat(hp->cont, vptr, end + 1);
222
+ }
223
+
224
+ static int is_chunked(VALUE v)
225
+ {
226
+ /* common case first */
227
+ if (STR_CSTR_CASE_EQ(v, "chunked"))
228
+ return 1;
229
+
230
+ /*
231
+ * call Ruby function in unicorn/http_request.rb to deal with unlikely
232
+ * comma-delimited case
233
+ */
234
+ return rb_funcall(cHttpParser, id_is_chunked_p, 1, v) != Qfalse;
235
+ }
236
+
237
+ static void write_value(struct http_parser *hp,
238
+ const char *buffer, const char *p)
239
+ {
240
+ VALUE f = find_common_field(PTR_TO(start.field), hp->s.field_len);
241
+ VALUE v;
242
+ VALUE e;
243
+
244
+ VALIDATE_MAX_LENGTH(LEN(mark, p), FIELD_VALUE);
245
+ v = LEN(mark, p) == 0 ? rb_str_buf_new(128) : STRIPPED_STR_NEW(mark, p);
246
+ if (NIL_P(f)) {
247
+ const char *field = PTR_TO(start.field);
248
+ size_t flen = hp->s.field_len;
249
+
250
+ VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
251
+
252
+ /*
253
+ * ignore "Version" headers since they conflict with the HTTP_VERSION
254
+ * rack env variable.
255
+ */
256
+ if (CONST_MEM_EQ("VERSION", field, flen)) {
257
+ hp->cont = Qnil;
258
+ return;
259
+ }
260
+ f = uncommon_field(field, flen);
261
+ } else if (f == g_http_connection) {
262
+ hp_keepalive_connection(hp, v);
263
+ } else if (f == g_content_length && !HP_FL_TEST(hp, CHUNKED)) {
264
+ if (hp->len.content)
265
+ parser_raise(eHttpParserError, "Content-Length already set");
266
+ hp->len.content = parse_length(RSTRING_PTR(v), RSTRING_LEN(v));
267
+ if (hp->len.content < 0)
268
+ parser_raise(eHttpParserError, "invalid Content-Length");
269
+ if (hp->len.content != 0)
270
+ HP_FL_SET(hp, HASBODY);
271
+ hp_invalid_if_trailer(hp);
272
+ } else if (f == g_http_transfer_encoding) {
273
+ if (is_chunked(v)) {
274
+ if (HP_FL_TEST(hp, CHUNKED))
275
+ /*
276
+ * RFC 7230 3.3.1:
277
+ * A sender MUST NOT apply chunked more than once to a message body
278
+ * (i.e., chunking an already chunked message is not allowed).
279
+ */
280
+ parser_raise(eHttpParserError, "Transfer-Encoding double chunked");
281
+
282
+ HP_FL_SET(hp, CHUNKED);
283
+ HP_FL_SET(hp, HASBODY);
284
+
285
+ /* RFC 7230 3.3.3, 3: favor chunked if Content-Length exists */
286
+ hp->len.content = 0;
287
+ } else if (HP_FL_TEST(hp, CHUNKED)) {
288
+ /*
289
+ * RFC 7230 3.3.3, point 3 states:
290
+ * If a Transfer-Encoding header field is present in a request and
291
+ * the chunked transfer coding is not the final encoding, the
292
+ * message body length cannot be determined reliably; the server
293
+ * MUST respond with the 400 (Bad Request) status code and then
294
+ * close the connection.
295
+ */
296
+ parser_raise(eHttpParserError, "invalid Transfer-Encoding");
297
+ }
298
+ hp_invalid_if_trailer(hp);
299
+ } else if (f == g_http_trailer) {
300
+ HP_FL_SET(hp, HASTRAILER);
301
+ hp_invalid_if_trailer(hp);
302
+ } else {
303
+ assert(TYPE(f) == T_STRING && "memoized object is not a string");
304
+ assert_frozen(f);
305
+ }
306
+
307
+ e = rb_hash_aref(hp->env, f);
308
+ if (NIL_P(e)) {
309
+ hp->cont = rb_hash_aset(hp->env, f, v);
310
+ } else if (f == g_http_host) {
311
+ /*
312
+ * ignored, absolute URLs in REQUEST_URI take precedence over
313
+ * the Host: header (ref: rfc 2616, section 5.2.1)
314
+ */
315
+ hp->cont = Qnil;
316
+ } else {
317
+ rb_str_buf_cat(e, ",", 1);
318
+ hp->cont = rb_str_buf_append(e, v);
319
+ }
320
+ }
321
+
322
+ /** Machine **/
323
+
324
+
325
+ #line 429 "unicorn_http.rl"
326
+
327
+
328
+ /** Data **/
329
+
330
+ #line 331 "unicorn_http.c"
331
+ static const int http_parser_start = 1;
332
+ static const int http_parser_first_final = 122;
333
+ static const int http_parser_error = 0;
334
+
335
+ static const int http_parser_en_ChunkedBody = 100;
336
+ static const int http_parser_en_ChunkedBody_chunk_chunk_end = 105;
337
+ static const int http_parser_en_Trailers = 114;
338
+ static const int http_parser_en_main = 1;
339
+
340
+
341
+ #line 433 "unicorn_http.rl"
342
+
343
+ static void http_parser_init(struct http_parser *hp)
344
+ {
345
+ int cs = 0;
346
+ hp->flags = 0;
347
+ hp->mark = 0;
348
+ hp->offset = 0;
349
+ hp->start.field = 0;
350
+ hp->s.field_len = 0;
351
+ hp->len.content = 0;
352
+ hp->cont = Qfalse; /* zero on MRI, should be optimized away by above */
353
+
354
+ #line 355 "unicorn_http.c"
355
+ {
356
+ cs = http_parser_start;
357
+ }
358
+
359
+ #line 445 "unicorn_http.rl"
360
+ hp->cs = cs;
361
+ }
362
+
363
+ /** exec **/
364
+ static void
365
+ http_parser_execute(struct http_parser *hp, char *buffer, size_t len)
366
+ {
367
+ const char *p, *pe;
368
+ int cs = hp->cs;
369
+ size_t off = hp->offset;
370
+
371
+ if (cs == http_parser_first_final)
372
+ return;
373
+
374
+ assert(off <= len && "offset past end of buffer");
375
+
376
+ p = buffer+off;
377
+ pe = buffer+len;
378
+
379
+ assert((void *)(pe - p) == (void *)(len - off) &&
380
+ "pointers aren't same distance");
381
+
382
+ if (HP_FL_TEST(hp, INCHUNK)) {
383
+ HP_FL_UNSET(hp, INCHUNK);
384
+ goto skip_chunk_data_hack;
385
+ }
386
+
387
+ #line 388 "unicorn_http.c"
388
+ {
389
+ if ( p == pe )
390
+ goto _test_eof;
391
+ switch ( cs )
392
+ {
393
+ case 1:
394
+ switch( (*p) ) {
395
+ case 33: goto tr0;
396
+ case 71: goto tr2;
397
+ case 124: goto tr0;
398
+ case 126: goto tr0;
399
+ }
400
+ if ( (*p) < 45 ) {
401
+ if ( (*p) > 39 ) {
402
+ if ( 42 <= (*p) && (*p) <= 43 )
403
+ goto tr0;
404
+ } else if ( (*p) >= 35 )
405
+ goto tr0;
406
+ } else if ( (*p) > 46 ) {
407
+ if ( (*p) < 65 ) {
408
+ if ( 48 <= (*p) && (*p) <= 57 )
409
+ goto tr0;
410
+ } else if ( (*p) > 90 ) {
411
+ if ( 94 <= (*p) && (*p) <= 122 )
412
+ goto tr0;
413
+ } else
414
+ goto tr0;
415
+ } else
416
+ goto tr0;
417
+ goto st0;
418
+ st0:
419
+ cs = 0;
420
+ goto _out;
421
+ tr0:
422
+ #line 325 "unicorn_http.rl"
423
+ {MARK(mark, p); }
424
+ goto st2;
425
+ st2:
426
+ if ( ++p == pe )
427
+ goto _test_eof2;
428
+ case 2:
429
+ #line 430 "unicorn_http.c"
430
+ switch( (*p) ) {
431
+ case 32: goto tr3;
432
+ case 33: goto st49;
433
+ case 124: goto st49;
434
+ case 126: goto st49;
435
+ }
436
+ if ( (*p) < 45 ) {
437
+ if ( (*p) > 39 ) {
438
+ if ( 42 <= (*p) && (*p) <= 43 )
439
+ goto st49;
440
+ } else if ( (*p) >= 35 )
441
+ goto st49;
442
+ } else if ( (*p) > 46 ) {
443
+ if ( (*p) < 65 ) {
444
+ if ( 48 <= (*p) && (*p) <= 57 )
445
+ goto st49;
446
+ } else if ( (*p) > 90 ) {
447
+ if ( 94 <= (*p) && (*p) <= 122 )
448
+ goto st49;
449
+ } else
450
+ goto st49;
451
+ } else
452
+ goto st49;
453
+ goto st0;
454
+ tr3:
455
+ #line 334 "unicorn_http.rl"
456
+ { request_method(hp, PTR_TO(mark), LEN(mark, p)); }
457
+ goto st3;
458
+ st3:
459
+ if ( ++p == pe )
460
+ goto _test_eof3;
461
+ case 3:
462
+ #line 463 "unicorn_http.c"
463
+ switch( (*p) ) {
464
+ case 42: goto tr5;
465
+ case 47: goto tr6;
466
+ case 72: goto tr7;
467
+ case 104: goto tr7;
468
+ }
469
+ goto st0;
470
+ tr5:
471
+ #line 325 "unicorn_http.rl"
472
+ {MARK(mark, p); }
473
+ goto st4;
474
+ st4:
475
+ if ( ++p == pe )
476
+ goto _test_eof4;
477
+ case 4:
478
+ #line 479 "unicorn_http.c"
479
+ switch( (*p) ) {
480
+ case 32: goto tr8;
481
+ case 35: goto tr9;
482
+ }
483
+ goto st0;
484
+ tr8:
485
+ #line 339 "unicorn_http.rl"
486
+ {
487
+ VALUE str;
488
+
489
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
490
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
491
+ /*
492
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
493
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
494
+ */
495
+ if (STR_CSTR_EQ(str, "*")) {
496
+ str = rb_str_new(NULL, 0);
497
+ rb_hash_aset(hp->env, g_path_info, str);
498
+ rb_hash_aset(hp->env, g_request_path, str);
499
+ }
500
+ }
501
+ goto st5;
502
+ tr42:
503
+ #line 325 "unicorn_http.rl"
504
+ {MARK(mark, p); }
505
+ #line 354 "unicorn_http.rl"
506
+ {
507
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
508
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
509
+ }
510
+ goto st5;
511
+ tr45:
512
+ #line 354 "unicorn_http.rl"
513
+ {
514
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
515
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
516
+ }
517
+ goto st5;
518
+ tr49:
519
+ #line 364 "unicorn_http.rl"
520
+ {
521
+ VALUE val;
522
+
523
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
524
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
525
+
526
+ /* rack says PATH_INFO must start with "/" or be empty */
527
+ if (!STR_CSTR_EQ(val, "*"))
528
+ rb_hash_aset(hp->env, g_path_info, val);
529
+ }
530
+ #line 339 "unicorn_http.rl"
531
+ {
532
+ VALUE str;
533
+
534
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
535
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
536
+ /*
537
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
538
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
539
+ */
540
+ if (STR_CSTR_EQ(str, "*")) {
541
+ str = rb_str_new(NULL, 0);
542
+ rb_hash_aset(hp->env, g_path_info, str);
543
+ rb_hash_aset(hp->env, g_request_path, str);
544
+ }
545
+ }
546
+ goto st5;
547
+ tr55:
548
+ #line 358 "unicorn_http.rl"
549
+ {MARK(start.query, p); }
550
+ #line 359 "unicorn_http.rl"
551
+ {
552
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
553
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
554
+ }
555
+ #line 339 "unicorn_http.rl"
556
+ {
557
+ VALUE str;
558
+
559
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
560
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
561
+ /*
562
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
563
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
564
+ */
565
+ if (STR_CSTR_EQ(str, "*")) {
566
+ str = rb_str_new(NULL, 0);
567
+ rb_hash_aset(hp->env, g_path_info, str);
568
+ rb_hash_aset(hp->env, g_request_path, str);
569
+ }
570
+ }
571
+ goto st5;
572
+ tr59:
573
+ #line 359 "unicorn_http.rl"
574
+ {
575
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
576
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
577
+ }
578
+ #line 339 "unicorn_http.rl"
579
+ {
580
+ VALUE str;
581
+
582
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
583
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
584
+ /*
585
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
586
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
587
+ */
588
+ if (STR_CSTR_EQ(str, "*")) {
589
+ str = rb_str_new(NULL, 0);
590
+ rb_hash_aset(hp->env, g_path_info, str);
591
+ rb_hash_aset(hp->env, g_request_path, str);
592
+ }
593
+ }
594
+ goto st5;
595
+ st5:
596
+ if ( ++p == pe )
597
+ goto _test_eof5;
598
+ case 5:
599
+ #line 600 "unicorn_http.c"
600
+ if ( (*p) == 72 )
601
+ goto tr10;
602
+ goto st0;
603
+ tr10:
604
+ #line 325 "unicorn_http.rl"
605
+ {MARK(mark, p); }
606
+ goto st6;
607
+ st6:
608
+ if ( ++p == pe )
609
+ goto _test_eof6;
610
+ case 6:
611
+ #line 612 "unicorn_http.c"
612
+ if ( (*p) == 84 )
613
+ goto st7;
614
+ goto st0;
615
+ st7:
616
+ if ( ++p == pe )
617
+ goto _test_eof7;
618
+ case 7:
619
+ if ( (*p) == 84 )
620
+ goto st8;
621
+ goto st0;
622
+ st8:
623
+ if ( ++p == pe )
624
+ goto _test_eof8;
625
+ case 8:
626
+ if ( (*p) == 80 )
627
+ goto st9;
628
+ goto st0;
629
+ st9:
630
+ if ( ++p == pe )
631
+ goto _test_eof9;
632
+ case 9:
633
+ if ( (*p) == 47 )
634
+ goto st10;
635
+ goto st0;
636
+ st10:
637
+ if ( ++p == pe )
638
+ goto _test_eof10;
639
+ case 10:
640
+ if ( 48 <= (*p) && (*p) <= 57 )
641
+ goto st11;
642
+ goto st0;
643
+ st11:
644
+ if ( ++p == pe )
645
+ goto _test_eof11;
646
+ case 11:
647
+ if ( (*p) == 46 )
648
+ goto st12;
649
+ if ( 48 <= (*p) && (*p) <= 57 )
650
+ goto st11;
651
+ goto st0;
652
+ st12:
653
+ if ( ++p == pe )
654
+ goto _test_eof12;
655
+ case 12:
656
+ if ( 48 <= (*p) && (*p) <= 57 )
657
+ goto st13;
658
+ goto st0;
659
+ st13:
660
+ if ( ++p == pe )
661
+ goto _test_eof13;
662
+ case 13:
663
+ switch( (*p) ) {
664
+ case 10: goto tr18;
665
+ case 13: goto tr19;
666
+ }
667
+ if ( 48 <= (*p) && (*p) <= 57 )
668
+ goto st13;
669
+ goto st0;
670
+ tr18:
671
+ #line 363 "unicorn_http.rl"
672
+ { http_version(hp, PTR_TO(mark), LEN(mark, p)); }
673
+ goto st14;
674
+ tr26:
675
+ #line 331 "unicorn_http.rl"
676
+ { MARK(mark, p); }
677
+ #line 333 "unicorn_http.rl"
678
+ { write_cont_value(hp, buffer, p); }
679
+ goto st14;
680
+ tr29:
681
+ #line 333 "unicorn_http.rl"
682
+ { write_cont_value(hp, buffer, p); }
683
+ goto st14;
684
+ tr36:
685
+ #line 331 "unicorn_http.rl"
686
+ { MARK(mark, p); }
687
+ #line 332 "unicorn_http.rl"
688
+ { write_value(hp, buffer, p); }
689
+ goto st14;
690
+ tr39:
691
+ #line 332 "unicorn_http.rl"
692
+ { write_value(hp, buffer, p); }
693
+ goto st14;
694
+ st14:
695
+ if ( ++p == pe )
696
+ goto _test_eof14;
697
+ case 14:
698
+ #line 699 "unicorn_http.c"
699
+ switch( (*p) ) {
700
+ case 9: goto st15;
701
+ case 10: goto tr21;
702
+ case 13: goto st18;
703
+ case 32: goto st15;
704
+ case 33: goto tr23;
705
+ case 124: goto tr23;
706
+ case 126: goto tr23;
707
+ }
708
+ if ( (*p) < 45 ) {
709
+ if ( (*p) > 39 ) {
710
+ if ( 42 <= (*p) && (*p) <= 43 )
711
+ goto tr23;
712
+ } else if ( (*p) >= 35 )
713
+ goto tr23;
714
+ } else if ( (*p) > 46 ) {
715
+ if ( (*p) < 65 ) {
716
+ if ( 48 <= (*p) && (*p) <= 57 )
717
+ goto tr23;
718
+ } else if ( (*p) > 90 ) {
719
+ if ( 94 <= (*p) && (*p) <= 122 )
720
+ goto tr23;
721
+ } else
722
+ goto tr23;
723
+ } else
724
+ goto tr23;
725
+ goto st0;
726
+ tr25:
727
+ #line 331 "unicorn_http.rl"
728
+ { MARK(mark, p); }
729
+ goto st15;
730
+ st15:
731
+ if ( ++p == pe )
732
+ goto _test_eof15;
733
+ case 15:
734
+ #line 735 "unicorn_http.c"
735
+ switch( (*p) ) {
736
+ case 9: goto tr25;
737
+ case 10: goto tr26;
738
+ case 13: goto tr27;
739
+ case 32: goto tr25;
740
+ case 127: goto st0;
741
+ }
742
+ if ( 0 <= (*p) && (*p) <= 31 )
743
+ goto st0;
744
+ goto tr24;
745
+ tr24:
746
+ #line 331 "unicorn_http.rl"
747
+ { MARK(mark, p); }
748
+ goto st16;
749
+ st16:
750
+ if ( ++p == pe )
751
+ goto _test_eof16;
752
+ case 16:
753
+ #line 754 "unicorn_http.c"
754
+ switch( (*p) ) {
755
+ case 10: goto tr29;
756
+ case 13: goto tr30;
757
+ case 127: goto st0;
758
+ }
759
+ if ( (*p) > 8 ) {
760
+ if ( 11 <= (*p) && (*p) <= 31 )
761
+ goto st0;
762
+ } else if ( (*p) >= 0 )
763
+ goto st0;
764
+ goto st16;
765
+ tr19:
766
+ #line 363 "unicorn_http.rl"
767
+ { http_version(hp, PTR_TO(mark), LEN(mark, p)); }
768
+ goto st17;
769
+ tr27:
770
+ #line 331 "unicorn_http.rl"
771
+ { MARK(mark, p); }
772
+ #line 333 "unicorn_http.rl"
773
+ { write_cont_value(hp, buffer, p); }
774
+ goto st17;
775
+ tr30:
776
+ #line 333 "unicorn_http.rl"
777
+ { write_cont_value(hp, buffer, p); }
778
+ goto st17;
779
+ tr37:
780
+ #line 331 "unicorn_http.rl"
781
+ { MARK(mark, p); }
782
+ #line 332 "unicorn_http.rl"
783
+ { write_value(hp, buffer, p); }
784
+ goto st17;
785
+ tr40:
786
+ #line 332 "unicorn_http.rl"
787
+ { write_value(hp, buffer, p); }
788
+ goto st17;
789
+ st17:
790
+ if ( ++p == pe )
791
+ goto _test_eof17;
792
+ case 17:
793
+ #line 794 "unicorn_http.c"
794
+ if ( (*p) == 10 )
795
+ goto st14;
796
+ goto st0;
797
+ tr21:
798
+ #line 379 "unicorn_http.rl"
799
+ {
800
+ finalize_header(hp);
801
+
802
+ cs = http_parser_first_final;
803
+ if (HP_FL_TEST(hp, HASBODY)) {
804
+ HP_FL_SET(hp, INBODY);
805
+ if (HP_FL_TEST(hp, CHUNKED))
806
+ cs = http_parser_en_ChunkedBody;
807
+ } else {
808
+ HP_FL_SET(hp, REQEOF);
809
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
810
+ }
811
+ /*
812
+ * go back to Ruby so we can call the Rack application, we'll reenter
813
+ * the parser iff the body needs to be processed.
814
+ */
815
+ goto post_exec;
816
+ }
817
+ goto st122;
818
+ tr104:
819
+ #line 339 "unicorn_http.rl"
820
+ {
821
+ VALUE str;
822
+
823
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
824
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
825
+ /*
826
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
827
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
828
+ */
829
+ if (STR_CSTR_EQ(str, "*")) {
830
+ str = rb_str_new(NULL, 0);
831
+ rb_hash_aset(hp->env, g_path_info, str);
832
+ rb_hash_aset(hp->env, g_request_path, str);
833
+ }
834
+ }
835
+ #line 379 "unicorn_http.rl"
836
+ {
837
+ finalize_header(hp);
838
+
839
+ cs = http_parser_first_final;
840
+ if (HP_FL_TEST(hp, HASBODY)) {
841
+ HP_FL_SET(hp, INBODY);
842
+ if (HP_FL_TEST(hp, CHUNKED))
843
+ cs = http_parser_en_ChunkedBody;
844
+ } else {
845
+ HP_FL_SET(hp, REQEOF);
846
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
847
+ }
848
+ /*
849
+ * go back to Ruby so we can call the Rack application, we'll reenter
850
+ * the parser iff the body needs to be processed.
851
+ */
852
+ goto post_exec;
853
+ }
854
+ goto st122;
855
+ tr108:
856
+ #line 325 "unicorn_http.rl"
857
+ {MARK(mark, p); }
858
+ #line 354 "unicorn_http.rl"
859
+ {
860
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
861
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
862
+ }
863
+ #line 379 "unicorn_http.rl"
864
+ {
865
+ finalize_header(hp);
866
+
867
+ cs = http_parser_first_final;
868
+ if (HP_FL_TEST(hp, HASBODY)) {
869
+ HP_FL_SET(hp, INBODY);
870
+ if (HP_FL_TEST(hp, CHUNKED))
871
+ cs = http_parser_en_ChunkedBody;
872
+ } else {
873
+ HP_FL_SET(hp, REQEOF);
874
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
875
+ }
876
+ /*
877
+ * go back to Ruby so we can call the Rack application, we'll reenter
878
+ * the parser iff the body needs to be processed.
879
+ */
880
+ goto post_exec;
881
+ }
882
+ goto st122;
883
+ tr112:
884
+ #line 354 "unicorn_http.rl"
885
+ {
886
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
887
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
888
+ }
889
+ #line 379 "unicorn_http.rl"
890
+ {
891
+ finalize_header(hp);
892
+
893
+ cs = http_parser_first_final;
894
+ if (HP_FL_TEST(hp, HASBODY)) {
895
+ HP_FL_SET(hp, INBODY);
896
+ if (HP_FL_TEST(hp, CHUNKED))
897
+ cs = http_parser_en_ChunkedBody;
898
+ } else {
899
+ HP_FL_SET(hp, REQEOF);
900
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
901
+ }
902
+ /*
903
+ * go back to Ruby so we can call the Rack application, we'll reenter
904
+ * the parser iff the body needs to be processed.
905
+ */
906
+ goto post_exec;
907
+ }
908
+ goto st122;
909
+ tr117:
910
+ #line 364 "unicorn_http.rl"
911
+ {
912
+ VALUE val;
913
+
914
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
915
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
916
+
917
+ /* rack says PATH_INFO must start with "/" or be empty */
918
+ if (!STR_CSTR_EQ(val, "*"))
919
+ rb_hash_aset(hp->env, g_path_info, val);
920
+ }
921
+ #line 339 "unicorn_http.rl"
922
+ {
923
+ VALUE str;
924
+
925
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
926
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
927
+ /*
928
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
929
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
930
+ */
931
+ if (STR_CSTR_EQ(str, "*")) {
932
+ str = rb_str_new(NULL, 0);
933
+ rb_hash_aset(hp->env, g_path_info, str);
934
+ rb_hash_aset(hp->env, g_request_path, str);
935
+ }
936
+ }
937
+ #line 379 "unicorn_http.rl"
938
+ {
939
+ finalize_header(hp);
940
+
941
+ cs = http_parser_first_final;
942
+ if (HP_FL_TEST(hp, HASBODY)) {
943
+ HP_FL_SET(hp, INBODY);
944
+ if (HP_FL_TEST(hp, CHUNKED))
945
+ cs = http_parser_en_ChunkedBody;
946
+ } else {
947
+ HP_FL_SET(hp, REQEOF);
948
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
949
+ }
950
+ /*
951
+ * go back to Ruby so we can call the Rack application, we'll reenter
952
+ * the parser iff the body needs to be processed.
953
+ */
954
+ goto post_exec;
955
+ }
956
+ goto st122;
957
+ tr124:
958
+ #line 358 "unicorn_http.rl"
959
+ {MARK(start.query, p); }
960
+ #line 359 "unicorn_http.rl"
961
+ {
962
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
963
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
964
+ }
965
+ #line 339 "unicorn_http.rl"
966
+ {
967
+ VALUE str;
968
+
969
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
970
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
971
+ /*
972
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
973
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
974
+ */
975
+ if (STR_CSTR_EQ(str, "*")) {
976
+ str = rb_str_new(NULL, 0);
977
+ rb_hash_aset(hp->env, g_path_info, str);
978
+ rb_hash_aset(hp->env, g_request_path, str);
979
+ }
980
+ }
981
+ #line 379 "unicorn_http.rl"
982
+ {
983
+ finalize_header(hp);
984
+
985
+ cs = http_parser_first_final;
986
+ if (HP_FL_TEST(hp, HASBODY)) {
987
+ HP_FL_SET(hp, INBODY);
988
+ if (HP_FL_TEST(hp, CHUNKED))
989
+ cs = http_parser_en_ChunkedBody;
990
+ } else {
991
+ HP_FL_SET(hp, REQEOF);
992
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
993
+ }
994
+ /*
995
+ * go back to Ruby so we can call the Rack application, we'll reenter
996
+ * the parser iff the body needs to be processed.
997
+ */
998
+ goto post_exec;
999
+ }
1000
+ goto st122;
1001
+ tr129:
1002
+ #line 359 "unicorn_http.rl"
1003
+ {
1004
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
1005
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
1006
+ }
1007
+ #line 339 "unicorn_http.rl"
1008
+ {
1009
+ VALUE str;
1010
+
1011
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1012
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1013
+ /*
1014
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1015
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1016
+ */
1017
+ if (STR_CSTR_EQ(str, "*")) {
1018
+ str = rb_str_new(NULL, 0);
1019
+ rb_hash_aset(hp->env, g_path_info, str);
1020
+ rb_hash_aset(hp->env, g_request_path, str);
1021
+ }
1022
+ }
1023
+ #line 379 "unicorn_http.rl"
1024
+ {
1025
+ finalize_header(hp);
1026
+
1027
+ cs = http_parser_first_final;
1028
+ if (HP_FL_TEST(hp, HASBODY)) {
1029
+ HP_FL_SET(hp, INBODY);
1030
+ if (HP_FL_TEST(hp, CHUNKED))
1031
+ cs = http_parser_en_ChunkedBody;
1032
+ } else {
1033
+ HP_FL_SET(hp, REQEOF);
1034
+ assert(!HP_FL_TEST(hp, CHUNKED) && "chunked encoding without body!");
1035
+ }
1036
+ /*
1037
+ * go back to Ruby so we can call the Rack application, we'll reenter
1038
+ * the parser iff the body needs to be processed.
1039
+ */
1040
+ goto post_exec;
1041
+ }
1042
+ goto st122;
1043
+ st122:
1044
+ if ( ++p == pe )
1045
+ goto _test_eof122;
1046
+ case 122:
1047
+ #line 1048 "unicorn_http.c"
1048
+ goto st0;
1049
+ tr105:
1050
+ #line 339 "unicorn_http.rl"
1051
+ {
1052
+ VALUE str;
1053
+
1054
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1055
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1056
+ /*
1057
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1058
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1059
+ */
1060
+ if (STR_CSTR_EQ(str, "*")) {
1061
+ str = rb_str_new(NULL, 0);
1062
+ rb_hash_aset(hp->env, g_path_info, str);
1063
+ rb_hash_aset(hp->env, g_request_path, str);
1064
+ }
1065
+ }
1066
+ goto st18;
1067
+ tr109:
1068
+ #line 325 "unicorn_http.rl"
1069
+ {MARK(mark, p); }
1070
+ #line 354 "unicorn_http.rl"
1071
+ {
1072
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
1073
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
1074
+ }
1075
+ goto st18;
1076
+ tr113:
1077
+ #line 354 "unicorn_http.rl"
1078
+ {
1079
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), FRAGMENT);
1080
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, p));
1081
+ }
1082
+ goto st18;
1083
+ tr118:
1084
+ #line 364 "unicorn_http.rl"
1085
+ {
1086
+ VALUE val;
1087
+
1088
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
1089
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
1090
+
1091
+ /* rack says PATH_INFO must start with "/" or be empty */
1092
+ if (!STR_CSTR_EQ(val, "*"))
1093
+ rb_hash_aset(hp->env, g_path_info, val);
1094
+ }
1095
+ #line 339 "unicorn_http.rl"
1096
+ {
1097
+ VALUE str;
1098
+
1099
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1100
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1101
+ /*
1102
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1103
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1104
+ */
1105
+ if (STR_CSTR_EQ(str, "*")) {
1106
+ str = rb_str_new(NULL, 0);
1107
+ rb_hash_aset(hp->env, g_path_info, str);
1108
+ rb_hash_aset(hp->env, g_request_path, str);
1109
+ }
1110
+ }
1111
+ goto st18;
1112
+ tr125:
1113
+ #line 358 "unicorn_http.rl"
1114
+ {MARK(start.query, p); }
1115
+ #line 359 "unicorn_http.rl"
1116
+ {
1117
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
1118
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
1119
+ }
1120
+ #line 339 "unicorn_http.rl"
1121
+ {
1122
+ VALUE str;
1123
+
1124
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1125
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1126
+ /*
1127
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1128
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1129
+ */
1130
+ if (STR_CSTR_EQ(str, "*")) {
1131
+ str = rb_str_new(NULL, 0);
1132
+ rb_hash_aset(hp->env, g_path_info, str);
1133
+ rb_hash_aset(hp->env, g_request_path, str);
1134
+ }
1135
+ }
1136
+ goto st18;
1137
+ tr130:
1138
+ #line 359 "unicorn_http.rl"
1139
+ {
1140
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
1141
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
1142
+ }
1143
+ #line 339 "unicorn_http.rl"
1144
+ {
1145
+ VALUE str;
1146
+
1147
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1148
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1149
+ /*
1150
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1151
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1152
+ */
1153
+ if (STR_CSTR_EQ(str, "*")) {
1154
+ str = rb_str_new(NULL, 0);
1155
+ rb_hash_aset(hp->env, g_path_info, str);
1156
+ rb_hash_aset(hp->env, g_request_path, str);
1157
+ }
1158
+ }
1159
+ goto st18;
1160
+ st18:
1161
+ if ( ++p == pe )
1162
+ goto _test_eof18;
1163
+ case 18:
1164
+ #line 1165 "unicorn_http.c"
1165
+ if ( (*p) == 10 )
1166
+ goto tr21;
1167
+ goto st0;
1168
+ tr23:
1169
+ #line 327 "unicorn_http.rl"
1170
+ { MARK(start.field, p); }
1171
+ #line 328 "unicorn_http.rl"
1172
+ { snake_upcase_char(deconst(p)); }
1173
+ goto st19;
1174
+ tr32:
1175
+ #line 328 "unicorn_http.rl"
1176
+ { snake_upcase_char(deconst(p)); }
1177
+ goto st19;
1178
+ st19:
1179
+ if ( ++p == pe )
1180
+ goto _test_eof19;
1181
+ case 19:
1182
+ #line 1183 "unicorn_http.c"
1183
+ switch( (*p) ) {
1184
+ case 33: goto tr32;
1185
+ case 58: goto tr33;
1186
+ case 124: goto tr32;
1187
+ case 126: goto tr32;
1188
+ }
1189
+ if ( (*p) < 45 ) {
1190
+ if ( (*p) > 39 ) {
1191
+ if ( 42 <= (*p) && (*p) <= 43 )
1192
+ goto tr32;
1193
+ } else if ( (*p) >= 35 )
1194
+ goto tr32;
1195
+ } else if ( (*p) > 46 ) {
1196
+ if ( (*p) < 65 ) {
1197
+ if ( 48 <= (*p) && (*p) <= 57 )
1198
+ goto tr32;
1199
+ } else if ( (*p) > 90 ) {
1200
+ if ( 94 <= (*p) && (*p) <= 122 )
1201
+ goto tr32;
1202
+ } else
1203
+ goto tr32;
1204
+ } else
1205
+ goto tr32;
1206
+ goto st0;
1207
+ tr35:
1208
+ #line 331 "unicorn_http.rl"
1209
+ { MARK(mark, p); }
1210
+ goto st20;
1211
+ tr33:
1212
+ #line 330 "unicorn_http.rl"
1213
+ { hp->s.field_len = LEN(start.field, p); }
1214
+ goto st20;
1215
+ st20:
1216
+ if ( ++p == pe )
1217
+ goto _test_eof20;
1218
+ case 20:
1219
+ #line 1220 "unicorn_http.c"
1220
+ switch( (*p) ) {
1221
+ case 9: goto tr35;
1222
+ case 10: goto tr36;
1223
+ case 13: goto tr37;
1224
+ case 32: goto tr35;
1225
+ case 127: goto st0;
1226
+ }
1227
+ if ( 0 <= (*p) && (*p) <= 31 )
1228
+ goto st0;
1229
+ goto tr34;
1230
+ tr34:
1231
+ #line 331 "unicorn_http.rl"
1232
+ { MARK(mark, p); }
1233
+ goto st21;
1234
+ st21:
1235
+ if ( ++p == pe )
1236
+ goto _test_eof21;
1237
+ case 21:
1238
+ #line 1239 "unicorn_http.c"
1239
+ switch( (*p) ) {
1240
+ case 10: goto tr39;
1241
+ case 13: goto tr40;
1242
+ case 127: goto st0;
1243
+ }
1244
+ if ( (*p) > 8 ) {
1245
+ if ( 11 <= (*p) && (*p) <= 31 )
1246
+ goto st0;
1247
+ } else if ( (*p) >= 0 )
1248
+ goto st0;
1249
+ goto st21;
1250
+ tr9:
1251
+ #line 339 "unicorn_http.rl"
1252
+ {
1253
+ VALUE str;
1254
+
1255
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1256
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1257
+ /*
1258
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1259
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1260
+ */
1261
+ if (STR_CSTR_EQ(str, "*")) {
1262
+ str = rb_str_new(NULL, 0);
1263
+ rb_hash_aset(hp->env, g_path_info, str);
1264
+ rb_hash_aset(hp->env, g_request_path, str);
1265
+ }
1266
+ }
1267
+ goto st22;
1268
+ tr50:
1269
+ #line 364 "unicorn_http.rl"
1270
+ {
1271
+ VALUE val;
1272
+
1273
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
1274
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
1275
+
1276
+ /* rack says PATH_INFO must start with "/" or be empty */
1277
+ if (!STR_CSTR_EQ(val, "*"))
1278
+ rb_hash_aset(hp->env, g_path_info, val);
1279
+ }
1280
+ #line 339 "unicorn_http.rl"
1281
+ {
1282
+ VALUE str;
1283
+
1284
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1285
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1286
+ /*
1287
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1288
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1289
+ */
1290
+ if (STR_CSTR_EQ(str, "*")) {
1291
+ str = rb_str_new(NULL, 0);
1292
+ rb_hash_aset(hp->env, g_path_info, str);
1293
+ rb_hash_aset(hp->env, g_request_path, str);
1294
+ }
1295
+ }
1296
+ goto st22;
1297
+ tr56:
1298
+ #line 358 "unicorn_http.rl"
1299
+ {MARK(start.query, p); }
1300
+ #line 359 "unicorn_http.rl"
1301
+ {
1302
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
1303
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
1304
+ }
1305
+ #line 339 "unicorn_http.rl"
1306
+ {
1307
+ VALUE str;
1308
+
1309
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1310
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1311
+ /*
1312
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1313
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1314
+ */
1315
+ if (STR_CSTR_EQ(str, "*")) {
1316
+ str = rb_str_new(NULL, 0);
1317
+ rb_hash_aset(hp->env, g_path_info, str);
1318
+ rb_hash_aset(hp->env, g_request_path, str);
1319
+ }
1320
+ }
1321
+ goto st22;
1322
+ tr60:
1323
+ #line 359 "unicorn_http.rl"
1324
+ {
1325
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
1326
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
1327
+ }
1328
+ #line 339 "unicorn_http.rl"
1329
+ {
1330
+ VALUE str;
1331
+
1332
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
1333
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
1334
+ /*
1335
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
1336
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
1337
+ */
1338
+ if (STR_CSTR_EQ(str, "*")) {
1339
+ str = rb_str_new(NULL, 0);
1340
+ rb_hash_aset(hp->env, g_path_info, str);
1341
+ rb_hash_aset(hp->env, g_request_path, str);
1342
+ }
1343
+ }
1344
+ goto st22;
1345
+ st22:
1346
+ if ( ++p == pe )
1347
+ goto _test_eof22;
1348
+ case 22:
1349
+ #line 1350 "unicorn_http.c"
1350
+ switch( (*p) ) {
1351
+ case 32: goto tr42;
1352
+ case 35: goto st0;
1353
+ case 37: goto tr43;
1354
+ case 127: goto st0;
1355
+ }
1356
+ if ( 0 <= (*p) && (*p) <= 31 )
1357
+ goto st0;
1358
+ goto tr41;
1359
+ tr41:
1360
+ #line 325 "unicorn_http.rl"
1361
+ {MARK(mark, p); }
1362
+ goto st23;
1363
+ st23:
1364
+ if ( ++p == pe )
1365
+ goto _test_eof23;
1366
+ case 23:
1367
+ #line 1368 "unicorn_http.c"
1368
+ switch( (*p) ) {
1369
+ case 32: goto tr45;
1370
+ case 35: goto st0;
1371
+ case 37: goto st24;
1372
+ case 127: goto st0;
1373
+ }
1374
+ if ( 0 <= (*p) && (*p) <= 31 )
1375
+ goto st0;
1376
+ goto st23;
1377
+ tr43:
1378
+ #line 325 "unicorn_http.rl"
1379
+ {MARK(mark, p); }
1380
+ goto st24;
1381
+ st24:
1382
+ if ( ++p == pe )
1383
+ goto _test_eof24;
1384
+ case 24:
1385
+ #line 1386 "unicorn_http.c"
1386
+ if ( (*p) < 65 ) {
1387
+ if ( 48 <= (*p) && (*p) <= 57 )
1388
+ goto st25;
1389
+ } else if ( (*p) > 70 ) {
1390
+ if ( 97 <= (*p) && (*p) <= 102 )
1391
+ goto st25;
1392
+ } else
1393
+ goto st25;
1394
+ goto st0;
1395
+ st25:
1396
+ if ( ++p == pe )
1397
+ goto _test_eof25;
1398
+ case 25:
1399
+ if ( (*p) < 65 ) {
1400
+ if ( 48 <= (*p) && (*p) <= 57 )
1401
+ goto st23;
1402
+ } else if ( (*p) > 70 ) {
1403
+ if ( 97 <= (*p) && (*p) <= 102 )
1404
+ goto st23;
1405
+ } else
1406
+ goto st23;
1407
+ goto st0;
1408
+ tr6:
1409
+ #line 325 "unicorn_http.rl"
1410
+ {MARK(mark, p); }
1411
+ goto st26;
1412
+ tr76:
1413
+ #line 338 "unicorn_http.rl"
1414
+ { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
1415
+ #line 325 "unicorn_http.rl"
1416
+ {MARK(mark, p); }
1417
+ goto st26;
1418
+ st26:
1419
+ if ( ++p == pe )
1420
+ goto _test_eof26;
1421
+ case 26:
1422
+ #line 1423 "unicorn_http.c"
1423
+ switch( (*p) ) {
1424
+ case 32: goto tr49;
1425
+ case 35: goto tr50;
1426
+ case 37: goto st27;
1427
+ case 63: goto tr52;
1428
+ case 127: goto st0;
1429
+ }
1430
+ if ( 0 <= (*p) && (*p) <= 31 )
1431
+ goto st0;
1432
+ goto st26;
1433
+ st27:
1434
+ if ( ++p == pe )
1435
+ goto _test_eof27;
1436
+ case 27:
1437
+ if ( (*p) < 65 ) {
1438
+ if ( 48 <= (*p) && (*p) <= 57 )
1439
+ goto st28;
1440
+ } else if ( (*p) > 70 ) {
1441
+ if ( 97 <= (*p) && (*p) <= 102 )
1442
+ goto st28;
1443
+ } else
1444
+ goto st28;
1445
+ goto st0;
1446
+ st28:
1447
+ if ( ++p == pe )
1448
+ goto _test_eof28;
1449
+ case 28:
1450
+ if ( (*p) < 65 ) {
1451
+ if ( 48 <= (*p) && (*p) <= 57 )
1452
+ goto st26;
1453
+ } else if ( (*p) > 70 ) {
1454
+ if ( 97 <= (*p) && (*p) <= 102 )
1455
+ goto st26;
1456
+ } else
1457
+ goto st26;
1458
+ goto st0;
1459
+ tr52:
1460
+ #line 364 "unicorn_http.rl"
1461
+ {
1462
+ VALUE val;
1463
+
1464
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
1465
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
1466
+
1467
+ /* rack says PATH_INFO must start with "/" or be empty */
1468
+ if (!STR_CSTR_EQ(val, "*"))
1469
+ rb_hash_aset(hp->env, g_path_info, val);
1470
+ }
1471
+ goto st29;
1472
+ st29:
1473
+ if ( ++p == pe )
1474
+ goto _test_eof29;
1475
+ case 29:
1476
+ #line 1477 "unicorn_http.c"
1477
+ switch( (*p) ) {
1478
+ case 32: goto tr55;
1479
+ case 35: goto tr56;
1480
+ case 37: goto tr57;
1481
+ case 127: goto st0;
1482
+ }
1483
+ if ( 0 <= (*p) && (*p) <= 31 )
1484
+ goto st0;
1485
+ goto tr54;
1486
+ tr54:
1487
+ #line 358 "unicorn_http.rl"
1488
+ {MARK(start.query, p); }
1489
+ goto st30;
1490
+ st30:
1491
+ if ( ++p == pe )
1492
+ goto _test_eof30;
1493
+ case 30:
1494
+ #line 1495 "unicorn_http.c"
1495
+ switch( (*p) ) {
1496
+ case 32: goto tr59;
1497
+ case 35: goto tr60;
1498
+ case 37: goto st31;
1499
+ case 127: goto st0;
1500
+ }
1501
+ if ( 0 <= (*p) && (*p) <= 31 )
1502
+ goto st0;
1503
+ goto st30;
1504
+ tr57:
1505
+ #line 358 "unicorn_http.rl"
1506
+ {MARK(start.query, p); }
1507
+ goto st31;
1508
+ st31:
1509
+ if ( ++p == pe )
1510
+ goto _test_eof31;
1511
+ case 31:
1512
+ #line 1513 "unicorn_http.c"
1513
+ if ( (*p) < 65 ) {
1514
+ if ( 48 <= (*p) && (*p) <= 57 )
1515
+ goto st32;
1516
+ } else if ( (*p) > 70 ) {
1517
+ if ( 97 <= (*p) && (*p) <= 102 )
1518
+ goto st32;
1519
+ } else
1520
+ goto st32;
1521
+ goto st0;
1522
+ st32:
1523
+ if ( ++p == pe )
1524
+ goto _test_eof32;
1525
+ case 32:
1526
+ if ( (*p) < 65 ) {
1527
+ if ( 48 <= (*p) && (*p) <= 57 )
1528
+ goto st30;
1529
+ } else if ( (*p) > 70 ) {
1530
+ if ( 97 <= (*p) && (*p) <= 102 )
1531
+ goto st30;
1532
+ } else
1533
+ goto st30;
1534
+ goto st0;
1535
+ tr7:
1536
+ #line 325 "unicorn_http.rl"
1537
+ {MARK(mark, p); }
1538
+ #line 329 "unicorn_http.rl"
1539
+ { downcase_char(deconst(p)); }
1540
+ goto st33;
1541
+ st33:
1542
+ if ( ++p == pe )
1543
+ goto _test_eof33;
1544
+ case 33:
1545
+ #line 1546 "unicorn_http.c"
1546
+ switch( (*p) ) {
1547
+ case 84: goto tr63;
1548
+ case 116: goto tr63;
1549
+ }
1550
+ goto st0;
1551
+ tr63:
1552
+ #line 329 "unicorn_http.rl"
1553
+ { downcase_char(deconst(p)); }
1554
+ goto st34;
1555
+ st34:
1556
+ if ( ++p == pe )
1557
+ goto _test_eof34;
1558
+ case 34:
1559
+ #line 1560 "unicorn_http.c"
1560
+ switch( (*p) ) {
1561
+ case 84: goto tr64;
1562
+ case 116: goto tr64;
1563
+ }
1564
+ goto st0;
1565
+ tr64:
1566
+ #line 329 "unicorn_http.rl"
1567
+ { downcase_char(deconst(p)); }
1568
+ goto st35;
1569
+ st35:
1570
+ if ( ++p == pe )
1571
+ goto _test_eof35;
1572
+ case 35:
1573
+ #line 1574 "unicorn_http.c"
1574
+ switch( (*p) ) {
1575
+ case 80: goto tr65;
1576
+ case 112: goto tr65;
1577
+ }
1578
+ goto st0;
1579
+ tr65:
1580
+ #line 329 "unicorn_http.rl"
1581
+ { downcase_char(deconst(p)); }
1582
+ goto st36;
1583
+ st36:
1584
+ if ( ++p == pe )
1585
+ goto _test_eof36;
1586
+ case 36:
1587
+ #line 1588 "unicorn_http.c"
1588
+ switch( (*p) ) {
1589
+ case 58: goto tr66;
1590
+ case 83: goto tr67;
1591
+ case 115: goto tr67;
1592
+ }
1593
+ goto st0;
1594
+ tr66:
1595
+ #line 335 "unicorn_http.rl"
1596
+ {
1597
+ rb_hash_aset(hp->env, g_rack_url_scheme, STR_NEW(mark, p));
1598
+ }
1599
+ goto st37;
1600
+ st37:
1601
+ if ( ++p == pe )
1602
+ goto _test_eof37;
1603
+ case 37:
1604
+ #line 1605 "unicorn_http.c"
1605
+ if ( (*p) == 47 )
1606
+ goto st38;
1607
+ goto st0;
1608
+ st38:
1609
+ if ( ++p == pe )
1610
+ goto _test_eof38;
1611
+ case 38:
1612
+ if ( (*p) == 47 )
1613
+ goto st39;
1614
+ goto st0;
1615
+ st39:
1616
+ if ( ++p == pe )
1617
+ goto _test_eof39;
1618
+ case 39:
1619
+ switch( (*p) ) {
1620
+ case 37: goto st41;
1621
+ case 47: goto st0;
1622
+ case 60: goto st0;
1623
+ case 91: goto tr73;
1624
+ case 95: goto tr72;
1625
+ case 127: goto st0;
1626
+ }
1627
+ if ( (*p) < 45 ) {
1628
+ if ( (*p) > 32 ) {
1629
+ if ( 34 <= (*p) && (*p) <= 35 )
1630
+ goto st0;
1631
+ } else if ( (*p) >= 0 )
1632
+ goto st0;
1633
+ } else if ( (*p) > 57 ) {
1634
+ if ( (*p) < 65 ) {
1635
+ if ( 62 <= (*p) && (*p) <= 64 )
1636
+ goto st0;
1637
+ } else if ( (*p) > 90 ) {
1638
+ if ( 97 <= (*p) && (*p) <= 122 )
1639
+ goto tr72;
1640
+ } else
1641
+ goto tr72;
1642
+ } else
1643
+ goto tr72;
1644
+ goto st40;
1645
+ st40:
1646
+ if ( ++p == pe )
1647
+ goto _test_eof40;
1648
+ case 40:
1649
+ switch( (*p) ) {
1650
+ case 37: goto st41;
1651
+ case 47: goto st0;
1652
+ case 60: goto st0;
1653
+ case 64: goto st39;
1654
+ case 127: goto st0;
1655
+ }
1656
+ if ( (*p) < 34 ) {
1657
+ if ( 0 <= (*p) && (*p) <= 32 )
1658
+ goto st0;
1659
+ } else if ( (*p) > 35 ) {
1660
+ if ( 62 <= (*p) && (*p) <= 63 )
1661
+ goto st0;
1662
+ } else
1663
+ goto st0;
1664
+ goto st40;
1665
+ st41:
1666
+ if ( ++p == pe )
1667
+ goto _test_eof41;
1668
+ case 41:
1669
+ if ( (*p) < 65 ) {
1670
+ if ( 48 <= (*p) && (*p) <= 57 )
1671
+ goto st42;
1672
+ } else if ( (*p) > 70 ) {
1673
+ if ( 97 <= (*p) && (*p) <= 102 )
1674
+ goto st42;
1675
+ } else
1676
+ goto st42;
1677
+ goto st0;
1678
+ st42:
1679
+ if ( ++p == pe )
1680
+ goto _test_eof42;
1681
+ case 42:
1682
+ if ( (*p) < 65 ) {
1683
+ if ( 48 <= (*p) && (*p) <= 57 )
1684
+ goto st40;
1685
+ } else if ( (*p) > 70 ) {
1686
+ if ( 97 <= (*p) && (*p) <= 102 )
1687
+ goto st40;
1688
+ } else
1689
+ goto st40;
1690
+ goto st0;
1691
+ tr72:
1692
+ #line 325 "unicorn_http.rl"
1693
+ {MARK(mark, p); }
1694
+ goto st43;
1695
+ st43:
1696
+ if ( ++p == pe )
1697
+ goto _test_eof43;
1698
+ case 43:
1699
+ #line 1700 "unicorn_http.c"
1700
+ switch( (*p) ) {
1701
+ case 37: goto st41;
1702
+ case 47: goto tr76;
1703
+ case 58: goto st44;
1704
+ case 60: goto st0;
1705
+ case 64: goto st39;
1706
+ case 95: goto st43;
1707
+ case 127: goto st0;
1708
+ }
1709
+ if ( (*p) < 45 ) {
1710
+ if ( (*p) > 32 ) {
1711
+ if ( 34 <= (*p) && (*p) <= 35 )
1712
+ goto st0;
1713
+ } else if ( (*p) >= 0 )
1714
+ goto st0;
1715
+ } else if ( (*p) > 57 ) {
1716
+ if ( (*p) < 65 ) {
1717
+ if ( 62 <= (*p) && (*p) <= 63 )
1718
+ goto st0;
1719
+ } else if ( (*p) > 90 ) {
1720
+ if ( 97 <= (*p) && (*p) <= 122 )
1721
+ goto st43;
1722
+ } else
1723
+ goto st43;
1724
+ } else
1725
+ goto st43;
1726
+ goto st40;
1727
+ st44:
1728
+ if ( ++p == pe )
1729
+ goto _test_eof44;
1730
+ case 44:
1731
+ switch( (*p) ) {
1732
+ case 37: goto st41;
1733
+ case 47: goto tr76;
1734
+ case 60: goto st0;
1735
+ case 64: goto st39;
1736
+ case 127: goto st0;
1737
+ }
1738
+ if ( (*p) < 34 ) {
1739
+ if ( 0 <= (*p) && (*p) <= 32 )
1740
+ goto st0;
1741
+ } else if ( (*p) > 35 ) {
1742
+ if ( (*p) > 57 ) {
1743
+ if ( 62 <= (*p) && (*p) <= 63 )
1744
+ goto st0;
1745
+ } else if ( (*p) >= 48 )
1746
+ goto st44;
1747
+ } else
1748
+ goto st0;
1749
+ goto st40;
1750
+ tr73:
1751
+ #line 325 "unicorn_http.rl"
1752
+ {MARK(mark, p); }
1753
+ goto st45;
1754
+ st45:
1755
+ if ( ++p == pe )
1756
+ goto _test_eof45;
1757
+ case 45:
1758
+ #line 1759 "unicorn_http.c"
1759
+ switch( (*p) ) {
1760
+ case 37: goto st41;
1761
+ case 47: goto st0;
1762
+ case 60: goto st0;
1763
+ case 64: goto st39;
1764
+ case 127: goto st0;
1765
+ }
1766
+ if ( (*p) < 48 ) {
1767
+ if ( (*p) > 32 ) {
1768
+ if ( 34 <= (*p) && (*p) <= 35 )
1769
+ goto st0;
1770
+ } else if ( (*p) >= 0 )
1771
+ goto st0;
1772
+ } else if ( (*p) > 58 ) {
1773
+ if ( (*p) < 65 ) {
1774
+ if ( 62 <= (*p) && (*p) <= 63 )
1775
+ goto st0;
1776
+ } else if ( (*p) > 70 ) {
1777
+ if ( 97 <= (*p) && (*p) <= 102 )
1778
+ goto st46;
1779
+ } else
1780
+ goto st46;
1781
+ } else
1782
+ goto st46;
1783
+ goto st40;
1784
+ st46:
1785
+ if ( ++p == pe )
1786
+ goto _test_eof46;
1787
+ case 46:
1788
+ switch( (*p) ) {
1789
+ case 37: goto st41;
1790
+ case 47: goto st0;
1791
+ case 60: goto st0;
1792
+ case 64: goto st39;
1793
+ case 93: goto st47;
1794
+ case 127: goto st0;
1795
+ }
1796
+ if ( (*p) < 48 ) {
1797
+ if ( (*p) > 32 ) {
1798
+ if ( 34 <= (*p) && (*p) <= 35 )
1799
+ goto st0;
1800
+ } else if ( (*p) >= 0 )
1801
+ goto st0;
1802
+ } else if ( (*p) > 58 ) {
1803
+ if ( (*p) < 65 ) {
1804
+ if ( 62 <= (*p) && (*p) <= 63 )
1805
+ goto st0;
1806
+ } else if ( (*p) > 70 ) {
1807
+ if ( 97 <= (*p) && (*p) <= 102 )
1808
+ goto st46;
1809
+ } else
1810
+ goto st46;
1811
+ } else
1812
+ goto st46;
1813
+ goto st40;
1814
+ st47:
1815
+ if ( ++p == pe )
1816
+ goto _test_eof47;
1817
+ case 47:
1818
+ switch( (*p) ) {
1819
+ case 37: goto st41;
1820
+ case 47: goto tr76;
1821
+ case 58: goto st44;
1822
+ case 60: goto st0;
1823
+ case 64: goto st39;
1824
+ case 127: goto st0;
1825
+ }
1826
+ if ( (*p) < 34 ) {
1827
+ if ( 0 <= (*p) && (*p) <= 32 )
1828
+ goto st0;
1829
+ } else if ( (*p) > 35 ) {
1830
+ if ( 62 <= (*p) && (*p) <= 63 )
1831
+ goto st0;
1832
+ } else
1833
+ goto st0;
1834
+ goto st40;
1835
+ tr67:
1836
+ #line 329 "unicorn_http.rl"
1837
+ { downcase_char(deconst(p)); }
1838
+ goto st48;
1839
+ st48:
1840
+ if ( ++p == pe )
1841
+ goto _test_eof48;
1842
+ case 48:
1843
+ #line 1844 "unicorn_http.c"
1844
+ if ( (*p) == 58 )
1845
+ goto tr66;
1846
+ goto st0;
1847
+ st49:
1848
+ if ( ++p == pe )
1849
+ goto _test_eof49;
1850
+ case 49:
1851
+ switch( (*p) ) {
1852
+ case 32: goto tr3;
1853
+ case 33: goto st50;
1854
+ case 124: goto st50;
1855
+ case 126: goto st50;
1856
+ }
1857
+ if ( (*p) < 45 ) {
1858
+ if ( (*p) > 39 ) {
1859
+ if ( 42 <= (*p) && (*p) <= 43 )
1860
+ goto st50;
1861
+ } else if ( (*p) >= 35 )
1862
+ goto st50;
1863
+ } else if ( (*p) > 46 ) {
1864
+ if ( (*p) < 65 ) {
1865
+ if ( 48 <= (*p) && (*p) <= 57 )
1866
+ goto st50;
1867
+ } else if ( (*p) > 90 ) {
1868
+ if ( 94 <= (*p) && (*p) <= 122 )
1869
+ goto st50;
1870
+ } else
1871
+ goto st50;
1872
+ } else
1873
+ goto st50;
1874
+ goto st0;
1875
+ st50:
1876
+ if ( ++p == pe )
1877
+ goto _test_eof50;
1878
+ case 50:
1879
+ switch( (*p) ) {
1880
+ case 32: goto tr3;
1881
+ case 33: goto st51;
1882
+ case 124: goto st51;
1883
+ case 126: goto st51;
1884
+ }
1885
+ if ( (*p) < 45 ) {
1886
+ if ( (*p) > 39 ) {
1887
+ if ( 42 <= (*p) && (*p) <= 43 )
1888
+ goto st51;
1889
+ } else if ( (*p) >= 35 )
1890
+ goto st51;
1891
+ } else if ( (*p) > 46 ) {
1892
+ if ( (*p) < 65 ) {
1893
+ if ( 48 <= (*p) && (*p) <= 57 )
1894
+ goto st51;
1895
+ } else if ( (*p) > 90 ) {
1896
+ if ( 94 <= (*p) && (*p) <= 122 )
1897
+ goto st51;
1898
+ } else
1899
+ goto st51;
1900
+ } else
1901
+ goto st51;
1902
+ goto st0;
1903
+ st51:
1904
+ if ( ++p == pe )
1905
+ goto _test_eof51;
1906
+ case 51:
1907
+ switch( (*p) ) {
1908
+ case 32: goto tr3;
1909
+ case 33: goto st52;
1910
+ case 124: goto st52;
1911
+ case 126: goto st52;
1912
+ }
1913
+ if ( (*p) < 45 ) {
1914
+ if ( (*p) > 39 ) {
1915
+ if ( 42 <= (*p) && (*p) <= 43 )
1916
+ goto st52;
1917
+ } else if ( (*p) >= 35 )
1918
+ goto st52;
1919
+ } else if ( (*p) > 46 ) {
1920
+ if ( (*p) < 65 ) {
1921
+ if ( 48 <= (*p) && (*p) <= 57 )
1922
+ goto st52;
1923
+ } else if ( (*p) > 90 ) {
1924
+ if ( 94 <= (*p) && (*p) <= 122 )
1925
+ goto st52;
1926
+ } else
1927
+ goto st52;
1928
+ } else
1929
+ goto st52;
1930
+ goto st0;
1931
+ st52:
1932
+ if ( ++p == pe )
1933
+ goto _test_eof52;
1934
+ case 52:
1935
+ switch( (*p) ) {
1936
+ case 32: goto tr3;
1937
+ case 33: goto st53;
1938
+ case 124: goto st53;
1939
+ case 126: goto st53;
1940
+ }
1941
+ if ( (*p) < 45 ) {
1942
+ if ( (*p) > 39 ) {
1943
+ if ( 42 <= (*p) && (*p) <= 43 )
1944
+ goto st53;
1945
+ } else if ( (*p) >= 35 )
1946
+ goto st53;
1947
+ } else if ( (*p) > 46 ) {
1948
+ if ( (*p) < 65 ) {
1949
+ if ( 48 <= (*p) && (*p) <= 57 )
1950
+ goto st53;
1951
+ } else if ( (*p) > 90 ) {
1952
+ if ( 94 <= (*p) && (*p) <= 122 )
1953
+ goto st53;
1954
+ } else
1955
+ goto st53;
1956
+ } else
1957
+ goto st53;
1958
+ goto st0;
1959
+ st53:
1960
+ if ( ++p == pe )
1961
+ goto _test_eof53;
1962
+ case 53:
1963
+ switch( (*p) ) {
1964
+ case 32: goto tr3;
1965
+ case 33: goto st54;
1966
+ case 124: goto st54;
1967
+ case 126: goto st54;
1968
+ }
1969
+ if ( (*p) < 45 ) {
1970
+ if ( (*p) > 39 ) {
1971
+ if ( 42 <= (*p) && (*p) <= 43 )
1972
+ goto st54;
1973
+ } else if ( (*p) >= 35 )
1974
+ goto st54;
1975
+ } else if ( (*p) > 46 ) {
1976
+ if ( (*p) < 65 ) {
1977
+ if ( 48 <= (*p) && (*p) <= 57 )
1978
+ goto st54;
1979
+ } else if ( (*p) > 90 ) {
1980
+ if ( 94 <= (*p) && (*p) <= 122 )
1981
+ goto st54;
1982
+ } else
1983
+ goto st54;
1984
+ } else
1985
+ goto st54;
1986
+ goto st0;
1987
+ st54:
1988
+ if ( ++p == pe )
1989
+ goto _test_eof54;
1990
+ case 54:
1991
+ switch( (*p) ) {
1992
+ case 32: goto tr3;
1993
+ case 33: goto st55;
1994
+ case 124: goto st55;
1995
+ case 126: goto st55;
1996
+ }
1997
+ if ( (*p) < 45 ) {
1998
+ if ( (*p) > 39 ) {
1999
+ if ( 42 <= (*p) && (*p) <= 43 )
2000
+ goto st55;
2001
+ } else if ( (*p) >= 35 )
2002
+ goto st55;
2003
+ } else if ( (*p) > 46 ) {
2004
+ if ( (*p) < 65 ) {
2005
+ if ( 48 <= (*p) && (*p) <= 57 )
2006
+ goto st55;
2007
+ } else if ( (*p) > 90 ) {
2008
+ if ( 94 <= (*p) && (*p) <= 122 )
2009
+ goto st55;
2010
+ } else
2011
+ goto st55;
2012
+ } else
2013
+ goto st55;
2014
+ goto st0;
2015
+ st55:
2016
+ if ( ++p == pe )
2017
+ goto _test_eof55;
2018
+ case 55:
2019
+ switch( (*p) ) {
2020
+ case 32: goto tr3;
2021
+ case 33: goto st56;
2022
+ case 124: goto st56;
2023
+ case 126: goto st56;
2024
+ }
2025
+ if ( (*p) < 45 ) {
2026
+ if ( (*p) > 39 ) {
2027
+ if ( 42 <= (*p) && (*p) <= 43 )
2028
+ goto st56;
2029
+ } else if ( (*p) >= 35 )
2030
+ goto st56;
2031
+ } else if ( (*p) > 46 ) {
2032
+ if ( (*p) < 65 ) {
2033
+ if ( 48 <= (*p) && (*p) <= 57 )
2034
+ goto st56;
2035
+ } else if ( (*p) > 90 ) {
2036
+ if ( 94 <= (*p) && (*p) <= 122 )
2037
+ goto st56;
2038
+ } else
2039
+ goto st56;
2040
+ } else
2041
+ goto st56;
2042
+ goto st0;
2043
+ st56:
2044
+ if ( ++p == pe )
2045
+ goto _test_eof56;
2046
+ case 56:
2047
+ switch( (*p) ) {
2048
+ case 32: goto tr3;
2049
+ case 33: goto st57;
2050
+ case 124: goto st57;
2051
+ case 126: goto st57;
2052
+ }
2053
+ if ( (*p) < 45 ) {
2054
+ if ( (*p) > 39 ) {
2055
+ if ( 42 <= (*p) && (*p) <= 43 )
2056
+ goto st57;
2057
+ } else if ( (*p) >= 35 )
2058
+ goto st57;
2059
+ } else if ( (*p) > 46 ) {
2060
+ if ( (*p) < 65 ) {
2061
+ if ( 48 <= (*p) && (*p) <= 57 )
2062
+ goto st57;
2063
+ } else if ( (*p) > 90 ) {
2064
+ if ( 94 <= (*p) && (*p) <= 122 )
2065
+ goto st57;
2066
+ } else
2067
+ goto st57;
2068
+ } else
2069
+ goto st57;
2070
+ goto st0;
2071
+ st57:
2072
+ if ( ++p == pe )
2073
+ goto _test_eof57;
2074
+ case 57:
2075
+ switch( (*p) ) {
2076
+ case 32: goto tr3;
2077
+ case 33: goto st58;
2078
+ case 124: goto st58;
2079
+ case 126: goto st58;
2080
+ }
2081
+ if ( (*p) < 45 ) {
2082
+ if ( (*p) > 39 ) {
2083
+ if ( 42 <= (*p) && (*p) <= 43 )
2084
+ goto st58;
2085
+ } else if ( (*p) >= 35 )
2086
+ goto st58;
2087
+ } else if ( (*p) > 46 ) {
2088
+ if ( (*p) < 65 ) {
2089
+ if ( 48 <= (*p) && (*p) <= 57 )
2090
+ goto st58;
2091
+ } else if ( (*p) > 90 ) {
2092
+ if ( 94 <= (*p) && (*p) <= 122 )
2093
+ goto st58;
2094
+ } else
2095
+ goto st58;
2096
+ } else
2097
+ goto st58;
2098
+ goto st0;
2099
+ st58:
2100
+ if ( ++p == pe )
2101
+ goto _test_eof58;
2102
+ case 58:
2103
+ switch( (*p) ) {
2104
+ case 32: goto tr3;
2105
+ case 33: goto st59;
2106
+ case 124: goto st59;
2107
+ case 126: goto st59;
2108
+ }
2109
+ if ( (*p) < 45 ) {
2110
+ if ( (*p) > 39 ) {
2111
+ if ( 42 <= (*p) && (*p) <= 43 )
2112
+ goto st59;
2113
+ } else if ( (*p) >= 35 )
2114
+ goto st59;
2115
+ } else if ( (*p) > 46 ) {
2116
+ if ( (*p) < 65 ) {
2117
+ if ( 48 <= (*p) && (*p) <= 57 )
2118
+ goto st59;
2119
+ } else if ( (*p) > 90 ) {
2120
+ if ( 94 <= (*p) && (*p) <= 122 )
2121
+ goto st59;
2122
+ } else
2123
+ goto st59;
2124
+ } else
2125
+ goto st59;
2126
+ goto st0;
2127
+ st59:
2128
+ if ( ++p == pe )
2129
+ goto _test_eof59;
2130
+ case 59:
2131
+ switch( (*p) ) {
2132
+ case 32: goto tr3;
2133
+ case 33: goto st60;
2134
+ case 124: goto st60;
2135
+ case 126: goto st60;
2136
+ }
2137
+ if ( (*p) < 45 ) {
2138
+ if ( (*p) > 39 ) {
2139
+ if ( 42 <= (*p) && (*p) <= 43 )
2140
+ goto st60;
2141
+ } else if ( (*p) >= 35 )
2142
+ goto st60;
2143
+ } else if ( (*p) > 46 ) {
2144
+ if ( (*p) < 65 ) {
2145
+ if ( 48 <= (*p) && (*p) <= 57 )
2146
+ goto st60;
2147
+ } else if ( (*p) > 90 ) {
2148
+ if ( 94 <= (*p) && (*p) <= 122 )
2149
+ goto st60;
2150
+ } else
2151
+ goto st60;
2152
+ } else
2153
+ goto st60;
2154
+ goto st0;
2155
+ st60:
2156
+ if ( ++p == pe )
2157
+ goto _test_eof60;
2158
+ case 60:
2159
+ switch( (*p) ) {
2160
+ case 32: goto tr3;
2161
+ case 33: goto st61;
2162
+ case 124: goto st61;
2163
+ case 126: goto st61;
2164
+ }
2165
+ if ( (*p) < 45 ) {
2166
+ if ( (*p) > 39 ) {
2167
+ if ( 42 <= (*p) && (*p) <= 43 )
2168
+ goto st61;
2169
+ } else if ( (*p) >= 35 )
2170
+ goto st61;
2171
+ } else if ( (*p) > 46 ) {
2172
+ if ( (*p) < 65 ) {
2173
+ if ( 48 <= (*p) && (*p) <= 57 )
2174
+ goto st61;
2175
+ } else if ( (*p) > 90 ) {
2176
+ if ( 94 <= (*p) && (*p) <= 122 )
2177
+ goto st61;
2178
+ } else
2179
+ goto st61;
2180
+ } else
2181
+ goto st61;
2182
+ goto st0;
2183
+ st61:
2184
+ if ( ++p == pe )
2185
+ goto _test_eof61;
2186
+ case 61:
2187
+ switch( (*p) ) {
2188
+ case 32: goto tr3;
2189
+ case 33: goto st62;
2190
+ case 124: goto st62;
2191
+ case 126: goto st62;
2192
+ }
2193
+ if ( (*p) < 45 ) {
2194
+ if ( (*p) > 39 ) {
2195
+ if ( 42 <= (*p) && (*p) <= 43 )
2196
+ goto st62;
2197
+ } else if ( (*p) >= 35 )
2198
+ goto st62;
2199
+ } else if ( (*p) > 46 ) {
2200
+ if ( (*p) < 65 ) {
2201
+ if ( 48 <= (*p) && (*p) <= 57 )
2202
+ goto st62;
2203
+ } else if ( (*p) > 90 ) {
2204
+ if ( 94 <= (*p) && (*p) <= 122 )
2205
+ goto st62;
2206
+ } else
2207
+ goto st62;
2208
+ } else
2209
+ goto st62;
2210
+ goto st0;
2211
+ st62:
2212
+ if ( ++p == pe )
2213
+ goto _test_eof62;
2214
+ case 62:
2215
+ switch( (*p) ) {
2216
+ case 32: goto tr3;
2217
+ case 33: goto st63;
2218
+ case 124: goto st63;
2219
+ case 126: goto st63;
2220
+ }
2221
+ if ( (*p) < 45 ) {
2222
+ if ( (*p) > 39 ) {
2223
+ if ( 42 <= (*p) && (*p) <= 43 )
2224
+ goto st63;
2225
+ } else if ( (*p) >= 35 )
2226
+ goto st63;
2227
+ } else if ( (*p) > 46 ) {
2228
+ if ( (*p) < 65 ) {
2229
+ if ( 48 <= (*p) && (*p) <= 57 )
2230
+ goto st63;
2231
+ } else if ( (*p) > 90 ) {
2232
+ if ( 94 <= (*p) && (*p) <= 122 )
2233
+ goto st63;
2234
+ } else
2235
+ goto st63;
2236
+ } else
2237
+ goto st63;
2238
+ goto st0;
2239
+ st63:
2240
+ if ( ++p == pe )
2241
+ goto _test_eof63;
2242
+ case 63:
2243
+ switch( (*p) ) {
2244
+ case 32: goto tr3;
2245
+ case 33: goto st64;
2246
+ case 124: goto st64;
2247
+ case 126: goto st64;
2248
+ }
2249
+ if ( (*p) < 45 ) {
2250
+ if ( (*p) > 39 ) {
2251
+ if ( 42 <= (*p) && (*p) <= 43 )
2252
+ goto st64;
2253
+ } else if ( (*p) >= 35 )
2254
+ goto st64;
2255
+ } else if ( (*p) > 46 ) {
2256
+ if ( (*p) < 65 ) {
2257
+ if ( 48 <= (*p) && (*p) <= 57 )
2258
+ goto st64;
2259
+ } else if ( (*p) > 90 ) {
2260
+ if ( 94 <= (*p) && (*p) <= 122 )
2261
+ goto st64;
2262
+ } else
2263
+ goto st64;
2264
+ } else
2265
+ goto st64;
2266
+ goto st0;
2267
+ st64:
2268
+ if ( ++p == pe )
2269
+ goto _test_eof64;
2270
+ case 64:
2271
+ switch( (*p) ) {
2272
+ case 32: goto tr3;
2273
+ case 33: goto st65;
2274
+ case 124: goto st65;
2275
+ case 126: goto st65;
2276
+ }
2277
+ if ( (*p) < 45 ) {
2278
+ if ( (*p) > 39 ) {
2279
+ if ( 42 <= (*p) && (*p) <= 43 )
2280
+ goto st65;
2281
+ } else if ( (*p) >= 35 )
2282
+ goto st65;
2283
+ } else if ( (*p) > 46 ) {
2284
+ if ( (*p) < 65 ) {
2285
+ if ( 48 <= (*p) && (*p) <= 57 )
2286
+ goto st65;
2287
+ } else if ( (*p) > 90 ) {
2288
+ if ( 94 <= (*p) && (*p) <= 122 )
2289
+ goto st65;
2290
+ } else
2291
+ goto st65;
2292
+ } else
2293
+ goto st65;
2294
+ goto st0;
2295
+ st65:
2296
+ if ( ++p == pe )
2297
+ goto _test_eof65;
2298
+ case 65:
2299
+ switch( (*p) ) {
2300
+ case 32: goto tr3;
2301
+ case 33: goto st66;
2302
+ case 124: goto st66;
2303
+ case 126: goto st66;
2304
+ }
2305
+ if ( (*p) < 45 ) {
2306
+ if ( (*p) > 39 ) {
2307
+ if ( 42 <= (*p) && (*p) <= 43 )
2308
+ goto st66;
2309
+ } else if ( (*p) >= 35 )
2310
+ goto st66;
2311
+ } else if ( (*p) > 46 ) {
2312
+ if ( (*p) < 65 ) {
2313
+ if ( 48 <= (*p) && (*p) <= 57 )
2314
+ goto st66;
2315
+ } else if ( (*p) > 90 ) {
2316
+ if ( 94 <= (*p) && (*p) <= 122 )
2317
+ goto st66;
2318
+ } else
2319
+ goto st66;
2320
+ } else
2321
+ goto st66;
2322
+ goto st0;
2323
+ st66:
2324
+ if ( ++p == pe )
2325
+ goto _test_eof66;
2326
+ case 66:
2327
+ switch( (*p) ) {
2328
+ case 32: goto tr3;
2329
+ case 33: goto st67;
2330
+ case 124: goto st67;
2331
+ case 126: goto st67;
2332
+ }
2333
+ if ( (*p) < 45 ) {
2334
+ if ( (*p) > 39 ) {
2335
+ if ( 42 <= (*p) && (*p) <= 43 )
2336
+ goto st67;
2337
+ } else if ( (*p) >= 35 )
2338
+ goto st67;
2339
+ } else if ( (*p) > 46 ) {
2340
+ if ( (*p) < 65 ) {
2341
+ if ( 48 <= (*p) && (*p) <= 57 )
2342
+ goto st67;
2343
+ } else if ( (*p) > 90 ) {
2344
+ if ( 94 <= (*p) && (*p) <= 122 )
2345
+ goto st67;
2346
+ } else
2347
+ goto st67;
2348
+ } else
2349
+ goto st67;
2350
+ goto st0;
2351
+ st67:
2352
+ if ( ++p == pe )
2353
+ goto _test_eof67;
2354
+ case 67:
2355
+ if ( (*p) == 32 )
2356
+ goto tr3;
2357
+ goto st0;
2358
+ tr2:
2359
+ #line 325 "unicorn_http.rl"
2360
+ {MARK(mark, p); }
2361
+ goto st68;
2362
+ st68:
2363
+ if ( ++p == pe )
2364
+ goto _test_eof68;
2365
+ case 68:
2366
+ #line 2367 "unicorn_http.c"
2367
+ switch( (*p) ) {
2368
+ case 32: goto tr3;
2369
+ case 33: goto st49;
2370
+ case 69: goto st69;
2371
+ case 124: goto st49;
2372
+ case 126: goto st49;
2373
+ }
2374
+ if ( (*p) < 45 ) {
2375
+ if ( (*p) > 39 ) {
2376
+ if ( 42 <= (*p) && (*p) <= 43 )
2377
+ goto st49;
2378
+ } else if ( (*p) >= 35 )
2379
+ goto st49;
2380
+ } else if ( (*p) > 46 ) {
2381
+ if ( (*p) < 65 ) {
2382
+ if ( 48 <= (*p) && (*p) <= 57 )
2383
+ goto st49;
2384
+ } else if ( (*p) > 90 ) {
2385
+ if ( 94 <= (*p) && (*p) <= 122 )
2386
+ goto st49;
2387
+ } else
2388
+ goto st49;
2389
+ } else
2390
+ goto st49;
2391
+ goto st0;
2392
+ st69:
2393
+ if ( ++p == pe )
2394
+ goto _test_eof69;
2395
+ case 69:
2396
+ switch( (*p) ) {
2397
+ case 32: goto tr3;
2398
+ case 33: goto st50;
2399
+ case 84: goto st70;
2400
+ case 124: goto st50;
2401
+ case 126: goto st50;
2402
+ }
2403
+ if ( (*p) < 45 ) {
2404
+ if ( (*p) > 39 ) {
2405
+ if ( 42 <= (*p) && (*p) <= 43 )
2406
+ goto st50;
2407
+ } else if ( (*p) >= 35 )
2408
+ goto st50;
2409
+ } else if ( (*p) > 46 ) {
2410
+ if ( (*p) < 65 ) {
2411
+ if ( 48 <= (*p) && (*p) <= 57 )
2412
+ goto st50;
2413
+ } else if ( (*p) > 90 ) {
2414
+ if ( 94 <= (*p) && (*p) <= 122 )
2415
+ goto st50;
2416
+ } else
2417
+ goto st50;
2418
+ } else
2419
+ goto st50;
2420
+ goto st0;
2421
+ st70:
2422
+ if ( ++p == pe )
2423
+ goto _test_eof70;
2424
+ case 70:
2425
+ switch( (*p) ) {
2426
+ case 32: goto tr100;
2427
+ case 33: goto st51;
2428
+ case 124: goto st51;
2429
+ case 126: goto st51;
2430
+ }
2431
+ if ( (*p) < 45 ) {
2432
+ if ( (*p) > 39 ) {
2433
+ if ( 42 <= (*p) && (*p) <= 43 )
2434
+ goto st51;
2435
+ } else if ( (*p) >= 35 )
2436
+ goto st51;
2437
+ } else if ( (*p) > 46 ) {
2438
+ if ( (*p) < 65 ) {
2439
+ if ( 48 <= (*p) && (*p) <= 57 )
2440
+ goto st51;
2441
+ } else if ( (*p) > 90 ) {
2442
+ if ( 94 <= (*p) && (*p) <= 122 )
2443
+ goto st51;
2444
+ } else
2445
+ goto st51;
2446
+ } else
2447
+ goto st51;
2448
+ goto st0;
2449
+ tr100:
2450
+ #line 334 "unicorn_http.rl"
2451
+ { request_method(hp, PTR_TO(mark), LEN(mark, p)); }
2452
+ goto st71;
2453
+ st71:
2454
+ if ( ++p == pe )
2455
+ goto _test_eof71;
2456
+ case 71:
2457
+ #line 2458 "unicorn_http.c"
2458
+ switch( (*p) ) {
2459
+ case 42: goto tr101;
2460
+ case 47: goto tr102;
2461
+ case 72: goto tr103;
2462
+ case 104: goto tr103;
2463
+ }
2464
+ goto st0;
2465
+ tr101:
2466
+ #line 325 "unicorn_http.rl"
2467
+ {MARK(mark, p); }
2468
+ goto st72;
2469
+ st72:
2470
+ if ( ++p == pe )
2471
+ goto _test_eof72;
2472
+ case 72:
2473
+ #line 2474 "unicorn_http.c"
2474
+ switch( (*p) ) {
2475
+ case 10: goto tr104;
2476
+ case 13: goto tr105;
2477
+ case 32: goto tr8;
2478
+ case 35: goto tr106;
2479
+ }
2480
+ goto st0;
2481
+ tr106:
2482
+ #line 339 "unicorn_http.rl"
2483
+ {
2484
+ VALUE str;
2485
+
2486
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
2487
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
2488
+ /*
2489
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
2490
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
2491
+ */
2492
+ if (STR_CSTR_EQ(str, "*")) {
2493
+ str = rb_str_new(NULL, 0);
2494
+ rb_hash_aset(hp->env, g_path_info, str);
2495
+ rb_hash_aset(hp->env, g_request_path, str);
2496
+ }
2497
+ }
2498
+ goto st73;
2499
+ tr119:
2500
+ #line 364 "unicorn_http.rl"
2501
+ {
2502
+ VALUE val;
2503
+
2504
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
2505
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
2506
+
2507
+ /* rack says PATH_INFO must start with "/" or be empty */
2508
+ if (!STR_CSTR_EQ(val, "*"))
2509
+ rb_hash_aset(hp->env, g_path_info, val);
2510
+ }
2511
+ #line 339 "unicorn_http.rl"
2512
+ {
2513
+ VALUE str;
2514
+
2515
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
2516
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
2517
+ /*
2518
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
2519
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
2520
+ */
2521
+ if (STR_CSTR_EQ(str, "*")) {
2522
+ str = rb_str_new(NULL, 0);
2523
+ rb_hash_aset(hp->env, g_path_info, str);
2524
+ rb_hash_aset(hp->env, g_request_path, str);
2525
+ }
2526
+ }
2527
+ goto st73;
2528
+ tr126:
2529
+ #line 358 "unicorn_http.rl"
2530
+ {MARK(start.query, p); }
2531
+ #line 359 "unicorn_http.rl"
2532
+ {
2533
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
2534
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
2535
+ }
2536
+ #line 339 "unicorn_http.rl"
2537
+ {
2538
+ VALUE str;
2539
+
2540
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
2541
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
2542
+ /*
2543
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
2544
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
2545
+ */
2546
+ if (STR_CSTR_EQ(str, "*")) {
2547
+ str = rb_str_new(NULL, 0);
2548
+ rb_hash_aset(hp->env, g_path_info, str);
2549
+ rb_hash_aset(hp->env, g_request_path, str);
2550
+ }
2551
+ }
2552
+ goto st73;
2553
+ tr131:
2554
+ #line 359 "unicorn_http.rl"
2555
+ {
2556
+ VALIDATE_MAX_URI_LENGTH(LEN(start.query, p), QUERY_STRING);
2557
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, p));
2558
+ }
2559
+ #line 339 "unicorn_http.rl"
2560
+ {
2561
+ VALUE str;
2562
+
2563
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_URI);
2564
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, p));
2565
+ /*
2566
+ * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
2567
+ * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
2568
+ */
2569
+ if (STR_CSTR_EQ(str, "*")) {
2570
+ str = rb_str_new(NULL, 0);
2571
+ rb_hash_aset(hp->env, g_path_info, str);
2572
+ rb_hash_aset(hp->env, g_request_path, str);
2573
+ }
2574
+ }
2575
+ goto st73;
2576
+ st73:
2577
+ if ( ++p == pe )
2578
+ goto _test_eof73;
2579
+ case 73:
2580
+ #line 2581 "unicorn_http.c"
2581
+ switch( (*p) ) {
2582
+ case 10: goto tr108;
2583
+ case 13: goto tr109;
2584
+ case 32: goto tr42;
2585
+ case 35: goto st0;
2586
+ case 37: goto tr110;
2587
+ case 127: goto st0;
2588
+ }
2589
+ if ( 0 <= (*p) && (*p) <= 31 )
2590
+ goto st0;
2591
+ goto tr107;
2592
+ tr107:
2593
+ #line 325 "unicorn_http.rl"
2594
+ {MARK(mark, p); }
2595
+ goto st74;
2596
+ st74:
2597
+ if ( ++p == pe )
2598
+ goto _test_eof74;
2599
+ case 74:
2600
+ #line 2601 "unicorn_http.c"
2601
+ switch( (*p) ) {
2602
+ case 10: goto tr112;
2603
+ case 13: goto tr113;
2604
+ case 32: goto tr45;
2605
+ case 35: goto st0;
2606
+ case 37: goto st75;
2607
+ case 127: goto st0;
2608
+ }
2609
+ if ( 0 <= (*p) && (*p) <= 31 )
2610
+ goto st0;
2611
+ goto st74;
2612
+ tr110:
2613
+ #line 325 "unicorn_http.rl"
2614
+ {MARK(mark, p); }
2615
+ goto st75;
2616
+ st75:
2617
+ if ( ++p == pe )
2618
+ goto _test_eof75;
2619
+ case 75:
2620
+ #line 2621 "unicorn_http.c"
2621
+ if ( (*p) < 65 ) {
2622
+ if ( 48 <= (*p) && (*p) <= 57 )
2623
+ goto st76;
2624
+ } else if ( (*p) > 70 ) {
2625
+ if ( 97 <= (*p) && (*p) <= 102 )
2626
+ goto st76;
2627
+ } else
2628
+ goto st76;
2629
+ goto st0;
2630
+ st76:
2631
+ if ( ++p == pe )
2632
+ goto _test_eof76;
2633
+ case 76:
2634
+ if ( (*p) < 65 ) {
2635
+ if ( 48 <= (*p) && (*p) <= 57 )
2636
+ goto st74;
2637
+ } else if ( (*p) > 70 ) {
2638
+ if ( 97 <= (*p) && (*p) <= 102 )
2639
+ goto st74;
2640
+ } else
2641
+ goto st74;
2642
+ goto st0;
2643
+ tr102:
2644
+ #line 325 "unicorn_http.rl"
2645
+ {MARK(mark, p); }
2646
+ goto st77;
2647
+ tr147:
2648
+ #line 338 "unicorn_http.rl"
2649
+ { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, p)); }
2650
+ #line 325 "unicorn_http.rl"
2651
+ {MARK(mark, p); }
2652
+ goto st77;
2653
+ st77:
2654
+ if ( ++p == pe )
2655
+ goto _test_eof77;
2656
+ case 77:
2657
+ #line 2658 "unicorn_http.c"
2658
+ switch( (*p) ) {
2659
+ case 10: goto tr117;
2660
+ case 13: goto tr118;
2661
+ case 32: goto tr49;
2662
+ case 35: goto tr119;
2663
+ case 37: goto st78;
2664
+ case 63: goto tr121;
2665
+ case 127: goto st0;
2666
+ }
2667
+ if ( 0 <= (*p) && (*p) <= 31 )
2668
+ goto st0;
2669
+ goto st77;
2670
+ st78:
2671
+ if ( ++p == pe )
2672
+ goto _test_eof78;
2673
+ case 78:
2674
+ if ( (*p) < 65 ) {
2675
+ if ( 48 <= (*p) && (*p) <= 57 )
2676
+ goto st79;
2677
+ } else if ( (*p) > 70 ) {
2678
+ if ( 97 <= (*p) && (*p) <= 102 )
2679
+ goto st79;
2680
+ } else
2681
+ goto st79;
2682
+ goto st0;
2683
+ st79:
2684
+ if ( ++p == pe )
2685
+ goto _test_eof79;
2686
+ case 79:
2687
+ if ( (*p) < 65 ) {
2688
+ if ( 48 <= (*p) && (*p) <= 57 )
2689
+ goto st77;
2690
+ } else if ( (*p) > 70 ) {
2691
+ if ( 97 <= (*p) && (*p) <= 102 )
2692
+ goto st77;
2693
+ } else
2694
+ goto st77;
2695
+ goto st0;
2696
+ tr121:
2697
+ #line 364 "unicorn_http.rl"
2698
+ {
2699
+ VALUE val;
2700
+
2701
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, p), REQUEST_PATH);
2702
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, p));
2703
+
2704
+ /* rack says PATH_INFO must start with "/" or be empty */
2705
+ if (!STR_CSTR_EQ(val, "*"))
2706
+ rb_hash_aset(hp->env, g_path_info, val);
2707
+ }
2708
+ goto st80;
2709
+ st80:
2710
+ if ( ++p == pe )
2711
+ goto _test_eof80;
2712
+ case 80:
2713
+ #line 2714 "unicorn_http.c"
2714
+ switch( (*p) ) {
2715
+ case 10: goto tr124;
2716
+ case 13: goto tr125;
2717
+ case 32: goto tr55;
2718
+ case 35: goto tr126;
2719
+ case 37: goto tr127;
2720
+ case 127: goto st0;
2721
+ }
2722
+ if ( 0 <= (*p) && (*p) <= 31 )
2723
+ goto st0;
2724
+ goto tr123;
2725
+ tr123:
2726
+ #line 358 "unicorn_http.rl"
2727
+ {MARK(start.query, p); }
2728
+ goto st81;
2729
+ st81:
2730
+ if ( ++p == pe )
2731
+ goto _test_eof81;
2732
+ case 81:
2733
+ #line 2734 "unicorn_http.c"
2734
+ switch( (*p) ) {
2735
+ case 10: goto tr129;
2736
+ case 13: goto tr130;
2737
+ case 32: goto tr59;
2738
+ case 35: goto tr131;
2739
+ case 37: goto st82;
2740
+ case 127: goto st0;
2741
+ }
2742
+ if ( 0 <= (*p) && (*p) <= 31 )
2743
+ goto st0;
2744
+ goto st81;
2745
+ tr127:
2746
+ #line 358 "unicorn_http.rl"
2747
+ {MARK(start.query, p); }
2748
+ goto st82;
2749
+ st82:
2750
+ if ( ++p == pe )
2751
+ goto _test_eof82;
2752
+ case 82:
2753
+ #line 2754 "unicorn_http.c"
2754
+ if ( (*p) < 65 ) {
2755
+ if ( 48 <= (*p) && (*p) <= 57 )
2756
+ goto st83;
2757
+ } else if ( (*p) > 70 ) {
2758
+ if ( 97 <= (*p) && (*p) <= 102 )
2759
+ goto st83;
2760
+ } else
2761
+ goto st83;
2762
+ goto st0;
2763
+ st83:
2764
+ if ( ++p == pe )
2765
+ goto _test_eof83;
2766
+ case 83:
2767
+ if ( (*p) < 65 ) {
2768
+ if ( 48 <= (*p) && (*p) <= 57 )
2769
+ goto st81;
2770
+ } else if ( (*p) > 70 ) {
2771
+ if ( 97 <= (*p) && (*p) <= 102 )
2772
+ goto st81;
2773
+ } else
2774
+ goto st81;
2775
+ goto st0;
2776
+ tr103:
2777
+ #line 325 "unicorn_http.rl"
2778
+ {MARK(mark, p); }
2779
+ #line 329 "unicorn_http.rl"
2780
+ { downcase_char(deconst(p)); }
2781
+ goto st84;
2782
+ st84:
2783
+ if ( ++p == pe )
2784
+ goto _test_eof84;
2785
+ case 84:
2786
+ #line 2787 "unicorn_http.c"
2787
+ switch( (*p) ) {
2788
+ case 84: goto tr134;
2789
+ case 116: goto tr134;
2790
+ }
2791
+ goto st0;
2792
+ tr134:
2793
+ #line 329 "unicorn_http.rl"
2794
+ { downcase_char(deconst(p)); }
2795
+ goto st85;
2796
+ st85:
2797
+ if ( ++p == pe )
2798
+ goto _test_eof85;
2799
+ case 85:
2800
+ #line 2801 "unicorn_http.c"
2801
+ switch( (*p) ) {
2802
+ case 84: goto tr135;
2803
+ case 116: goto tr135;
2804
+ }
2805
+ goto st0;
2806
+ tr135:
2807
+ #line 329 "unicorn_http.rl"
2808
+ { downcase_char(deconst(p)); }
2809
+ goto st86;
2810
+ st86:
2811
+ if ( ++p == pe )
2812
+ goto _test_eof86;
2813
+ case 86:
2814
+ #line 2815 "unicorn_http.c"
2815
+ switch( (*p) ) {
2816
+ case 80: goto tr136;
2817
+ case 112: goto tr136;
2818
+ }
2819
+ goto st0;
2820
+ tr136:
2821
+ #line 329 "unicorn_http.rl"
2822
+ { downcase_char(deconst(p)); }
2823
+ goto st87;
2824
+ st87:
2825
+ if ( ++p == pe )
2826
+ goto _test_eof87;
2827
+ case 87:
2828
+ #line 2829 "unicorn_http.c"
2829
+ switch( (*p) ) {
2830
+ case 58: goto tr137;
2831
+ case 83: goto tr138;
2832
+ case 115: goto tr138;
2833
+ }
2834
+ goto st0;
2835
+ tr137:
2836
+ #line 335 "unicorn_http.rl"
2837
+ {
2838
+ rb_hash_aset(hp->env, g_rack_url_scheme, STR_NEW(mark, p));
2839
+ }
2840
+ goto st88;
2841
+ st88:
2842
+ if ( ++p == pe )
2843
+ goto _test_eof88;
2844
+ case 88:
2845
+ #line 2846 "unicorn_http.c"
2846
+ if ( (*p) == 47 )
2847
+ goto st89;
2848
+ goto st0;
2849
+ st89:
2850
+ if ( ++p == pe )
2851
+ goto _test_eof89;
2852
+ case 89:
2853
+ if ( (*p) == 47 )
2854
+ goto st90;
2855
+ goto st0;
2856
+ st90:
2857
+ if ( ++p == pe )
2858
+ goto _test_eof90;
2859
+ case 90:
2860
+ switch( (*p) ) {
2861
+ case 37: goto st92;
2862
+ case 47: goto st0;
2863
+ case 60: goto st0;
2864
+ case 91: goto tr144;
2865
+ case 95: goto tr143;
2866
+ case 127: goto st0;
2867
+ }
2868
+ if ( (*p) < 45 ) {
2869
+ if ( (*p) > 32 ) {
2870
+ if ( 34 <= (*p) && (*p) <= 35 )
2871
+ goto st0;
2872
+ } else if ( (*p) >= 0 )
2873
+ goto st0;
2874
+ } else if ( (*p) > 57 ) {
2875
+ if ( (*p) < 65 ) {
2876
+ if ( 62 <= (*p) && (*p) <= 64 )
2877
+ goto st0;
2878
+ } else if ( (*p) > 90 ) {
2879
+ if ( 97 <= (*p) && (*p) <= 122 )
2880
+ goto tr143;
2881
+ } else
2882
+ goto tr143;
2883
+ } else
2884
+ goto tr143;
2885
+ goto st91;
2886
+ st91:
2887
+ if ( ++p == pe )
2888
+ goto _test_eof91;
2889
+ case 91:
2890
+ switch( (*p) ) {
2891
+ case 37: goto st92;
2892
+ case 47: goto st0;
2893
+ case 60: goto st0;
2894
+ case 64: goto st90;
2895
+ case 127: goto st0;
2896
+ }
2897
+ if ( (*p) < 34 ) {
2898
+ if ( 0 <= (*p) && (*p) <= 32 )
2899
+ goto st0;
2900
+ } else if ( (*p) > 35 ) {
2901
+ if ( 62 <= (*p) && (*p) <= 63 )
2902
+ goto st0;
2903
+ } else
2904
+ goto st0;
2905
+ goto st91;
2906
+ st92:
2907
+ if ( ++p == pe )
2908
+ goto _test_eof92;
2909
+ case 92:
2910
+ if ( (*p) < 65 ) {
2911
+ if ( 48 <= (*p) && (*p) <= 57 )
2912
+ goto st93;
2913
+ } else if ( (*p) > 70 ) {
2914
+ if ( 97 <= (*p) && (*p) <= 102 )
2915
+ goto st93;
2916
+ } else
2917
+ goto st93;
2918
+ goto st0;
2919
+ st93:
2920
+ if ( ++p == pe )
2921
+ goto _test_eof93;
2922
+ case 93:
2923
+ if ( (*p) < 65 ) {
2924
+ if ( 48 <= (*p) && (*p) <= 57 )
2925
+ goto st91;
2926
+ } else if ( (*p) > 70 ) {
2927
+ if ( 97 <= (*p) && (*p) <= 102 )
2928
+ goto st91;
2929
+ } else
2930
+ goto st91;
2931
+ goto st0;
2932
+ tr143:
2933
+ #line 325 "unicorn_http.rl"
2934
+ {MARK(mark, p); }
2935
+ goto st94;
2936
+ st94:
2937
+ if ( ++p == pe )
2938
+ goto _test_eof94;
2939
+ case 94:
2940
+ #line 2941 "unicorn_http.c"
2941
+ switch( (*p) ) {
2942
+ case 37: goto st92;
2943
+ case 47: goto tr147;
2944
+ case 58: goto st95;
2945
+ case 60: goto st0;
2946
+ case 64: goto st90;
2947
+ case 95: goto st94;
2948
+ case 127: goto st0;
2949
+ }
2950
+ if ( (*p) < 45 ) {
2951
+ if ( (*p) > 32 ) {
2952
+ if ( 34 <= (*p) && (*p) <= 35 )
2953
+ goto st0;
2954
+ } else if ( (*p) >= 0 )
2955
+ goto st0;
2956
+ } else if ( (*p) > 57 ) {
2957
+ if ( (*p) < 65 ) {
2958
+ if ( 62 <= (*p) && (*p) <= 63 )
2959
+ goto st0;
2960
+ } else if ( (*p) > 90 ) {
2961
+ if ( 97 <= (*p) && (*p) <= 122 )
2962
+ goto st94;
2963
+ } else
2964
+ goto st94;
2965
+ } else
2966
+ goto st94;
2967
+ goto st91;
2968
+ st95:
2969
+ if ( ++p == pe )
2970
+ goto _test_eof95;
2971
+ case 95:
2972
+ switch( (*p) ) {
2973
+ case 37: goto st92;
2974
+ case 47: goto tr147;
2975
+ case 60: goto st0;
2976
+ case 64: goto st90;
2977
+ case 127: goto st0;
2978
+ }
2979
+ if ( (*p) < 34 ) {
2980
+ if ( 0 <= (*p) && (*p) <= 32 )
2981
+ goto st0;
2982
+ } else if ( (*p) > 35 ) {
2983
+ if ( (*p) > 57 ) {
2984
+ if ( 62 <= (*p) && (*p) <= 63 )
2985
+ goto st0;
2986
+ } else if ( (*p) >= 48 )
2987
+ goto st95;
2988
+ } else
2989
+ goto st0;
2990
+ goto st91;
2991
+ tr144:
2992
+ #line 325 "unicorn_http.rl"
2993
+ {MARK(mark, p); }
2994
+ goto st96;
2995
+ st96:
2996
+ if ( ++p == pe )
2997
+ goto _test_eof96;
2998
+ case 96:
2999
+ #line 3000 "unicorn_http.c"
3000
+ switch( (*p) ) {
3001
+ case 37: goto st92;
3002
+ case 47: goto st0;
3003
+ case 60: goto st0;
3004
+ case 64: goto st90;
3005
+ case 127: goto st0;
3006
+ }
3007
+ if ( (*p) < 48 ) {
3008
+ if ( (*p) > 32 ) {
3009
+ if ( 34 <= (*p) && (*p) <= 35 )
3010
+ goto st0;
3011
+ } else if ( (*p) >= 0 )
3012
+ goto st0;
3013
+ } else if ( (*p) > 58 ) {
3014
+ if ( (*p) < 65 ) {
3015
+ if ( 62 <= (*p) && (*p) <= 63 )
3016
+ goto st0;
3017
+ } else if ( (*p) > 70 ) {
3018
+ if ( 97 <= (*p) && (*p) <= 102 )
3019
+ goto st97;
3020
+ } else
3021
+ goto st97;
3022
+ } else
3023
+ goto st97;
3024
+ goto st91;
3025
+ st97:
3026
+ if ( ++p == pe )
3027
+ goto _test_eof97;
3028
+ case 97:
3029
+ switch( (*p) ) {
3030
+ case 37: goto st92;
3031
+ case 47: goto st0;
3032
+ case 60: goto st0;
3033
+ case 64: goto st90;
3034
+ case 93: goto st98;
3035
+ case 127: goto st0;
3036
+ }
3037
+ if ( (*p) < 48 ) {
3038
+ if ( (*p) > 32 ) {
3039
+ if ( 34 <= (*p) && (*p) <= 35 )
3040
+ goto st0;
3041
+ } else if ( (*p) >= 0 )
3042
+ goto st0;
3043
+ } else if ( (*p) > 58 ) {
3044
+ if ( (*p) < 65 ) {
3045
+ if ( 62 <= (*p) && (*p) <= 63 )
3046
+ goto st0;
3047
+ } else if ( (*p) > 70 ) {
3048
+ if ( 97 <= (*p) && (*p) <= 102 )
3049
+ goto st97;
3050
+ } else
3051
+ goto st97;
3052
+ } else
3053
+ goto st97;
3054
+ goto st91;
3055
+ st98:
3056
+ if ( ++p == pe )
3057
+ goto _test_eof98;
3058
+ case 98:
3059
+ switch( (*p) ) {
3060
+ case 37: goto st92;
3061
+ case 47: goto tr147;
3062
+ case 58: goto st95;
3063
+ case 60: goto st0;
3064
+ case 64: goto st90;
3065
+ case 127: goto st0;
3066
+ }
3067
+ if ( (*p) < 34 ) {
3068
+ if ( 0 <= (*p) && (*p) <= 32 )
3069
+ goto st0;
3070
+ } else if ( (*p) > 35 ) {
3071
+ if ( 62 <= (*p) && (*p) <= 63 )
3072
+ goto st0;
3073
+ } else
3074
+ goto st0;
3075
+ goto st91;
3076
+ tr138:
3077
+ #line 329 "unicorn_http.rl"
3078
+ { downcase_char(deconst(p)); }
3079
+ goto st99;
3080
+ st99:
3081
+ if ( ++p == pe )
3082
+ goto _test_eof99;
3083
+ case 99:
3084
+ #line 3085 "unicorn_http.c"
3085
+ if ( (*p) == 58 )
3086
+ goto tr137;
3087
+ goto st0;
3088
+ st100:
3089
+ if ( ++p == pe )
3090
+ goto _test_eof100;
3091
+ case 100:
3092
+ if ( (*p) == 48 )
3093
+ goto tr151;
3094
+ if ( (*p) < 65 ) {
3095
+ if ( 49 <= (*p) && (*p) <= 57 )
3096
+ goto tr152;
3097
+ } else if ( (*p) > 70 ) {
3098
+ if ( 97 <= (*p) && (*p) <= 102 )
3099
+ goto tr152;
3100
+ } else
3101
+ goto tr152;
3102
+ goto st0;
3103
+ tr151:
3104
+ #line 374 "unicorn_http.rl"
3105
+ {
3106
+ hp->len.chunk = step_incr(hp->len.chunk, (*p), 16);
3107
+ if (hp->len.chunk < 0)
3108
+ parser_raise(eHttpParserError, "invalid chunk size");
3109
+ }
3110
+ goto st101;
3111
+ st101:
3112
+ if ( ++p == pe )
3113
+ goto _test_eof101;
3114
+ case 101:
3115
+ #line 3116 "unicorn_http.c"
3116
+ switch( (*p) ) {
3117
+ case 10: goto tr153;
3118
+ case 13: goto st102;
3119
+ case 48: goto tr151;
3120
+ case 59: goto st111;
3121
+ }
3122
+ if ( (*p) < 65 ) {
3123
+ if ( 49 <= (*p) && (*p) <= 57 )
3124
+ goto tr152;
3125
+ } else if ( (*p) > 70 ) {
3126
+ if ( 97 <= (*p) && (*p) <= 102 )
3127
+ goto tr152;
3128
+ } else
3129
+ goto tr152;
3130
+ goto st0;
3131
+ tr153:
3132
+ #line 403 "unicorn_http.rl"
3133
+ {
3134
+ HP_FL_SET(hp, INTRAILER);
3135
+ cs = http_parser_en_Trailers;
3136
+ ++p;
3137
+ assert(p <= pe && "buffer overflow after chunked body");
3138
+ goto post_exec;
3139
+ }
3140
+ goto st123;
3141
+ st123:
3142
+ if ( ++p == pe )
3143
+ goto _test_eof123;
3144
+ case 123:
3145
+ #line 3146 "unicorn_http.c"
3146
+ goto st0;
3147
+ st102:
3148
+ if ( ++p == pe )
3149
+ goto _test_eof102;
3150
+ case 102:
3151
+ if ( (*p) == 10 )
3152
+ goto tr153;
3153
+ goto st0;
3154
+ tr152:
3155
+ #line 374 "unicorn_http.rl"
3156
+ {
3157
+ hp->len.chunk = step_incr(hp->len.chunk, (*p), 16);
3158
+ if (hp->len.chunk < 0)
3159
+ parser_raise(eHttpParserError, "invalid chunk size");
3160
+ }
3161
+ goto st103;
3162
+ st103:
3163
+ if ( ++p == pe )
3164
+ goto _test_eof103;
3165
+ case 103:
3166
+ #line 3167 "unicorn_http.c"
3167
+ switch( (*p) ) {
3168
+ case 10: goto st104;
3169
+ case 13: goto st107;
3170
+ case 59: goto st108;
3171
+ }
3172
+ if ( (*p) < 65 ) {
3173
+ if ( 48 <= (*p) && (*p) <= 57 )
3174
+ goto tr152;
3175
+ } else if ( (*p) > 70 ) {
3176
+ if ( 97 <= (*p) && (*p) <= 102 )
3177
+ goto tr152;
3178
+ } else
3179
+ goto tr152;
3180
+ goto st0;
3181
+ st104:
3182
+ if ( ++p == pe )
3183
+ goto _test_eof104;
3184
+ case 104:
3185
+ goto tr159;
3186
+ tr159:
3187
+ #line 411 "unicorn_http.rl"
3188
+ {
3189
+ skip_chunk_data_hack: {
3190
+ size_t nr = MIN((size_t)hp->len.chunk, REMAINING);
3191
+ memcpy(RSTRING_PTR(hp->cont) + hp->s.dest_offset, p, nr);
3192
+ hp->s.dest_offset += nr;
3193
+ hp->len.chunk -= nr;
3194
+ p += nr;
3195
+ assert(hp->len.chunk >= 0 && "negative chunk length");
3196
+ if ((size_t)hp->len.chunk > REMAINING) {
3197
+ HP_FL_SET(hp, INCHUNK);
3198
+ goto post_exec;
3199
+ } else {
3200
+ p--;
3201
+ {goto st105;}
3202
+ }
3203
+ }}
3204
+ goto st105;
3205
+ st105:
3206
+ if ( ++p == pe )
3207
+ goto _test_eof105;
3208
+ case 105:
3209
+ #line 3210 "unicorn_http.c"
3210
+ switch( (*p) ) {
3211
+ case 10: goto st100;
3212
+ case 13: goto st106;
3213
+ }
3214
+ goto st0;
3215
+ st106:
3216
+ if ( ++p == pe )
3217
+ goto _test_eof106;
3218
+ case 106:
3219
+ if ( (*p) == 10 )
3220
+ goto st100;
3221
+ goto st0;
3222
+ st107:
3223
+ if ( ++p == pe )
3224
+ goto _test_eof107;
3225
+ case 107:
3226
+ if ( (*p) == 10 )
3227
+ goto st104;
3228
+ goto st0;
3229
+ st108:
3230
+ if ( ++p == pe )
3231
+ goto _test_eof108;
3232
+ case 108:
3233
+ switch( (*p) ) {
3234
+ case 10: goto st104;
3235
+ case 13: goto st107;
3236
+ case 32: goto st108;
3237
+ case 33: goto st109;
3238
+ case 59: goto st108;
3239
+ case 61: goto st110;
3240
+ case 124: goto st109;
3241
+ case 126: goto st109;
3242
+ }
3243
+ if ( (*p) < 45 ) {
3244
+ if ( (*p) > 39 ) {
3245
+ if ( 42 <= (*p) && (*p) <= 43 )
3246
+ goto st109;
3247
+ } else if ( (*p) >= 35 )
3248
+ goto st109;
3249
+ } else if ( (*p) > 46 ) {
3250
+ if ( (*p) < 65 ) {
3251
+ if ( 48 <= (*p) && (*p) <= 57 )
3252
+ goto st109;
3253
+ } else if ( (*p) > 90 ) {
3254
+ if ( 94 <= (*p) && (*p) <= 122 )
3255
+ goto st109;
3256
+ } else
3257
+ goto st109;
3258
+ } else
3259
+ goto st109;
3260
+ goto st0;
3261
+ st109:
3262
+ if ( ++p == pe )
3263
+ goto _test_eof109;
3264
+ case 109:
3265
+ switch( (*p) ) {
3266
+ case 10: goto st104;
3267
+ case 13: goto st107;
3268
+ case 33: goto st109;
3269
+ case 59: goto st108;
3270
+ case 61: goto st110;
3271
+ case 124: goto st109;
3272
+ case 126: goto st109;
3273
+ }
3274
+ if ( (*p) < 45 ) {
3275
+ if ( (*p) > 39 ) {
3276
+ if ( 42 <= (*p) && (*p) <= 43 )
3277
+ goto st109;
3278
+ } else if ( (*p) >= 35 )
3279
+ goto st109;
3280
+ } else if ( (*p) > 46 ) {
3281
+ if ( (*p) < 65 ) {
3282
+ if ( 48 <= (*p) && (*p) <= 57 )
3283
+ goto st109;
3284
+ } else if ( (*p) > 90 ) {
3285
+ if ( 94 <= (*p) && (*p) <= 122 )
3286
+ goto st109;
3287
+ } else
3288
+ goto st109;
3289
+ } else
3290
+ goto st109;
3291
+ goto st0;
3292
+ st110:
3293
+ if ( ++p == pe )
3294
+ goto _test_eof110;
3295
+ case 110:
3296
+ switch( (*p) ) {
3297
+ case 10: goto st104;
3298
+ case 13: goto st107;
3299
+ case 33: goto st110;
3300
+ case 59: goto st108;
3301
+ case 124: goto st110;
3302
+ case 126: goto st110;
3303
+ }
3304
+ if ( (*p) < 45 ) {
3305
+ if ( (*p) > 39 ) {
3306
+ if ( 42 <= (*p) && (*p) <= 43 )
3307
+ goto st110;
3308
+ } else if ( (*p) >= 35 )
3309
+ goto st110;
3310
+ } else if ( (*p) > 46 ) {
3311
+ if ( (*p) < 65 ) {
3312
+ if ( 48 <= (*p) && (*p) <= 57 )
3313
+ goto st110;
3314
+ } else if ( (*p) > 90 ) {
3315
+ if ( 94 <= (*p) && (*p) <= 122 )
3316
+ goto st110;
3317
+ } else
3318
+ goto st110;
3319
+ } else
3320
+ goto st110;
3321
+ goto st0;
3322
+ st111:
3323
+ if ( ++p == pe )
3324
+ goto _test_eof111;
3325
+ case 111:
3326
+ switch( (*p) ) {
3327
+ case 10: goto tr153;
3328
+ case 13: goto st102;
3329
+ case 32: goto st111;
3330
+ case 33: goto st112;
3331
+ case 59: goto st111;
3332
+ case 61: goto st113;
3333
+ case 124: goto st112;
3334
+ case 126: goto st112;
3335
+ }
3336
+ if ( (*p) < 45 ) {
3337
+ if ( (*p) > 39 ) {
3338
+ if ( 42 <= (*p) && (*p) <= 43 )
3339
+ goto st112;
3340
+ } else if ( (*p) >= 35 )
3341
+ goto st112;
3342
+ } else if ( (*p) > 46 ) {
3343
+ if ( (*p) < 65 ) {
3344
+ if ( 48 <= (*p) && (*p) <= 57 )
3345
+ goto st112;
3346
+ } else if ( (*p) > 90 ) {
3347
+ if ( 94 <= (*p) && (*p) <= 122 )
3348
+ goto st112;
3349
+ } else
3350
+ goto st112;
3351
+ } else
3352
+ goto st112;
3353
+ goto st0;
3354
+ st112:
3355
+ if ( ++p == pe )
3356
+ goto _test_eof112;
3357
+ case 112:
3358
+ switch( (*p) ) {
3359
+ case 10: goto tr153;
3360
+ case 13: goto st102;
3361
+ case 33: goto st112;
3362
+ case 59: goto st111;
3363
+ case 61: goto st113;
3364
+ case 124: goto st112;
3365
+ case 126: goto st112;
3366
+ }
3367
+ if ( (*p) < 45 ) {
3368
+ if ( (*p) > 39 ) {
3369
+ if ( 42 <= (*p) && (*p) <= 43 )
3370
+ goto st112;
3371
+ } else if ( (*p) >= 35 )
3372
+ goto st112;
3373
+ } else if ( (*p) > 46 ) {
3374
+ if ( (*p) < 65 ) {
3375
+ if ( 48 <= (*p) && (*p) <= 57 )
3376
+ goto st112;
3377
+ } else if ( (*p) > 90 ) {
3378
+ if ( 94 <= (*p) && (*p) <= 122 )
3379
+ goto st112;
3380
+ } else
3381
+ goto st112;
3382
+ } else
3383
+ goto st112;
3384
+ goto st0;
3385
+ st113:
3386
+ if ( ++p == pe )
3387
+ goto _test_eof113;
3388
+ case 113:
3389
+ switch( (*p) ) {
3390
+ case 10: goto tr153;
3391
+ case 13: goto st102;
3392
+ case 33: goto st113;
3393
+ case 59: goto st111;
3394
+ case 124: goto st113;
3395
+ case 126: goto st113;
3396
+ }
3397
+ if ( (*p) < 45 ) {
3398
+ if ( (*p) > 39 ) {
3399
+ if ( 42 <= (*p) && (*p) <= 43 )
3400
+ goto st113;
3401
+ } else if ( (*p) >= 35 )
3402
+ goto st113;
3403
+ } else if ( (*p) > 46 ) {
3404
+ if ( (*p) < 65 ) {
3405
+ if ( 48 <= (*p) && (*p) <= 57 )
3406
+ goto st113;
3407
+ } else if ( (*p) > 90 ) {
3408
+ if ( 94 <= (*p) && (*p) <= 122 )
3409
+ goto st113;
3410
+ } else
3411
+ goto st113;
3412
+ } else
3413
+ goto st113;
3414
+ goto st0;
3415
+ tr172:
3416
+ #line 331 "unicorn_http.rl"
3417
+ { MARK(mark, p); }
3418
+ #line 333 "unicorn_http.rl"
3419
+ { write_cont_value(hp, buffer, p); }
3420
+ goto st114;
3421
+ tr175:
3422
+ #line 333 "unicorn_http.rl"
3423
+ { write_cont_value(hp, buffer, p); }
3424
+ goto st114;
3425
+ tr182:
3426
+ #line 331 "unicorn_http.rl"
3427
+ { MARK(mark, p); }
3428
+ #line 332 "unicorn_http.rl"
3429
+ { write_value(hp, buffer, p); }
3430
+ goto st114;
3431
+ tr185:
3432
+ #line 332 "unicorn_http.rl"
3433
+ { write_value(hp, buffer, p); }
3434
+ goto st114;
3435
+ st114:
3436
+ if ( ++p == pe )
3437
+ goto _test_eof114;
3438
+ case 114:
3439
+ #line 3440 "unicorn_http.c"
3440
+ switch( (*p) ) {
3441
+ case 9: goto st115;
3442
+ case 10: goto tr167;
3443
+ case 13: goto st118;
3444
+ case 32: goto st115;
3445
+ case 33: goto tr169;
3446
+ case 124: goto tr169;
3447
+ case 126: goto tr169;
3448
+ }
3449
+ if ( (*p) < 45 ) {
3450
+ if ( (*p) > 39 ) {
3451
+ if ( 42 <= (*p) && (*p) <= 43 )
3452
+ goto tr169;
3453
+ } else if ( (*p) >= 35 )
3454
+ goto tr169;
3455
+ } else if ( (*p) > 46 ) {
3456
+ if ( (*p) < 65 ) {
3457
+ if ( 48 <= (*p) && (*p) <= 57 )
3458
+ goto tr169;
3459
+ } else if ( (*p) > 90 ) {
3460
+ if ( 94 <= (*p) && (*p) <= 122 )
3461
+ goto tr169;
3462
+ } else
3463
+ goto tr169;
3464
+ } else
3465
+ goto tr169;
3466
+ goto st0;
3467
+ tr171:
3468
+ #line 331 "unicorn_http.rl"
3469
+ { MARK(mark, p); }
3470
+ goto st115;
3471
+ st115:
3472
+ if ( ++p == pe )
3473
+ goto _test_eof115;
3474
+ case 115:
3475
+ #line 3476 "unicorn_http.c"
3476
+ switch( (*p) ) {
3477
+ case 9: goto tr171;
3478
+ case 10: goto tr172;
3479
+ case 13: goto tr173;
3480
+ case 32: goto tr171;
3481
+ case 127: goto st0;
3482
+ }
3483
+ if ( 0 <= (*p) && (*p) <= 31 )
3484
+ goto st0;
3485
+ goto tr170;
3486
+ tr170:
3487
+ #line 331 "unicorn_http.rl"
3488
+ { MARK(mark, p); }
3489
+ goto st116;
3490
+ st116:
3491
+ if ( ++p == pe )
3492
+ goto _test_eof116;
3493
+ case 116:
3494
+ #line 3495 "unicorn_http.c"
3495
+ switch( (*p) ) {
3496
+ case 10: goto tr175;
3497
+ case 13: goto tr176;
3498
+ case 127: goto st0;
3499
+ }
3500
+ if ( (*p) > 8 ) {
3501
+ if ( 11 <= (*p) && (*p) <= 31 )
3502
+ goto st0;
3503
+ } else if ( (*p) >= 0 )
3504
+ goto st0;
3505
+ goto st116;
3506
+ tr173:
3507
+ #line 331 "unicorn_http.rl"
3508
+ { MARK(mark, p); }
3509
+ #line 333 "unicorn_http.rl"
3510
+ { write_cont_value(hp, buffer, p); }
3511
+ goto st117;
3512
+ tr176:
3513
+ #line 333 "unicorn_http.rl"
3514
+ { write_cont_value(hp, buffer, p); }
3515
+ goto st117;
3516
+ tr183:
3517
+ #line 331 "unicorn_http.rl"
3518
+ { MARK(mark, p); }
3519
+ #line 332 "unicorn_http.rl"
3520
+ { write_value(hp, buffer, p); }
3521
+ goto st117;
3522
+ tr186:
3523
+ #line 332 "unicorn_http.rl"
3524
+ { write_value(hp, buffer, p); }
3525
+ goto st117;
3526
+ st117:
3527
+ if ( ++p == pe )
3528
+ goto _test_eof117;
3529
+ case 117:
3530
+ #line 3531 "unicorn_http.c"
3531
+ if ( (*p) == 10 )
3532
+ goto st114;
3533
+ goto st0;
3534
+ tr167:
3535
+ #line 398 "unicorn_http.rl"
3536
+ {
3537
+ cs = http_parser_first_final;
3538
+ goto post_exec;
3539
+ }
3540
+ goto st124;
3541
+ st124:
3542
+ if ( ++p == pe )
3543
+ goto _test_eof124;
3544
+ case 124:
3545
+ #line 3546 "unicorn_http.c"
3546
+ goto st0;
3547
+ st118:
3548
+ if ( ++p == pe )
3549
+ goto _test_eof118;
3550
+ case 118:
3551
+ if ( (*p) == 10 )
3552
+ goto tr167;
3553
+ goto st0;
3554
+ tr169:
3555
+ #line 327 "unicorn_http.rl"
3556
+ { MARK(start.field, p); }
3557
+ #line 328 "unicorn_http.rl"
3558
+ { snake_upcase_char(deconst(p)); }
3559
+ goto st119;
3560
+ tr178:
3561
+ #line 328 "unicorn_http.rl"
3562
+ { snake_upcase_char(deconst(p)); }
3563
+ goto st119;
3564
+ st119:
3565
+ if ( ++p == pe )
3566
+ goto _test_eof119;
3567
+ case 119:
3568
+ #line 3569 "unicorn_http.c"
3569
+ switch( (*p) ) {
3570
+ case 33: goto tr178;
3571
+ case 58: goto tr179;
3572
+ case 124: goto tr178;
3573
+ case 126: goto tr178;
3574
+ }
3575
+ if ( (*p) < 45 ) {
3576
+ if ( (*p) > 39 ) {
3577
+ if ( 42 <= (*p) && (*p) <= 43 )
3578
+ goto tr178;
3579
+ } else if ( (*p) >= 35 )
3580
+ goto tr178;
3581
+ } else if ( (*p) > 46 ) {
3582
+ if ( (*p) < 65 ) {
3583
+ if ( 48 <= (*p) && (*p) <= 57 )
3584
+ goto tr178;
3585
+ } else if ( (*p) > 90 ) {
3586
+ if ( 94 <= (*p) && (*p) <= 122 )
3587
+ goto tr178;
3588
+ } else
3589
+ goto tr178;
3590
+ } else
3591
+ goto tr178;
3592
+ goto st0;
3593
+ tr181:
3594
+ #line 331 "unicorn_http.rl"
3595
+ { MARK(mark, p); }
3596
+ goto st120;
3597
+ tr179:
3598
+ #line 330 "unicorn_http.rl"
3599
+ { hp->s.field_len = LEN(start.field, p); }
3600
+ goto st120;
3601
+ st120:
3602
+ if ( ++p == pe )
3603
+ goto _test_eof120;
3604
+ case 120:
3605
+ #line 3606 "unicorn_http.c"
3606
+ switch( (*p) ) {
3607
+ case 9: goto tr181;
3608
+ case 10: goto tr182;
3609
+ case 13: goto tr183;
3610
+ case 32: goto tr181;
3611
+ case 127: goto st0;
3612
+ }
3613
+ if ( 0 <= (*p) && (*p) <= 31 )
3614
+ goto st0;
3615
+ goto tr180;
3616
+ tr180:
3617
+ #line 331 "unicorn_http.rl"
3618
+ { MARK(mark, p); }
3619
+ goto st121;
3620
+ st121:
3621
+ if ( ++p == pe )
3622
+ goto _test_eof121;
3623
+ case 121:
3624
+ #line 3625 "unicorn_http.c"
3625
+ switch( (*p) ) {
3626
+ case 10: goto tr185;
3627
+ case 13: goto tr186;
3628
+ case 127: goto st0;
3629
+ }
3630
+ if ( (*p) > 8 ) {
3631
+ if ( 11 <= (*p) && (*p) <= 31 )
3632
+ goto st0;
3633
+ } else if ( (*p) >= 0 )
3634
+ goto st0;
3635
+ goto st121;
3636
+ }
3637
+ _test_eof2: cs = 2; goto _test_eof;
3638
+ _test_eof3: cs = 3; goto _test_eof;
3639
+ _test_eof4: cs = 4; goto _test_eof;
3640
+ _test_eof5: cs = 5; goto _test_eof;
3641
+ _test_eof6: cs = 6; goto _test_eof;
3642
+ _test_eof7: cs = 7; goto _test_eof;
3643
+ _test_eof8: cs = 8; goto _test_eof;
3644
+ _test_eof9: cs = 9; goto _test_eof;
3645
+ _test_eof10: cs = 10; goto _test_eof;
3646
+ _test_eof11: cs = 11; goto _test_eof;
3647
+ _test_eof12: cs = 12; goto _test_eof;
3648
+ _test_eof13: cs = 13; goto _test_eof;
3649
+ _test_eof14: cs = 14; goto _test_eof;
3650
+ _test_eof15: cs = 15; goto _test_eof;
3651
+ _test_eof16: cs = 16; goto _test_eof;
3652
+ _test_eof17: cs = 17; goto _test_eof;
3653
+ _test_eof122: cs = 122; goto _test_eof;
3654
+ _test_eof18: cs = 18; goto _test_eof;
3655
+ _test_eof19: cs = 19; goto _test_eof;
3656
+ _test_eof20: cs = 20; goto _test_eof;
3657
+ _test_eof21: cs = 21; goto _test_eof;
3658
+ _test_eof22: cs = 22; goto _test_eof;
3659
+ _test_eof23: cs = 23; goto _test_eof;
3660
+ _test_eof24: cs = 24; goto _test_eof;
3661
+ _test_eof25: cs = 25; goto _test_eof;
3662
+ _test_eof26: cs = 26; goto _test_eof;
3663
+ _test_eof27: cs = 27; goto _test_eof;
3664
+ _test_eof28: cs = 28; goto _test_eof;
3665
+ _test_eof29: cs = 29; goto _test_eof;
3666
+ _test_eof30: cs = 30; goto _test_eof;
3667
+ _test_eof31: cs = 31; goto _test_eof;
3668
+ _test_eof32: cs = 32; goto _test_eof;
3669
+ _test_eof33: cs = 33; goto _test_eof;
3670
+ _test_eof34: cs = 34; goto _test_eof;
3671
+ _test_eof35: cs = 35; goto _test_eof;
3672
+ _test_eof36: cs = 36; goto _test_eof;
3673
+ _test_eof37: cs = 37; goto _test_eof;
3674
+ _test_eof38: cs = 38; goto _test_eof;
3675
+ _test_eof39: cs = 39; goto _test_eof;
3676
+ _test_eof40: cs = 40; goto _test_eof;
3677
+ _test_eof41: cs = 41; goto _test_eof;
3678
+ _test_eof42: cs = 42; goto _test_eof;
3679
+ _test_eof43: cs = 43; goto _test_eof;
3680
+ _test_eof44: cs = 44; goto _test_eof;
3681
+ _test_eof45: cs = 45; goto _test_eof;
3682
+ _test_eof46: cs = 46; goto _test_eof;
3683
+ _test_eof47: cs = 47; goto _test_eof;
3684
+ _test_eof48: cs = 48; goto _test_eof;
3685
+ _test_eof49: cs = 49; goto _test_eof;
3686
+ _test_eof50: cs = 50; goto _test_eof;
3687
+ _test_eof51: cs = 51; goto _test_eof;
3688
+ _test_eof52: cs = 52; goto _test_eof;
3689
+ _test_eof53: cs = 53; goto _test_eof;
3690
+ _test_eof54: cs = 54; goto _test_eof;
3691
+ _test_eof55: cs = 55; goto _test_eof;
3692
+ _test_eof56: cs = 56; goto _test_eof;
3693
+ _test_eof57: cs = 57; goto _test_eof;
3694
+ _test_eof58: cs = 58; goto _test_eof;
3695
+ _test_eof59: cs = 59; goto _test_eof;
3696
+ _test_eof60: cs = 60; goto _test_eof;
3697
+ _test_eof61: cs = 61; goto _test_eof;
3698
+ _test_eof62: cs = 62; goto _test_eof;
3699
+ _test_eof63: cs = 63; goto _test_eof;
3700
+ _test_eof64: cs = 64; goto _test_eof;
3701
+ _test_eof65: cs = 65; goto _test_eof;
3702
+ _test_eof66: cs = 66; goto _test_eof;
3703
+ _test_eof67: cs = 67; goto _test_eof;
3704
+ _test_eof68: cs = 68; goto _test_eof;
3705
+ _test_eof69: cs = 69; goto _test_eof;
3706
+ _test_eof70: cs = 70; goto _test_eof;
3707
+ _test_eof71: cs = 71; goto _test_eof;
3708
+ _test_eof72: cs = 72; goto _test_eof;
3709
+ _test_eof73: cs = 73; goto _test_eof;
3710
+ _test_eof74: cs = 74; goto _test_eof;
3711
+ _test_eof75: cs = 75; goto _test_eof;
3712
+ _test_eof76: cs = 76; goto _test_eof;
3713
+ _test_eof77: cs = 77; goto _test_eof;
3714
+ _test_eof78: cs = 78; goto _test_eof;
3715
+ _test_eof79: cs = 79; goto _test_eof;
3716
+ _test_eof80: cs = 80; goto _test_eof;
3717
+ _test_eof81: cs = 81; goto _test_eof;
3718
+ _test_eof82: cs = 82; goto _test_eof;
3719
+ _test_eof83: cs = 83; goto _test_eof;
3720
+ _test_eof84: cs = 84; goto _test_eof;
3721
+ _test_eof85: cs = 85; goto _test_eof;
3722
+ _test_eof86: cs = 86; goto _test_eof;
3723
+ _test_eof87: cs = 87; goto _test_eof;
3724
+ _test_eof88: cs = 88; goto _test_eof;
3725
+ _test_eof89: cs = 89; goto _test_eof;
3726
+ _test_eof90: cs = 90; goto _test_eof;
3727
+ _test_eof91: cs = 91; goto _test_eof;
3728
+ _test_eof92: cs = 92; goto _test_eof;
3729
+ _test_eof93: cs = 93; goto _test_eof;
3730
+ _test_eof94: cs = 94; goto _test_eof;
3731
+ _test_eof95: cs = 95; goto _test_eof;
3732
+ _test_eof96: cs = 96; goto _test_eof;
3733
+ _test_eof97: cs = 97; goto _test_eof;
3734
+ _test_eof98: cs = 98; goto _test_eof;
3735
+ _test_eof99: cs = 99; goto _test_eof;
3736
+ _test_eof100: cs = 100; goto _test_eof;
3737
+ _test_eof101: cs = 101; goto _test_eof;
3738
+ _test_eof123: cs = 123; goto _test_eof;
3739
+ _test_eof102: cs = 102; goto _test_eof;
3740
+ _test_eof103: cs = 103; goto _test_eof;
3741
+ _test_eof104: cs = 104; goto _test_eof;
3742
+ _test_eof105: cs = 105; goto _test_eof;
3743
+ _test_eof106: cs = 106; goto _test_eof;
3744
+ _test_eof107: cs = 107; goto _test_eof;
3745
+ _test_eof108: cs = 108; goto _test_eof;
3746
+ _test_eof109: cs = 109; goto _test_eof;
3747
+ _test_eof110: cs = 110; goto _test_eof;
3748
+ _test_eof111: cs = 111; goto _test_eof;
3749
+ _test_eof112: cs = 112; goto _test_eof;
3750
+ _test_eof113: cs = 113; goto _test_eof;
3751
+ _test_eof114: cs = 114; goto _test_eof;
3752
+ _test_eof115: cs = 115; goto _test_eof;
3753
+ _test_eof116: cs = 116; goto _test_eof;
3754
+ _test_eof117: cs = 117; goto _test_eof;
3755
+ _test_eof124: cs = 124; goto _test_eof;
3756
+ _test_eof118: cs = 118; goto _test_eof;
3757
+ _test_eof119: cs = 119; goto _test_eof;
3758
+ _test_eof120: cs = 120; goto _test_eof;
3759
+ _test_eof121: cs = 121; goto _test_eof;
3760
+
3761
+ _test_eof: {}
3762
+ _out: {}
3763
+ }
3764
+
3765
+ #line 472 "unicorn_http.rl"
3766
+ post_exec: /* "_out:" also goes here */
3767
+ if (hp->cs != http_parser_error)
3768
+ hp->cs = cs;
3769
+ hp->offset = ulong2uint(p - buffer);
3770
+
3771
+ assert(p <= pe && "buffer overflow after parsing execute");
3772
+ assert(hp->offset <= len && "offset longer than length");
3773
+ }
3774
+
3775
+ static void hp_mark(void *ptr)
3776
+ {
3777
+ struct http_parser *hp = ptr;
3778
+
3779
+ rb_gc_mark(hp->buf);
3780
+ rb_gc_mark(hp->env);
3781
+ rb_gc_mark(hp->cont);
3782
+ }
3783
+
3784
+ static size_t hp_memsize(const void *ptr)
3785
+ {
3786
+ return sizeof(struct http_parser);
3787
+ }
3788
+
3789
+ static const rb_data_type_t hp_type = {
3790
+ "unicorn_http",
3791
+ { hp_mark, RUBY_TYPED_DEFAULT_FREE, hp_memsize, /* reserved */ },
3792
+ /* parent, data, [ flags ] */
3793
+ };
3794
+
3795
+ static struct http_parser *data_get(VALUE self)
3796
+ {
3797
+ struct http_parser *hp;
3798
+
3799
+ TypedData_Get_Struct(self, struct http_parser, &hp_type, hp);
3800
+ assert(hp && "failed to extract http_parser struct");
3801
+ return hp;
3802
+ }
3803
+
3804
+ /*
3805
+ * set rack.url_scheme to "https" or "http", no others are allowed by Rack
3806
+ * this resembles the Rack::Request#scheme method as of rack commit
3807
+ * 35bb5ba6746b5d346de9202c004cc926039650c7
3808
+ */
3809
+ static void set_url_scheme(VALUE env, VALUE *server_port)
3810
+ {
3811
+ VALUE scheme = rb_hash_aref(env, g_rack_url_scheme);
3812
+
3813
+ if (NIL_P(scheme)) {
3814
+ /*
3815
+ * would anybody be horribly opposed to removing the X-Forwarded-SSL
3816
+ * and X-Forwarded-Proto handling from this parser? We've had it
3817
+ * forever and nobody has said anything against it, either.
3818
+ * Anyways, please send comments to our public mailing list:
3819
+ * unicorn-public@yhbt.net (no HTML mail, no subscription necessary)
3820
+ */
3821
+ scheme = rb_hash_aref(env, g_http_x_forwarded_ssl);
3822
+ if (!NIL_P(scheme) && STR_CSTR_EQ(scheme, "on")) {
3823
+ *server_port = g_port_443;
3824
+ scheme = g_https;
3825
+ } else {
3826
+ scheme = rb_hash_aref(env, g_http_x_forwarded_proto);
3827
+ if (NIL_P(scheme)) {
3828
+ scheme = g_http;
3829
+ } else {
3830
+ long len = RSTRING_LEN(scheme);
3831
+ if (len >= 5 && !memcmp(RSTRING_PTR(scheme), "https", 5)) {
3832
+ if (len != 5)
3833
+ scheme = g_https;
3834
+ *server_port = g_port_443;
3835
+ } else {
3836
+ scheme = g_http;
3837
+ }
3838
+ }
3839
+ }
3840
+ rb_hash_aset(env, g_rack_url_scheme, scheme);
3841
+ } else if (STR_CSTR_EQ(scheme, "https")) {
3842
+ *server_port = g_port_443;
3843
+ } else {
3844
+ assert(*server_port == g_port_80 && "server_port not set");
3845
+ }
3846
+ }
3847
+
3848
+ /*
3849
+ * Parse and set the SERVER_NAME and SERVER_PORT variables
3850
+ * Not supporting X-Forwarded-Host/X-Forwarded-Port in here since
3851
+ * anybody who needs them is using an unsupported configuration and/or
3852
+ * incompetent. Rack::Request will handle X-Forwarded-{Port,Host} just
3853
+ * fine.
3854
+ */
3855
+ static void set_server_vars(VALUE env, VALUE *server_port)
3856
+ {
3857
+ VALUE server_name = g_localhost;
3858
+ VALUE host = rb_hash_aref(env, g_http_host);
3859
+
3860
+ if (!NIL_P(host)) {
3861
+ char *host_ptr = RSTRING_PTR(host);
3862
+ long host_len = RSTRING_LEN(host);
3863
+ char *colon;
3864
+
3865
+ if (*host_ptr == '[') { /* ipv6 address format */
3866
+ char *rbracket = memchr(host_ptr + 1, ']', host_len - 1);
3867
+
3868
+ if (rbracket)
3869
+ colon = (rbracket[1] == ':') ? rbracket + 1 : NULL;
3870
+ else
3871
+ colon = memchr(host_ptr + 1, ':', host_len - 1);
3872
+ } else {
3873
+ colon = memchr(host_ptr, ':', host_len);
3874
+ }
3875
+
3876
+ if (colon) {
3877
+ long port_start = colon - host_ptr + 1;
3878
+
3879
+ server_name = rb_str_substr(host, 0, colon - host_ptr);
3880
+ if ((host_len - port_start) > 0)
3881
+ *server_port = rb_str_substr(host, port_start, host_len);
3882
+ } else {
3883
+ server_name = host;
3884
+ }
3885
+ }
3886
+ rb_hash_aset(env, g_server_name, server_name);
3887
+ rb_hash_aset(env, g_server_port, *server_port);
3888
+ }
3889
+
3890
+ static void finalize_header(struct http_parser *hp)
3891
+ {
3892
+ VALUE server_port = g_port_80;
3893
+
3894
+ set_url_scheme(hp->env, &server_port);
3895
+ set_server_vars(hp->env, &server_port);
3896
+
3897
+ if (!HP_FL_TEST(hp, HASHEADER))
3898
+ rb_hash_aset(hp->env, g_server_protocol, g_http_09);
3899
+
3900
+ /* rack requires QUERY_STRING */
3901
+ if (NIL_P(rb_hash_aref(hp->env, g_query_string)))
3902
+ rb_hash_aset(hp->env, g_query_string, rb_str_new(NULL, 0));
3903
+ }
3904
+
3905
+ static VALUE HttpParser_alloc(VALUE klass)
3906
+ {
3907
+ struct http_parser *hp;
3908
+
3909
+ return TypedData_Make_Struct(klass, struct http_parser, &hp_type, hp);
3910
+ }
3911
+
3912
+ /**
3913
+ * call-seq:
3914
+ * parser.new => parser
3915
+ *
3916
+ * Creates a new parser.
3917
+ */
3918
+ static VALUE HttpParser_init(VALUE self)
3919
+ {
3920
+ struct http_parser *hp = data_get(self);
3921
+
3922
+ http_parser_init(hp);
3923
+ hp->buf = rb_str_new(NULL, 0);
3924
+ hp->env = rb_hash_new();
3925
+
3926
+ return self;
3927
+ }
3928
+
3929
+ /**
3930
+ * call-seq:
3931
+ * parser.clear => parser
3932
+ *
3933
+ * Resets the parser to it's initial state so that you can reuse it
3934
+ * rather than making new ones.
3935
+ */
3936
+ static VALUE HttpParser_clear(VALUE self)
3937
+ {
3938
+ struct http_parser *hp = data_get(self);
3939
+
3940
+ /* we can't safely reuse .buf and .env if hijacked */
3941
+ if (HP_FL_TEST(hp, HIJACK))
3942
+ return HttpParser_init(self);
3943
+
3944
+ http_parser_init(hp);
3945
+ rb_hash_clear(hp->env);
3946
+
3947
+ return self;
3948
+ }
3949
+
3950
+ static void advance_str(VALUE str, off_t nr)
3951
+ {
3952
+ long len = RSTRING_LEN(str);
3953
+
3954
+ if (len == 0)
3955
+ return;
3956
+
3957
+ rb_str_modify(str);
3958
+
3959
+ assert(nr <= len && "trying to advance past end of buffer");
3960
+ len -= nr;
3961
+ if (len > 0) /* unlikely, len is usually 0 */
3962
+ memmove(RSTRING_PTR(str), RSTRING_PTR(str) + nr, len);
3963
+ rb_str_set_len(str, len);
3964
+ }
3965
+
3966
+ /**
3967
+ * call-seq:
3968
+ * parser.content_length => nil or Integer
3969
+ *
3970
+ * Returns the number of bytes left to run through HttpParser#filter_body.
3971
+ * This will initially be the value of the "Content-Length" HTTP header
3972
+ * after header parsing is complete and will decrease in value as
3973
+ * HttpParser#filter_body is called for each chunk. This should return
3974
+ * zero for requests with no body.
3975
+ *
3976
+ * This will return nil on "Transfer-Encoding: chunked" requests.
3977
+ */
3978
+ static VALUE HttpParser_content_length(VALUE self)
3979
+ {
3980
+ struct http_parser *hp = data_get(self);
3981
+
3982
+ return HP_FL_TEST(hp, CHUNKED) ? Qnil : OFFT2NUM(hp->len.content);
3983
+ }
3984
+
3985
+ /**
3986
+ * Document-method: parse
3987
+ * call-seq:
3988
+ * parser.parse => env or nil
3989
+ *
3990
+ * Takes a Hash and a String of data, parses the String of data filling
3991
+ * in the Hash returning the Hash if parsing is finished, nil otherwise
3992
+ * When returning the env Hash, it may modify data to point to where
3993
+ * body processing should begin.
3994
+ *
3995
+ * Raises HttpParserError if there are parsing errors.
3996
+ */
3997
+ static VALUE HttpParser_parse(VALUE self)
3998
+ {
3999
+ struct http_parser *hp = data_get(self);
4000
+ VALUE data = hp->buf;
4001
+
4002
+ if (HP_FL_TEST(hp, TO_CLEAR))
4003
+ HttpParser_clear(self);
4004
+
4005
+ http_parser_execute(hp, RSTRING_PTR(data), RSTRING_LEN(data));
4006
+ if (hp->offset > MAX_HEADER_LEN)
4007
+ parser_raise(e413, "HTTP header is too large");
4008
+
4009
+ if (hp->cs == http_parser_first_final ||
4010
+ hp->cs == http_parser_en_ChunkedBody) {
4011
+ advance_str(data, hp->offset + 1);
4012
+ hp->offset = 0;
4013
+ if (HP_FL_TEST(hp, INTRAILER))
4014
+ HP_FL_SET(hp, REQEOF);
4015
+
4016
+ return hp->env;
4017
+ }
4018
+
4019
+ if (hp->cs == http_parser_error)
4020
+ parser_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
4021
+
4022
+ return Qnil;
4023
+ }
4024
+
4025
+ /**
4026
+ * Document-method: parse
4027
+ * call-seq:
4028
+ * parser.add_parse(buffer) => env or nil
4029
+ *
4030
+ * adds the contents of +buffer+ to the internal buffer and attempts to
4031
+ * continue parsing. Returns the +env+ Hash on success or nil if more
4032
+ * data is needed.
4033
+ *
4034
+ * Raises HttpParserError if there are parsing errors.
4035
+ */
4036
+ static VALUE HttpParser_add_parse(VALUE self, VALUE buffer)
4037
+ {
4038
+ struct http_parser *hp = data_get(self);
4039
+
4040
+ Check_Type(buffer, T_STRING);
4041
+ rb_str_buf_append(hp->buf, buffer);
4042
+
4043
+ return HttpParser_parse(self);
4044
+ }
4045
+
4046
+ /**
4047
+ * Document-method: trailers
4048
+ * call-seq:
4049
+ * parser.trailers(req, data) => req or nil
4050
+ *
4051
+ * This is an alias for HttpParser#headers
4052
+ */
4053
+
4054
+ /**
4055
+ * Document-method: headers
4056
+ */
4057
+ static VALUE HttpParser_headers(VALUE self, VALUE env, VALUE buf)
4058
+ {
4059
+ struct http_parser *hp = data_get(self);
4060
+
4061
+ hp->env = env;
4062
+ hp->buf = buf;
4063
+
4064
+ return HttpParser_parse(self);
4065
+ }
4066
+
4067
+ static int chunked_eof(struct http_parser *hp)
4068
+ {
4069
+ return ((hp->cs == http_parser_first_final) || HP_FL_TEST(hp, INTRAILER));
4070
+ }
4071
+
4072
+ /**
4073
+ * call-seq:
4074
+ * parser.body_eof? => true or false
4075
+ *
4076
+ * Detects if we're done filtering the body or not. This can be used
4077
+ * to detect when to stop calling HttpParser#filter_body.
4078
+ */
4079
+ static VALUE HttpParser_body_eof(VALUE self)
4080
+ {
4081
+ struct http_parser *hp = data_get(self);
4082
+
4083
+ if (HP_FL_TEST(hp, CHUNKED))
4084
+ return chunked_eof(hp) ? Qtrue : Qfalse;
4085
+
4086
+ return hp->len.content == 0 ? Qtrue : Qfalse;
4087
+ }
4088
+
4089
+ /**
4090
+ * call-seq:
4091
+ * parser.keepalive? => true or false
4092
+ *
4093
+ * This should be used to detect if a request can really handle
4094
+ * keepalives and pipelining. Currently, the rules are:
4095
+ *
4096
+ * 1. MUST be a GET or HEAD request
4097
+ * 2. MUST be HTTP/1.1 +or+ HTTP/1.0 with "Connection: keep-alive"
4098
+ * 3. MUST NOT have "Connection: close" set
4099
+ */
4100
+ static VALUE HttpParser_keepalive(VALUE self)
4101
+ {
4102
+ struct http_parser *hp = data_get(self);
4103
+
4104
+ return HP_FL_ALL(hp, KEEPALIVE) ? Qtrue : Qfalse;
4105
+ }
4106
+
4107
+ /* :nodoc: */
4108
+ static VALUE chunkable_response_p(VALUE self)
4109
+ {
4110
+ const struct http_parser *hp = data_get(self);
4111
+
4112
+ return HP_FL_ALL(hp, RES_CHUNKABLE) ? Qtrue : Qfalse;
4113
+ }
4114
+
4115
+ /**
4116
+ * call-seq:
4117
+ * parser.next? => true or false
4118
+ *
4119
+ * Exactly like HttpParser#keepalive?, except it will reset the internal
4120
+ * parser state on next parse if it returns true.
4121
+ */
4122
+ static VALUE HttpParser_next(VALUE self)
4123
+ {
4124
+ struct http_parser *hp = data_get(self);
4125
+
4126
+ if (HP_FL_ALL(hp, KEEPALIVE)) {
4127
+ HP_FL_SET(hp, TO_CLEAR);
4128
+ return Qtrue;
4129
+ }
4130
+ return Qfalse;
4131
+ }
4132
+
4133
+ /**
4134
+ * call-seq:
4135
+ * parser.headers? => true or false
4136
+ *
4137
+ * This should be used to detect if a request has headers (and if
4138
+ * the response will have headers as well). HTTP/0.9 requests
4139
+ * should return false, all subsequent HTTP versions will return true
4140
+ */
4141
+ static VALUE HttpParser_has_headers(VALUE self)
4142
+ {
4143
+ struct http_parser *hp = data_get(self);
4144
+
4145
+ return HP_FL_TEST(hp, HASHEADER) ? Qtrue : Qfalse;
4146
+ }
4147
+
4148
+ static VALUE HttpParser_buf(VALUE self)
4149
+ {
4150
+ return data_get(self)->buf;
4151
+ }
4152
+
4153
+ static VALUE HttpParser_env(VALUE self)
4154
+ {
4155
+ return data_get(self)->env;
4156
+ }
4157
+
4158
+ static VALUE HttpParser_hijacked_bang(VALUE self)
4159
+ {
4160
+ struct http_parser *hp = data_get(self);
4161
+
4162
+ HP_FL_SET(hp, HIJACK);
4163
+
4164
+ return self;
4165
+ }
4166
+
4167
+ /**
4168
+ * call-seq:
4169
+ * parser.filter_body(dst, src) => nil/src
4170
+ *
4171
+ * Takes a String of +src+, will modify data if dechunking is done.
4172
+ * Returns +nil+ if there is more data left to process. Returns
4173
+ * +src+ if body processing is complete. When returning +src+,
4174
+ * it may modify +src+ so the start of the string points to where
4175
+ * the body ended so that trailer processing can begin.
4176
+ *
4177
+ * Raises HttpParserError if there are dechunking errors.
4178
+ * Basically this is a glorified memcpy(3) that copies +src+
4179
+ * into +buf+ while filtering it through the dechunker.
4180
+ */
4181
+ static VALUE HttpParser_filter_body(VALUE self, VALUE dst, VALUE src)
4182
+ {
4183
+ struct http_parser *hp = data_get(self);
4184
+ char *srcptr;
4185
+ long srclen;
4186
+
4187
+ srcptr = RSTRING_PTR(src);
4188
+ srclen = RSTRING_LEN(src);
4189
+
4190
+ StringValue(dst);
4191
+
4192
+ if (HP_FL_TEST(hp, CHUNKED)) {
4193
+ if (!chunked_eof(hp)) {
4194
+ rb_str_modify(dst);
4195
+ rb_str_resize(dst, srclen); /* we can never copy more than srclen bytes */
4196
+
4197
+ hp->s.dest_offset = 0;
4198
+ hp->cont = dst;
4199
+ hp->buf = src;
4200
+ http_parser_execute(hp, srcptr, srclen);
4201
+ if (hp->cs == http_parser_error)
4202
+ parser_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
4203
+
4204
+ assert(hp->s.dest_offset <= hp->offset &&
4205
+ "destination buffer overflow");
4206
+ advance_str(src, hp->offset);
4207
+ rb_str_set_len(dst, hp->s.dest_offset);
4208
+
4209
+ if (RSTRING_LEN(dst) == 0 && chunked_eof(hp)) {
4210
+ assert(hp->len.chunk == 0 && "chunk at EOF but more to parse");
4211
+ } else {
4212
+ src = Qnil;
4213
+ }
4214
+ }
4215
+ } else {
4216
+ /* no need to enter the Ragel machine for unchunked transfers */
4217
+ assert(hp->len.content >= 0 && "negative Content-Length");
4218
+ if (hp->len.content > 0) {
4219
+ long nr = MIN(srclen, hp->len.content);
4220
+
4221
+ rb_str_modify(dst);
4222
+ rb_str_resize(dst, nr);
4223
+ /*
4224
+ * using rb_str_replace() to avoid memcpy() doesn't help in
4225
+ * most cases because a GC-aware programmer will pass an explicit
4226
+ * buffer to env["rack.input"].read and reuse the buffer in a loop.
4227
+ * This causes copy-on-write behavior to be triggered anyways
4228
+ * when the +src+ buffer is modified (when reading off the socket).
4229
+ */
4230
+ hp->buf = src;
4231
+ memcpy(RSTRING_PTR(dst), srcptr, nr);
4232
+ hp->len.content -= nr;
4233
+ if (hp->len.content == 0) {
4234
+ HP_FL_SET(hp, REQEOF);
4235
+ hp->cs = http_parser_first_final;
4236
+ }
4237
+ advance_str(src, nr);
4238
+ src = Qnil;
4239
+ }
4240
+ }
4241
+ hp->offset = 0; /* for trailer parsing */
4242
+ return src;
4243
+ }
4244
+
4245
+ static VALUE HttpParser_rssset(VALUE self, VALUE boolean)
4246
+ {
4247
+ struct http_parser *hp = data_get(self);
4248
+
4249
+ if (RTEST(boolean))
4250
+ HP_FL_SET(hp, RESSTART);
4251
+ else
4252
+ HP_FL_UNSET(hp, RESSTART);
4253
+
4254
+ return boolean; /* ignored by Ruby anyways */
4255
+ }
4256
+
4257
+ static VALUE HttpParser_rssget(VALUE self)
4258
+ {
4259
+ struct http_parser *hp = data_get(self);
4260
+
4261
+ return HP_FL_TEST(hp, RESSTART) ? Qtrue : Qfalse;
4262
+ }
4263
+
4264
+ #define SET_GLOBAL(var,str) do { \
4265
+ var = find_common_field(str, sizeof(str) - 1); \
4266
+ assert(!NIL_P(var) && "missed global field"); \
4267
+ } while (0)
4268
+
4269
+ void Init_unicorn_http(void)
4270
+ {
4271
+ VALUE mUnicorn;
4272
+
4273
+ mUnicorn = rb_define_module("Unicorn");
4274
+ cHttpParser = rb_define_class_under(mUnicorn, "HttpParser", rb_cObject);
4275
+ eHttpParserError =
4276
+ rb_define_class_under(mUnicorn, "HttpParserError", rb_eIOError);
4277
+ e413 = rb_define_class_under(mUnicorn, "RequestEntityTooLargeError",
4278
+ eHttpParserError);
4279
+ e414 = rb_define_class_under(mUnicorn, "RequestURITooLongError",
4280
+ eHttpParserError);
4281
+
4282
+ id_uminus = rb_intern("-@");
4283
+ init_globals();
4284
+ rb_define_alloc_func(cHttpParser, HttpParser_alloc);
4285
+ rb_define_method(cHttpParser, "initialize", HttpParser_init, 0);
4286
+ rb_define_method(cHttpParser, "clear", HttpParser_clear, 0);
4287
+ rb_define_method(cHttpParser, "parse", HttpParser_parse, 0);
4288
+ rb_define_method(cHttpParser, "add_parse", HttpParser_add_parse, 1);
4289
+ rb_define_method(cHttpParser, "headers", HttpParser_headers, 2);
4290
+ rb_define_method(cHttpParser, "trailers", HttpParser_headers, 2);
4291
+ rb_define_method(cHttpParser, "filter_body", HttpParser_filter_body, 2);
4292
+ rb_define_method(cHttpParser, "content_length", HttpParser_content_length, 0);
4293
+ rb_define_method(cHttpParser, "body_eof?", HttpParser_body_eof, 0);
4294
+ rb_define_method(cHttpParser, "keepalive?", HttpParser_keepalive, 0);
4295
+ rb_define_method(cHttpParser, "chunkable_response?", chunkable_response_p, 0);
4296
+ rb_define_method(cHttpParser, "headers?", HttpParser_has_headers, 0);
4297
+ rb_define_method(cHttpParser, "next?", HttpParser_next, 0);
4298
+ rb_define_method(cHttpParser, "buf", HttpParser_buf, 0);
4299
+ rb_define_method(cHttpParser, "env", HttpParser_env, 0);
4300
+ rb_define_method(cHttpParser, "hijacked!", HttpParser_hijacked_bang, 0);
4301
+ rb_define_method(cHttpParser, "response_start_sent=", HttpParser_rssset, 1);
4302
+ rb_define_method(cHttpParser, "response_start_sent", HttpParser_rssget, 0);
4303
+
4304
+ /*
4305
+ * The maximum size a single chunk when using chunked transfer encoding.
4306
+ * This is only a theoretical maximum used to detect errors in clients,
4307
+ * it is highly unlikely to encounter clients that send more than
4308
+ * several kilobytes at once.
4309
+ */
4310
+ rb_define_const(cHttpParser, "CHUNK_MAX", OFFT2NUM(UH_OFF_T_MAX));
4311
+
4312
+ /*
4313
+ * The maximum size of the body as specified by Content-Length.
4314
+ * This is only a theoretical maximum, the actual limit is subject
4315
+ * to the limits of the file system used for +Dir.tmpdir+.
4316
+ */
4317
+ rb_define_const(cHttpParser, "LENGTH_MAX", OFFT2NUM(UH_OFF_T_MAX));
4318
+
4319
+ rb_define_singleton_method(cHttpParser, "max_header_len=", set_maxhdrlen, 1);
4320
+
4321
+ init_common_fields();
4322
+ SET_GLOBAL(g_http_host, "HOST");
4323
+ SET_GLOBAL(g_http_trailer, "TRAILER");
4324
+ SET_GLOBAL(g_http_transfer_encoding, "TRANSFER_ENCODING");
4325
+ SET_GLOBAL(g_content_length, "CONTENT_LENGTH");
4326
+ SET_GLOBAL(g_http_connection, "CONNECTION");
4327
+ id_set_backtrace = rb_intern("set_backtrace");
4328
+ init_unicorn_httpdate();
4329
+
4330
+ id_is_chunked_p = rb_intern("is_chunked?");
4331
+
4332
+ init_epollexclusive(mUnicorn);
4333
+ }
4334
+ #undef SET_GLOBAL