unicorn-maintained 6.2.0

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