Upgrade http parser, change node as needed.
authorRyan Dahl <ry@tinyclouds.org>
Thu, 15 Oct 2009 17:18:18 +0000 (19:18 +0200)
committerRyan Dahl <ry@tinyclouds.org>
Thu, 15 Oct 2009 17:18:18 +0000 (19:18 +0200)
The latest version of http-parser is a bit more stringent EOF semantics.

13 files changed:
deps/http_parser/LICENSE
deps/http_parser/Makefile
deps/http_parser/README.md
deps/http_parser/http_parser.c
deps/http_parser/http_parser.h
deps/http_parser/http_parser.rl
deps/http_parser/test.c
lib/http.js
src/http.cc
src/http.h
test/mjsunit/test-http-malformed-request.js
test/mjsunit/test-http-proxy.js
test/mjsunit/test-http-server.js

index 7fb7fcd..561e5c5 100644 (file)
@@ -1,4 +1,5 @@
 Copyright 2009, Ryan Lienhart Dahl. All rights reserved.
+
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to
 deal in the Software without restriction, including without limitation the
@@ -15,16 +16,13 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE. 
-
-
-
+IN THE SOFTWARE.
 
 http_parser is based on Zed Shaw's Mongrel. Mongrel's license is as follows.
 
--- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT --
+---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
 Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
-<zedshaw at zedshaw dot com> and contributors. You can redistribute it 
+<zedshaw at zedshaw dot com> and contributors. You can redistribute it
 and/or modify it under either the terms of the GPL2 or the conditions below:
 
 1. You may make and give away verbatim copies of the source form of the
@@ -66,9 +64,9 @@ and/or modify it under either the terms of the GPL2 or the conditions below:
    software (possibly commercial).  But some files in the distribution
    are not written by the author, so that they are not under this terms.
 
-5. The scripts and library files supplied as input to or produced as 
+5. The scripts and library files supplied as input to or produced as
    output from the software do not automatically fall under the
-   copyright of the software, but belong to whomever generated them, 
+   copyright of the software, but belong to whomever generated them,
    and may be sold commercially, and may be aggregated with this
    software.
 
@@ -76,4 +74,4 @@ and/or modify it under either the terms of the GPL2 or the conditions below:
    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    PURPOSE.
--- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT --
+---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
index afe7229..899de24 100644 (file)
@@ -1,8 +1,8 @@
 #OPT=-O0 -g -Wall -Wextra -Werror
 OPT=-O2
 
-test: http_parser.o test.c 
-       gcc $(OPT) http_parser.o test.c -o $@ 
+test: http_parser.o test.c
+       gcc $(OPT) http_parser.o test.c -o $@
 
 http_parser.o: http_parser.c http_parser.h Makefile
        gcc $(OPT) -c http_parser.c
index d60473e..1e77aa5 100644 (file)
@@ -5,11 +5,11 @@ This is a parser for HTTP messages written in C. It parses both requests
 and responses. The parser is designed to be used in performance HTTP
 applications. It does not make any allocations, it does not buffer data, and
 it can be interrupted at anytime. It only requires about 128 bytes of data
-per message stream (in a web server that is per connection). 
+per message stream (in a web server that is per connection).
 
 Features:
 
-  * No dependencies 
+  * No dependencies
   * Parses both requests and responses.
   * Handles keep-alive streams.
   * Decodes chunked encoding.
@@ -43,21 +43,35 @@ When data is received on the socket execute the parser and check for errors.
     char buf[len];
     ssize_t recved;
 
-    recved = read(fd, buf, len);
-    if (recved != 0) // handle error
+    recved = recv(fd, buf, len, 0);
 
+    if (recved < 0) {
+      /* Handle error. */
+    }
+
+    /* Start up / continue the parser.
+     * Note we pass the recved==0 to http_parser_execute to signal
+     * that EOF has been recieved.
+     */
     http_parser_execute(parser, buf, recved);
 
     if (http_parser_has_error(parser)) {
-      // handle error. usually just close the connection
+      /* Handle error. Usually just close the connection. */
     }
 
+HTTP needs to know where the end of the stream is. For example, sometimes
+servers send responses without Content-Length and expect the client to
+consume input (for the body) until EOF. To tell http_parser about EOF, give
+`0` as the third parameter to `http_parser_execute()`. Callbacks and errors
+can still be encountered during an EOF, so one must still be prepared
+to receive them.
+
 Scalar valued message information such as `status_code`, `method`, and the
 HTTP version are stored in the parser structure. This data is only
 temporarlly stored in `http_parser` and gets reset on each new message. If
 this information is needed later, copy it out of the structure during the
 `headers_complete` callback.
-  
+
 The parser decodes the transfer-encoding for both requests and responses
 transparently. That is, a chunked encoding is decoded before being sent to
 the on_body callback.
@@ -129,3 +143,10 @@ Releases
   * [0.1](http://s3.amazonaws.com/four.livejournal/20090427/http_parser-0.1.tar.gz)
 
 The source repo is at [github](http://github.com/ry/http-parser).
+
+Bindings
+--------
+
+  * [Ruby](http://github.com/yakischloba/http-parser-ffi)
+
+  * [Lua](http://github.com/phoenixsol/lua-http-parser)
index b0e4b56..ecb699c 100644 (file)
@@ -3,7 +3,7 @@
  * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
  *
  * All rights reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "http_parser.h"
 #include <limits.h>
 #include <assert.h>
 
+/* parser->flags */
+#define EATING      0x01
+#define ERROR       0x02
+#define CHUNKED     0x04
+#define EAT_FOREVER 0x10
+
 static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
@@ -36,12 +42,14 @@ static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      };
-#define TRUE 1
-#define FALSE 0
-#define MIN(a,b) (a < b ? a : b)
-#define NULL (void*)(0)
 
-#define MAX_FIELD_SIZE 80*1024
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#undef NULL
+#define NULL ((void*)(0))
+
+#define MAX_FIELD_SIZE (80*1024)
 
 #define REMAINING (unsigned long)(pe - p)
 #define CALLBACK(FOR)                                                \
@@ -49,34 +57,36 @@ do {                                                                 \
   if (parser->FOR##_mark) {                                          \
     parser->FOR##_size += p - parser->FOR##_mark;                    \
     if (parser->FOR##_size > MAX_FIELD_SIZE) {                       \
-      parser->error = TRUE;                                          \
-      return 0;                                                      \
+      parser->flags |= ERROR;                                        \
+      return;                                                        \
     }                                                                \
     if (parser->on_##FOR) {                                          \
       callback_return_value = parser->on_##FOR(parser,               \
         parser->FOR##_mark,                                          \
         p - parser->FOR##_mark);                                     \
     }                                                                \
+    if (callback_return_value != 0) {                                \
+      parser->flags |= ERROR;                                        \
+      return;                                                        \
+    }                                                                \
   }                                                                  \
 } while(0)
 
 #define RESET_PARSER(parser)                                         \
-    parser->chunk_size = 0;                                          \
-    parser->eating = 0;                                              \
-    parser->header_field_mark = NULL;                                \
-    parser->header_value_mark = NULL;                                \
-    parser->query_string_mark = NULL;                                \
-    parser->path_mark = NULL;                                        \
-    parser->uri_mark = NULL;                                         \
-    parser->fragment_mark = NULL;                                    \
-    parser->status_code = 0;                                         \
-    parser->method = 0;                                              \
-    parser->transfer_encoding = HTTP_IDENTITY;                       \
-    parser->version_major = 0;                                       \
-    parser->version_minor = 0;                                       \
-    parser->keep_alive = -1;                                         \
-    parser->content_length = 0;                                      \
-    parser->body_read = 0; 
+  parser->chunk_size = 0;                                            \
+  parser->flags = 0;                                                 \
+  parser->header_field_mark = NULL;                                  \
+  parser->header_value_mark = NULL;                                  \
+  parser->query_string_mark = NULL;                                  \
+  parser->path_mark = NULL;                                          \
+  parser->uri_mark = NULL;                                           \
+  parser->fragment_mark = NULL;                                      \
+  parser->status_code = 0;                                           \
+  parser->method = 0;                                                \
+  parser->version = HTTP_VERSION_OTHER;                              \
+  parser->keep_alive = -1;                                           \
+  parser->content_length = -1;                                       \
+  parser->body_read = 0
 
 #define END_REQUEST                                                  \
 do {                                                                 \
@@ -98,46 +108,45 @@ do {                                                                 \
     parser->body_read += tmp;                                        \
     parser->chunk_size -= tmp;                                       \
     if (0 == parser->chunk_size) {                                   \
-      parser->eating = FALSE;                                        \
-      if (parser->transfer_encoding == HTTP_IDENTITY) {              \
+      parser->flags &= ~EATING;                                      \
+      if (!(parser->flags & CHUNKED)) {                              \
         END_REQUEST;                                                 \
       }                                                              \
     } else {                                                         \
-      parser->eating = TRUE;                                         \
+      parser->flags |= EATING;                                       \
     }                                                                \
   }                                                                  \
 } while (0)
 
-#line 413 "http_parser.rl"
+#line 411 "http_parser.rl"
 
 
 
-#line 116 "http_parser.c"
+#line 126 "http_parser.c"
 static const int http_parser_start = 1;
-static const int http_parser_first_final = 266;
+static const int http_parser_first_final = 280;
 static const int http_parser_error = 0;
 
 static const int http_parser_en_ChunkedBody = 2;
-static const int http_parser_en_ChunkedBody_chunk_chunk_end = 12;
-static const int http_parser_en_Requests = 268;
-static const int http_parser_en_Responses = 269;
+static const int http_parser_en_ChunkedBody_chunk_chunk_end = 13;
+static const int http_parser_en_Requests = 282;
+static const int http_parser_en_Responses = 283;
 static const int http_parser_en_main = 1;
 
-#line 416 "http_parser.rl"
+#line 414 "http_parser.rl"
 
 void
-http_parser_init (http_parser *parser, enum http_parser_type type) 
+http_parser_init (http_parser *parser, enum http_parser_type type)
 {
   int cs = 0;
   
-#line 134 "http_parser.c"
+#line 144 "http_parser.c"
        {
        cs = http_parser_start;
        }
-#line 422 "http_parser.rl"
+#line 420 "http_parser.rl"
   parser->cs = cs;
   parser->type = type;
-  parser->error = 0;
 
   parser->on_message_begin = NULL;
   parser->on_path = NULL;
@@ -154,23 +163,39 @@ http_parser_init (http_parser *parser, enum http_parser_type type)
 }
 
 /** exec **/
-size_t
+void
 http_parser_execute (http_parser *parser, const char *buffer, size_t len)
 {
   size_t tmp; // REMOVE ME this is extremely hacky
   int callback_return_value = 0;
-  const char *p, *pe;
+  const char *p, *pe, *eof;
   int cs = parser->cs;
 
   p = buffer;
   pe = buffer+len;
+  eof = len ? NULL : pe;
 
-  if (0 < parser->chunk_size && parser->eating) {
+  if (parser->flags & EAT_FOREVER) {
+    if (len == 0) {
+      if (parser->on_message_complete) {
+        callback_return_value = parser->on_message_complete(parser);
+        if (callback_return_value != 0) parser->flags |= ERROR;
+      }
+    } else {
+      if (parser->on_body) {
+        callback_return_value = parser->on_body(parser, p, len);
+        if (callback_return_value != 0) parser->flags |= ERROR;
+      }
+    }
+    return;
+  }
+
+  if (0 < parser->chunk_size && (parser->flags & EATING)) {
     /* eat body */
     SKIP_BODY(MIN(len, parser->chunk_size));
     if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
   }
 
@@ -182,7 +207,7 @@ http_parser_execute (http_parser *parser, const char *buffer, size_t len)
   if (parser->uri_mark)            parser->uri_mark            = buffer;
 
   
-#line 186 "http_parser.c"
+#line 211 "http_parser.c"
        {
        if ( p == pe )
                goto _test_eof;
@@ -191,14 +216,14 @@ http_parser_execute (http_parser *parser, const char *buffer, size_t len)
 _again:
        switch ( cs ) {
                case 1: goto st1;
-               case 266: goto st266;
+               case 280: goto st280;
                case 0: goto st0;
                case 2: goto st2;
                case 3: goto st3;
                case 4: goto st4;
                case 5: goto st5;
                case 6: goto st6;
-               case 267: goto st267;
+               case 281: goto st281;
                case 7: goto st7;
                case 8: goto st8;
                case 9: goto st9;
@@ -212,9 +237,9 @@ _again:
                case 17: goto st17;
                case 18: goto st18;
                case 19: goto st19;
-               case 268: goto st268;
                case 20: goto st20;
                case 21: goto st21;
+               case 282: goto st282;
                case 22: goto st22;
                case 23: goto st23;
                case 24: goto st24;
@@ -375,7 +400,6 @@ _again:
                case 179: goto st179;
                case 180: goto st180;
                case 181: goto st181;
-               case 269: goto st269;
                case 182: goto st182;
                case 183: goto st183;
                case 184: goto st184;
@@ -384,6 +408,7 @@ _again:
                case 187: goto st187;
                case 188: goto st188;
                case 189: goto st189;
+               case 283: goto st283;
                case 190: goto st190;
                case 191: goto st191;
                case 192: goto st192;
@@ -460,6 +485,20 @@ _again:
                case 263: goto st263;
                case 264: goto st264;
                case 265: goto st265;
+               case 266: goto st266;
+               case 267: goto st267;
+               case 268: goto st268;
+               case 269: goto st269;
+               case 270: goto st270;
+               case 271: goto st271;
+               case 272: goto st272;
+               case 273: goto st273;
+               case 274: goto st274;
+               case 275: goto st275;
+               case 276: goto st276;
+               case 277: goto st277;
+               case 278: goto st278;
+               case 279: goto st279;
        default: break;
        }
 
@@ -474,21 +513,21 @@ st1:
 case 1:
        goto tr0;
 tr0:
-#line 404 "http_parser.rl"
+#line 402 "http_parser.rl"
        {
     p--;
     if (parser->type == HTTP_REQUEST) {
-      {goto st268;}
+      {goto st282;}
     } else {
-      {goto st269;}
+      {goto st283;}
     }
   }
-       goto st266;
-st266:
+       goto st280;
+st280:
        if ( ++p == pe )
-               goto _test_eof266;
-case 266:
-#line 492 "http_parser.c"
+               goto _test_eof280;
+case 280:
+#line 531 "http_parser.c"
        goto st0;
 st0:
 cs = 0;
@@ -509,7 +548,7 @@ case 2:
                goto tr3;
        goto st0;
 tr1:
-#line 253 "http_parser.rl"
+#line 233 "http_parser.rl"
        {
     parser->chunk_size *= 16;
     parser->chunk_size += unhex[(int)*p];
@@ -519,11 +558,12 @@ st3:
        if ( ++p == pe )
                goto _test_eof3;
 case 3:
-#line 523 "http_parser.c"
+#line 562 "http_parser.c"
        switch( (*p) ) {
                case 13: goto st4;
+               case 32: goto st9;
                case 48: goto tr1;
-               case 59: goto st17;
+               case 59: goto st19;
        }
        if ( (*p) < 65 ) {
                if ( 49 <= (*p) && (*p) <= 57 )
@@ -574,25 +614,25 @@ st6:
                goto _test_eof6;
 case 6:
        if ( (*p) == 10 )
-               goto tr9;
+               goto tr10;
        goto st0;
-tr9:
-       cs = 267;
-#line 273 "http_parser.rl"
+tr10:
+       cs = 281;
+#line 253 "http_parser.rl"
        {
     END_REQUEST;
     if (parser->type == HTTP_REQUEST) {
-      cs = 268;
+      cs = 282;
     } else {
-      cs = 269;
+      cs = 283;
     }
   }
        goto _again;
-st267:
+st281:
        if ( ++p == pe )
-               goto _test_eof267;
-case 267:
-#line 596 "http_parser.c"
+               goto _test_eof281;
+case 281:
+#line 636 "http_parser.c"
        goto st0;
 st7:
        if ( ++p == pe )
@@ -629,21 +669,31 @@ case 8:
        if ( (*p) == 13 )
                goto st4;
        goto st8;
+st9:
+       if ( ++p == pe )
+               goto _test_eof9;
+case 9:
+       switch( (*p) ) {
+               case 13: goto st4;
+               case 32: goto st9;
+       }
+       goto st0;
 tr3:
-#line 253 "http_parser.rl"
+#line 233 "http_parser.rl"
        {
     parser->chunk_size *= 16;
     parser->chunk_size += unhex[(int)*p];
   }
-       goto st9;
-st9:
+       goto st10;
+st10:
        if ( ++p == pe )
-               goto _test_eof9;
-case 9:
-#line 644 "http_parser.c"
+               goto _test_eof10;
+case 10:
+#line 693 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto st10;
-               case 59: goto st14;
+               case 13: goto st11;
+               case 32: goto st15;
+               case 59: goto st16;
        }
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
@@ -654,256 +704,279 @@ case 9:
        } else
                goto tr3;
        goto st0;
-st10:
-       if ( ++p == pe )
-               goto _test_eof10;
-case 10:
-       if ( (*p) == 10 )
-               goto st11;
-       goto st0;
 st11:
        if ( ++p == pe )
                goto _test_eof11;
 case 11:
-       goto tr14;
-tr14:
-#line 258 "http_parser.rl"
+       if ( (*p) == 10 )
+               goto st12;
+       goto st0;
+st12:
+       if ( ++p == pe )
+               goto _test_eof12;
+case 12:
+       goto tr16;
+tr16:
+#line 238 "http_parser.rl"
        {
     SKIP_BODY(MIN(parser->chunk_size, REMAINING));
     if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
 
-    p--; 
+    p--;
     if (parser->chunk_size > REMAINING) {
-      {p++; cs = 12; goto _out;}
+      {p++; cs = 13; goto _out;}
     } else {
-      {goto st12;} 
+      {goto st13;}
     }
   }
-       goto st12;
-st12:
-       if ( ++p == pe )
-               goto _test_eof12;
-case 12:
-#line 691 "http_parser.c"
-       if ( (*p) == 13 )
-               goto st13;
-       goto st0;
+       goto st13;
 st13:
        if ( ++p == pe )
                goto _test_eof13;
 case 13:
-       if ( (*p) == 10 )
-               goto st2;
+#line 741 "http_parser.c"
+       if ( (*p) == 13 )
+               goto st14;
        goto st0;
 st14:
        if ( ++p == pe )
                goto _test_eof14;
 case 14:
+       if ( (*p) == 10 )
+               goto st2;
+       goto st0;
+st15:
+       if ( ++p == pe )
+               goto _test_eof15;
+case 15:
+       switch( (*p) ) {
+               case 13: goto st11;
+               case 32: goto st15;
+       }
+       goto st0;
+st16:
+       if ( ++p == pe )
+               goto _test_eof16;
+case 16:
        switch( (*p) ) {
-               case 13: goto st10;
-               case 32: goto st14;
-               case 33: goto st15;
-               case 59: goto st14;
-               case 61: goto st16;
-               case 124: goto st15;
-               case 126: goto st15;
+               case 13: goto st11;
+               case 32: goto st16;
+               case 33: goto st17;
+               case 59: goto st16;
+               case 61: goto st18;
+               case 124: goto st17;
+               case 126: goto st17;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st15;
+                               goto st17;
                } else if ( (*p) >= 35 )
-                       goto st15;
+                       goto st17;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st15;
+                               goto st17;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st15;
+                               goto st17;
                } else
-                       goto st15;
+                       goto st17;
        } else
-               goto st15;
+               goto st17;
        goto st0;
-st15:
+st17:
        if ( ++p == pe )
-               goto _test_eof15;
-case 15:
+               goto _test_eof17;
+case 17:
        switch( (*p) ) {
-               case 13: goto st10;
-               case 33: goto st15;
-               case 59: goto st14;
-               case 61: goto st16;
-               case 124: goto st15;
-               case 126: goto st15;
+               case 13: goto st11;
+               case 33: goto st17;
+               case 59: goto st16;
+               case 61: goto st18;
+               case 124: goto st17;
+               case 126: goto st17;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st15;
+                               goto st17;
                } else if ( (*p) >= 35 )
-                       goto st15;
+                       goto st17;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st15;
+                               goto st17;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st15;
+                               goto st17;
                } else
-                       goto st15;
+                       goto st17;
        } else
-               goto st15;
+               goto st17;
        goto st0;
-st16:
+st18:
        if ( ++p == pe )
-               goto _test_eof16;
-case 16:
+               goto _test_eof18;
+case 18:
        switch( (*p) ) {
-               case 13: goto st10;
-               case 33: goto st16;
-               case 59: goto st14;
-               case 124: goto st16;
-               case 126: goto st16;
+               case 13: goto st11;
+               case 33: goto st18;
+               case 59: goto st16;
+               case 124: goto st18;
+               case 126: goto st18;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st16;
+                               goto st18;
                } else if ( (*p) >= 35 )
-                       goto st16;
+                       goto st18;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st16;
+                               goto st18;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st16;
+                               goto st18;
                } else
-                       goto st16;
+                       goto st18;
        } else
-               goto st16;
+               goto st18;
        goto st0;
-st17:
+st19:
        if ( ++p == pe )
-               goto _test_eof17;
-case 17:
+               goto _test_eof19;
+case 19:
        switch( (*p) ) {
                case 13: goto st4;
-               case 32: goto st17;
-               case 33: goto st18;
-               case 59: goto st17;
-               case 61: goto st19;
-               case 124: goto st18;
-               case 126: goto st18;
+               case 32: goto st19;
+               case 33: goto st20;
+               case 59: goto st19;
+               case 61: goto st21;
+               case 124: goto st20;
+               case 126: goto st20;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st18;
+                               goto st20;
                } else if ( (*p) >= 35 )
-                       goto st18;
+                       goto st20;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st18;
+                               goto st20;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st18;
+                               goto st20;
                } else
-                       goto st18;
+                       goto st20;
        } else
-               goto st18;
+               goto st20;
        goto st0;
-st18:
+st20:
        if ( ++p == pe )
-               goto _test_eof18;
-case 18:
+               goto _test_eof20;
+case 20:
        switch( (*p) ) {
                case 13: goto st4;
-               case 33: goto st18;
-               case 59: goto st17;
-               case 61: goto st19;
-               case 124: goto st18;
-               case 126: goto st18;
+               case 33: goto st20;
+               case 59: goto st19;
+               case 61: goto st21;
+               case 124: goto st20;
+               case 126: goto st20;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st18;
+                               goto st20;
                } else if ( (*p) >= 35 )
-                       goto st18;
+                       goto st20;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st18;
+                               goto st20;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st18;
+                               goto st20;
                } else
-                       goto st18;
+                       goto st20;
        } else
-               goto st18;
+               goto st20;
        goto st0;
-st19:
+st21:
        if ( ++p == pe )
-               goto _test_eof19;
-case 19:
+               goto _test_eof21;
+case 21:
        switch( (*p) ) {
                case 13: goto st4;
-               case 33: goto st19;
-               case 59: goto st17;
-               case 124: goto st19;
-               case 126: goto st19;
+               case 33: goto st21;
+               case 59: goto st19;
+               case 124: goto st21;
+               case 126: goto st21;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st19;
+                               goto st21;
                } else if ( (*p) >= 35 )
-                       goto st19;
+                       goto st21;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st19;
+                               goto st21;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st19;
+                               goto st21;
                } else
-                       goto st19;
+                       goto st21;
        } else
-               goto st19;
+               goto st21;
        goto st0;
-tr45:
-       cs = 268;
-#line 203 "http_parser.rl"
+tr50:
+       cs = 282;
+#line 189 "http_parser.rl"
        {
     if(parser->on_headers_complete) {
       callback_return_value = parser->on_headers_complete(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-#line 282 "http_parser.rl"
+#line 262 "http_parser.rl"
        {
-    if (parser->transfer_encoding == HTTP_CHUNKED) {
+    if (parser->flags & CHUNKED) {
       cs = 2;
     } else {
-      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
-      parser->chunk_size = parser->content_length;
-      p += 1;  
+      /* this is pretty stupid. i'd prefer to combine this with
+       * skip_chunk_data */
+      if (parser->content_length < 0) {
+        /* If we didn't get a content length; if not keep-alive
+         * just read body until EOF */
+        if (!http_parser_should_keep_alive(parser)) {
+          parser->flags |= EAT_FOREVER;
+          parser->chunk_size = REMAINING;
+        } else {
+          /* Otherwise, if keep-alive, then assume the message
+           * has no body. */
+          parser->chunk_size = parser->content_length = 0;
+        }
+      } else {
+        parser->chunk_size = parser->content_length;
+      }
+      p += 1;
 
-      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      SKIP_BODY(MIN(REMAINING, parser->chunk_size));
 
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
 
       p--;
@@ -913,2571 +986,2438 @@ tr45:
     }
   }
        goto _again;
-st268:
-       if ( ++p == pe )
-               goto _test_eof268;
-case 268:
-#line 921 "http_parser.c"
-       switch( (*p) ) {
-               case 67: goto tr310;
-               case 68: goto tr311;
-               case 71: goto tr312;
-               case 72: goto tr313;
-               case 76: goto tr314;
-               case 77: goto tr315;
-               case 79: goto tr316;
-               case 80: goto tr317;
-               case 84: goto tr318;
-               case 85: goto tr319;
-       }
-       goto st0;
-tr310:
-#line 213 "http_parser.rl"
+st282:
+       if ( ++p == pe )
+               goto _test_eof282;
+case 282:
+#line 994 "http_parser.c"
+       switch( (*p) ) {
+               case 67: goto tr330;
+               case 68: goto tr331;
+               case 71: goto tr332;
+               case 72: goto tr333;
+               case 76: goto tr334;
+               case 77: goto tr335;
+               case 79: goto tr336;
+               case 80: goto tr337;
+               case 84: goto tr338;
+               case 85: goto tr339;
+       }
+       goto st0;
+tr330:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st20;
-st20:
-       if ( ++p == pe )
-               goto _test_eof20;
-case 20:
-#line 951 "http_parser.c"
-       if ( (*p) == 79 )
-               goto st21;
-       goto st0;
-st21:
-       if ( ++p == pe )
-               goto _test_eof21;
-case 21:
-       if ( (*p) == 80 )
-               goto st22;
-       goto st0;
+       goto st22;
 st22:
        if ( ++p == pe )
                goto _test_eof22;
 case 22:
-       if ( (*p) == 89 )
+#line 1024 "http_parser.c"
+       if ( (*p) == 79 )
                goto st23;
        goto st0;
 st23:
        if ( ++p == pe )
                goto _test_eof23;
 case 23:
+       if ( (*p) == 80 )
+               goto st24;
+       goto st0;
+st24:
+       if ( ++p == pe )
+               goto _test_eof24;
+case 24:
+       if ( (*p) == 89 )
+               goto st25;
+       goto st0;
+st25:
+       if ( ++p == pe )
+               goto _test_eof25;
+case 25:
        if ( (*p) == 32 )
-               goto tr24;
+               goto tr26;
        goto st0;
-tr24:
-#line 329 "http_parser.rl"
+tr26:
+#line 323 "http_parser.rl"
        { parser->method = HTTP_COPY;      }
-       goto st24;
-tr154:
-#line 330 "http_parser.rl"
+       goto st26;
+tr165:
+#line 324 "http_parser.rl"
        { parser->method = HTTP_DELETE;    }
-       goto st24;
-tr157:
-#line 331 "http_parser.rl"
+       goto st26;
+tr168:
+#line 325 "http_parser.rl"
        { parser->method = HTTP_GET;       }
-       goto st24;
-tr161:
-#line 332 "http_parser.rl"
+       goto st26;
+tr172:
+#line 326 "http_parser.rl"
        { parser->method = HTTP_HEAD;      }
-       goto st24;
-tr165:
-#line 333 "http_parser.rl"
+       goto st26;
+tr176:
+#line 327 "http_parser.rl"
        { parser->method = HTTP_LOCK;      }
-       goto st24;
-tr171:
-#line 334 "http_parser.rl"
+       goto st26;
+tr182:
+#line 328 "http_parser.rl"
        { parser->method = HTTP_MKCOL;     }
-       goto st24;
-tr174:
-#line 335 "http_parser.rl"
+       goto st26;
+tr185:
+#line 329 "http_parser.rl"
        { parser->method = HTTP_MOVE;      }
-       goto st24;
-tr181:
-#line 336 "http_parser.rl"
+       goto st26;
+tr192:
+#line 330 "http_parser.rl"
        { parser->method = HTTP_OPTIONS;   }
-       goto st24;
-tr187:
-#line 337 "http_parser.rl"
+       goto st26;
+tr198:
+#line 331 "http_parser.rl"
        { parser->method = HTTP_POST;      }
-       goto st24;
-tr195:
-#line 338 "http_parser.rl"
+       goto st26;
+tr206:
+#line 332 "http_parser.rl"
        { parser->method = HTTP_PROPFIND;  }
-       goto st24;
-tr200:
-#line 339 "http_parser.rl"
+       goto st26;
+tr211:
+#line 333 "http_parser.rl"
        { parser->method = HTTP_PROPPATCH; }
-       goto st24;
-tr202:
-#line 340 "http_parser.rl"
+       goto st26;
+tr213:
+#line 334 "http_parser.rl"
        { parser->method = HTTP_PUT;       }
-       goto st24;
-tr207:
-#line 341 "http_parser.rl"
+       goto st26;
+tr218:
+#line 335 "http_parser.rl"
        { parser->method = HTTP_TRACE;     }
-       goto st24;
-tr213:
-#line 342 "http_parser.rl"
+       goto st26;
+tr224:
+#line 336 "http_parser.rl"
        { parser->method = HTTP_UNLOCK;    }
-       goto st24;
-st24:
+       goto st26;
+st26:
        if ( ++p == pe )
-               goto _test_eof24;
-case 24:
-#line 1036 "http_parser.c"
+               goto _test_eof26;
+case 26:
+#line 1109 "http_parser.c"
        switch( (*p) ) {
-               case 42: goto tr25;
-               case 43: goto tr26;
-               case 47: goto tr27;
-               case 58: goto tr28;
+               case 42: goto tr27;
+               case 43: goto tr28;
+               case 47: goto tr29;
+               case 58: goto tr30;
        }
        if ( (*p) < 65 ) {
                if ( 45 <= (*p) && (*p) <= 57 )
-                       goto tr26;
+                       goto tr28;
        } else if ( (*p) > 90 ) {
                if ( 97 <= (*p) && (*p) <= 122 )
-                       goto tr26;
+                       goto tr28;
        } else
-               goto tr26;
+               goto tr28;
        goto st0;
-tr25:
-#line 138 "http_parser.rl"
+tr27:
+#line 148 "http_parser.rl"
        {
     parser->uri_mark = p;
     parser->uri_size = 0;
   }
-       goto st25;
-st25:
+       goto st27;
+st27:
        if ( ++p == pe )
-               goto _test_eof25;
-case 25:
-#line 1063 "http_parser.c"
+               goto _test_eof27;
+case 27:
+#line 1136 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr29;
-               case 35: goto tr30;
+               case 32: goto tr31;
+               case 35: goto tr32;
        }
        goto st0;
-tr29:
-#line 163 "http_parser.rl"
-       { 
+tr31:
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st26;
-tr124:
-#line 123 "http_parser.rl"
+       goto st28;
+tr135:
+#line 133 "http_parser.rl"
        {
     parser->fragment_mark = p;
     parser->fragment_size = 0;
   }
-#line 173 "http_parser.rl"
-       { 
+#line 171 "http_parser.rl"
+       {
     CALLBACK(fragment);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->fragment_mark = NULL;
     parser->fragment_size = 0;
   }
-       goto st26;
-tr127:
-#line 173 "http_parser.rl"
-       { 
+       goto st28;
+tr138:
+#line 171 "http_parser.rl"
+       {
     CALLBACK(fragment);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->fragment_mark = NULL;
     parser->fragment_size = 0;
   }
-       goto st26;
-tr135:
-#line 193 "http_parser.rl"
+       goto st28;
+tr146:
+#line 183 "http_parser.rl"
        {
     CALLBACK(path);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->path_mark = NULL;
     parser->path_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st26;
-tr141:
-#line 128 "http_parser.rl"
+       goto st28;
+tr152:
+#line 138 "http_parser.rl"
        {
     parser->query_string_mark = p;
     parser->query_string_size = 0;
   }
-#line 183 "http_parser.rl"
-       { 
+#line 177 "http_parser.rl"
+       {
     CALLBACK(query_string);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->query_string_mark = NULL;
     parser->query_string_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st26;
-tr145:
-#line 183 "http_parser.rl"
-       { 
+       goto st28;
+tr156:
+#line 177 "http_parser.rl"
+       {
     CALLBACK(query_string);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->query_string_mark = NULL;
     parser->query_string_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st26;
-st26:
-       if ( ++p == pe )
-               goto _test_eof26;
-case 26:
-#line 1185 "http_parser.c"
-       if ( (*p) == 72 )
-               goto st27;
-       goto st0;
-st27:
-       if ( ++p == pe )
-               goto _test_eof27;
-case 27:
-       if ( (*p) == 84 )
-               goto st28;
-       goto st0;
+       goto st28;
 st28:
        if ( ++p == pe )
                goto _test_eof28;
 case 28:
-       if ( (*p) == 84 )
+#line 1222 "http_parser.c"
+       if ( (*p) == 72 )
                goto st29;
        goto st0;
 st29:
        if ( ++p == pe )
                goto _test_eof29;
 case 29:
-       if ( (*p) == 80 )
+       if ( (*p) == 84 )
                goto st30;
        goto st0;
 st30:
        if ( ++p == pe )
                goto _test_eof30;
 case 30:
-       if ( (*p) == 47 )
+       if ( (*p) == 84 )
                goto st31;
        goto st0;
 st31:
        if ( ++p == pe )
                goto _test_eof31;
 case 31:
-       if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr36;
+       if ( (*p) == 80 )
+               goto st32;
        goto st0;
-tr36:
-#line 243 "http_parser.rl"
-       {
-    parser->version_major *= 10;
-    parser->version_major += *p - '0';
-  }
-       goto st32;
 st32:
        if ( ++p == pe )
                goto _test_eof32;
 case 32:
-#line 1235 "http_parser.c"
-       if ( (*p) == 46 )
+       if ( (*p) == 47 )
                goto st33;
        goto st0;
 st33:
        if ( ++p == pe )
                goto _test_eof33;
 case 33:
-       if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr38;
+       switch( (*p) ) {
+               case 48: goto st34;
+               case 49: goto st108;
+       }
+       if ( 50 <= (*p) && (*p) <= 57 )
+               goto st112;
        goto st0;
-tr38:
-#line 248 "http_parser.rl"
-       {
-    parser->version_minor *= 10;
-    parser->version_minor += *p - '0';
-  }
-       goto st34;
 st34:
        if ( ++p == pe )
                goto _test_eof34;
 case 34:
-#line 1257 "http_parser.c"
-       if ( (*p) == 13 )
+       if ( (*p) == 46 )
                goto st35;
        goto st0;
-tr49:
-#line 118 "http_parser.rl"
+st35:
+       if ( ++p == pe )
+               goto _test_eof35;
+case 35:
+       if ( (*p) == 57 )
+               goto st107;
+       if ( 48 <= (*p) && (*p) <= 56 )
+               goto st36;
+       goto st0;
+st36:
+       if ( ++p == pe )
+               goto _test_eof36;
+case 36:
+       if ( (*p) == 13 )
+               goto st37;
+       goto st0;
+tr54:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-#line 153 "http_parser.rl"
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st35;
-tr52:
-#line 153 "http_parser.rl"
+       goto st37;
+tr57:
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st35;
-tr71:
-#line 241 "http_parser.rl"
-       { parser->keep_alive = FALSE; }
-#line 153 "http_parser.rl"
+       goto st37;
+tr76:
+#line 227 "http_parser.rl"
+       { parser->keep_alive = 0; }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st35;
-tr81:
-#line 240 "http_parser.rl"
-       { parser->keep_alive = TRUE; }
-#line 153 "http_parser.rl"
+       goto st37;
+tr86:
+#line 226 "http_parser.rl"
+       { parser->keep_alive = 1; }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st35;
-tr122:
-#line 237 "http_parser.rl"
-       { parser->transfer_encoding = HTTP_IDENTITY; }
-#line 153 "http_parser.rl"
+       goto st37;
+tr126:
+#line 224 "http_parser.rl"
+       { parser->flags |= CHUNKED;  }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st35;
-st35:
+       goto st37;
+tr127:
+#line 231 "http_parser.rl"
+       { parser->version = HTTP_VERSION_09; }
+       goto st37;
+tr131:
+#line 230 "http_parser.rl"
+       { parser->version = HTTP_VERSION_10; }
+       goto st37;
+tr132:
+#line 229 "http_parser.rl"
+       { parser->version = HTTP_VERSION_11; }
+       goto st37;
+st37:
        if ( ++p == pe )
-               goto _test_eof35;
-case 35:
-#line 1336 "http_parser.c"
+               goto _test_eof37;
+case 37:
+#line 1355 "http_parser.c"
        if ( (*p) == 10 )
-               goto st36;
+               goto st38;
        goto st0;
-st36:
+st38:
        if ( ++p == pe )
-               goto _test_eof36;
-case 36:
+               goto _test_eof38;
+case 38:
        switch( (*p) ) {
-               case 13: goto st37;
-               case 33: goto tr42;
-               case 67: goto tr43;
-               case 84: goto tr44;
-               case 99: goto tr43;
-               case 116: goto tr44;
-               case 124: goto tr42;
-               case 126: goto tr42;
+               case 13: goto st39;
+               case 33: goto tr47;
+               case 67: goto tr48;
+               case 84: goto tr49;
+               case 99: goto tr48;
+               case 116: goto tr49;
+               case 124: goto tr47;
+               case 126: goto tr47;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto tr42;
+                               goto tr47;
                } else if ( (*p) >= 35 )
-                       goto tr42;
+                       goto tr47;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto tr42;
+                               goto tr47;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto tr42;
+                               goto tr47;
                } else
-                       goto tr42;
+                       goto tr47;
        } else
-               goto tr42;
+               goto tr47;
        goto st0;
-st37:
+st39:
        if ( ++p == pe )
-               goto _test_eof37;
-case 37:
+               goto _test_eof39;
+case 39:
        if ( (*p) == 10 )
-               goto tr45;
+               goto tr50;
        goto st0;
-tr42:
-#line 113 "http_parser.rl"
+tr47:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st38;
-st38:
+       goto st40;
+st40:
        if ( ++p == pe )
-               goto _test_eof38;
-case 38:
-#line 1390 "http_parser.c"
+               goto _test_eof40;
+case 40:
+#line 1409 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-tr47:
-#line 143 "http_parser.rl"
+tr52:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st39;
-st39:
+       goto st41;
+st41:
        if ( ++p == pe )
-               goto _test_eof39;
-case 39:
-#line 1431 "http_parser.c"
+               goto _test_eof41;
+case 41:
+#line 1446 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr49;
-               case 32: goto st39;
+               case 13: goto tr54;
+               case 32: goto st41;
        }
-       goto tr48;
-tr48:
-#line 118 "http_parser.rl"
+       goto tr53;
+tr53:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st40;
-st40:
+       goto st42;
+st42:
        if ( ++p == pe )
-               goto _test_eof40;
-case 40:
-#line 1448 "http_parser.c"
+               goto _test_eof42;
+case 42:
+#line 1463 "http_parser.c"
        if ( (*p) == 13 )
-               goto tr52;
-       goto st40;
-tr43:
-#line 113 "http_parser.rl"
+               goto tr57;
+       goto st42;
+tr48:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st41;
-st41:
+       goto st43;
+st43:
        if ( ++p == pe )
-               goto _test_eof41;
-case 41:
-#line 1463 "http_parser.c"
+               goto _test_eof43;
+case 43:
+#line 1478 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 79: goto st42;
-               case 111: goto st42;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 79: goto st44;
+               case 111: goto st44;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st42:
+st44:
        if ( ++p == pe )
-               goto _test_eof42;
-case 42:
+               goto _test_eof44;
+case 44:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st43;
-               case 110: goto st43;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st45;
+               case 110: goto st45;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st43:
+st45:
        if ( ++p == pe )
-               goto _test_eof43;
-case 43:
+               goto _test_eof45;
+case 45:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st44;
-               case 84: goto st67;
-               case 110: goto st44;
-               case 116: goto st67;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st46;
+               case 84: goto st69;
+               case 110: goto st46;
+               case 116: goto st69;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st44:
+st46:
        if ( ++p == pe )
-               goto _test_eof44;
-case 44:
+               goto _test_eof46;
+case 46:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 69: goto st45;
-               case 101: goto st45;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 69: goto st47;
+               case 101: goto st47;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st45:
+st47:
        if ( ++p == pe )
-               goto _test_eof45;
-case 45:
+               goto _test_eof47;
+case 47:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 67: goto st46;
-               case 99: goto st46;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 67: goto st48;
+               case 99: goto st48;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st46:
+st48:
        if ( ++p == pe )
-               goto _test_eof46;
-case 46:
+               goto _test_eof48;
+case 48:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 84: goto st47;
-               case 116: goto st47;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 84: goto st49;
+               case 116: goto st49;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st47:
+st49:
        if ( ++p == pe )
-               goto _test_eof47;
-case 47:
+               goto _test_eof49;
+case 49:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 73: goto st48;
-               case 105: goto st48;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 73: goto st50;
+               case 105: goto st50;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st48:
+st50:
        if ( ++p == pe )
-               goto _test_eof48;
-case 48:
+               goto _test_eof50;
+case 50:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 79: goto st49;
-               case 111: goto st49;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 79: goto st51;
+               case 111: goto st51;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st49:
+st51:
        if ( ++p == pe )
-               goto _test_eof49;
-case 49:
+               goto _test_eof51;
+case 51:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st50;
-               case 110: goto st50;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st52;
+               case 110: goto st52;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st50:
+st52:
        if ( ++p == pe )
-               goto _test_eof50;
-case 50:
+               goto _test_eof52;
+case 52:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr63;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr68;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-tr63:
-#line 143 "http_parser.rl"
+tr68:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st51;
-st51:
-       if ( ++p == pe )
-               goto _test_eof51;
-case 51:
-#line 1776 "http_parser.c"
-       switch( (*p) ) {
-               case 13: goto tr49;
-               case 32: goto st51;
-               case 67: goto tr65;
-               case 75: goto tr66;
-               case 99: goto tr65;
-               case 107: goto tr66;
-       }
-       goto tr48;
-tr65:
-#line 118 "http_parser.rl"
-       {
-    parser->header_value_mark = p;
-    parser->header_value_size = 0;
-  }
-       goto st52;
-st52:
-       if ( ++p == pe )
-               goto _test_eof52;
-case 52:
-#line 1797 "http_parser.c"
-       switch( (*p) ) {
-               case 13: goto tr52;
-               case 76: goto st53;
-               case 108: goto st53;
-       }
-       goto st40;
+       goto st53;
 st53:
        if ( ++p == pe )
                goto _test_eof53;
 case 53:
+#line 1787 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 79: goto st54;
-               case 111: goto st54;
+               case 13: goto tr54;
+               case 32: goto st53;
+               case 67: goto tr70;
+               case 75: goto tr71;
+               case 99: goto tr70;
+               case 107: goto tr71;
        }
-       goto st40;
+       goto tr53;
+tr70:
+#line 128 "http_parser.rl"
+       {
+    parser->header_value_mark = p;
+    parser->header_value_size = 0;
+  }
+       goto st54;
 st54:
        if ( ++p == pe )
                goto _test_eof54;
 case 54:
+#line 1808 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 83: goto st55;
-               case 115: goto st55;
+               case 13: goto tr57;
+               case 76: goto st55;
+               case 108: goto st55;
        }
-       goto st40;
+       goto st42;
 st55:
        if ( ++p == pe )
                goto _test_eof55;
 case 55:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 69: goto st56;
-               case 101: goto st56;
+               case 13: goto tr57;
+               case 79: goto st56;
+               case 111: goto st56;
        }
-       goto st40;
+       goto st42;
 st56:
        if ( ++p == pe )
                goto _test_eof56;
 case 56:
-       if ( (*p) == 13 )
-               goto tr71;
-       goto st40;
-tr66:
-#line 118 "http_parser.rl"
-       {
-    parser->header_value_mark = p;
-    parser->header_value_size = 0;
-  }
-       goto st57;
+       switch( (*p) ) {
+               case 13: goto tr57;
+               case 83: goto st57;
+               case 115: goto st57;
+       }
+       goto st42;
 st57:
        if ( ++p == pe )
                goto _test_eof57;
 case 57:
-#line 1852 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
+               case 13: goto tr57;
                case 69: goto st58;
                case 101: goto st58;
        }
-       goto st40;
+       goto st42;
 st58:
        if ( ++p == pe )
                goto _test_eof58;
 case 58:
-       switch( (*p) ) {
-               case 13: goto tr52;
-               case 69: goto st59;
-               case 101: goto st59;
-       }
-       goto st40;
+       if ( (*p) == 13 )
+               goto tr76;
+       goto st42;
+tr71:
+#line 128 "http_parser.rl"
+       {
+    parser->header_value_mark = p;
+    parser->header_value_size = 0;
+  }
+       goto st59;
 st59:
        if ( ++p == pe )
                goto _test_eof59;
 case 59:
+#line 1863 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 80: goto st60;
-               case 112: goto st60;
+               case 13: goto tr57;
+               case 69: goto st60;
+               case 101: goto st60;
        }
-       goto st40;
+       goto st42;
 st60:
        if ( ++p == pe )
                goto _test_eof60;
 case 60:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 45: goto st61;
+               case 13: goto tr57;
+               case 69: goto st61;
+               case 101: goto st61;
        }
-       goto st40;
+       goto st42;
 st61:
        if ( ++p == pe )
                goto _test_eof61;
 case 61:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 65: goto st62;
-               case 97: goto st62;
+               case 13: goto tr57;
+               case 80: goto st62;
+               case 112: goto st62;
        }
-       goto st40;
+       goto st42;
 st62:
        if ( ++p == pe )
                goto _test_eof62;
 case 62:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 76: goto st63;
-               case 108: goto st63;
+               case 13: goto tr57;
+               case 45: goto st63;
        }
-       goto st40;
+       goto st42;
 st63:
        if ( ++p == pe )
                goto _test_eof63;
 case 63:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 73: goto st64;
-               case 105: goto st64;
+               case 13: goto tr57;
+               case 65: goto st64;
+               case 97: goto st64;
        }
-       goto st40;
+       goto st42;
 st64:
        if ( ++p == pe )
                goto _test_eof64;
 case 64:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 86: goto st65;
-               case 118: goto st65;
+               case 13: goto tr57;
+               case 76: goto st65;
+               case 108: goto st65;
        }
-       goto st40;
+       goto st42;
 st65:
        if ( ++p == pe )
                goto _test_eof65;
 case 65:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 69: goto st66;
-               case 101: goto st66;
+               case 13: goto tr57;
+               case 73: goto st66;
+               case 105: goto st66;
        }
-       goto st40;
+       goto st42;
 st66:
        if ( ++p == pe )
                goto _test_eof66;
 case 66:
-       if ( (*p) == 13 )
-               goto tr81;
-       goto st40;
+       switch( (*p) ) {
+               case 13: goto tr57;
+               case 86: goto st67;
+               case 118: goto st67;
+       }
+       goto st42;
 st67:
        if ( ++p == pe )
                goto _test_eof67;
 case 67:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
+               case 13: goto tr57;
                case 69: goto st68;
                case 101: goto st68;
-               case 124: goto st38;
-               case 126: goto st38;
+       }
+       goto st42;
+st68:
+       if ( ++p == pe )
+               goto _test_eof68;
+case 68:
+       if ( (*p) == 13 )
+               goto tr86;
+       goto st42;
+st69:
+       if ( ++p == pe )
+               goto _test_eof69;
+case 69:
+       switch( (*p) ) {
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 69: goto st70;
+               case 101: goto st70;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st68:
+st70:
        if ( ++p == pe )
-               goto _test_eof68;
-case 68:
+               goto _test_eof70;
+case 70:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st69;
-               case 110: goto st69;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st71;
+               case 110: goto st71;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st69:
+st71:
        if ( ++p == pe )
-               goto _test_eof69;
-case 69:
+               goto _test_eof71;
+case 71:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 84: goto st70;
-               case 116: goto st70;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 84: goto st72;
+               case 116: goto st72;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st70:
+st72:
        if ( ++p == pe )
-               goto _test_eof70;
-case 70:
+               goto _test_eof72;
+case 72:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 45: goto st71;
-               case 46: goto st38;
-               case 58: goto tr47;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 45: goto st73;
+               case 46: goto st40;
+               case 58: goto tr52;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 48 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 57 ) {
                if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 65 )
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st71:
+st73:
        if ( ++p == pe )
-               goto _test_eof71;
-case 71:
+               goto _test_eof73;
+case 73:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 76: goto st72;
-               case 108: goto st72;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 76: goto st74;
+               case 108: goto st74;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st72:
+st74:
        if ( ++p == pe )
-               goto _test_eof72;
-case 72:
+               goto _test_eof74;
+case 74:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 69: goto st73;
-               case 101: goto st73;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 69: goto st75;
+               case 101: goto st75;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st73:
+st75:
        if ( ++p == pe )
-               goto _test_eof73;
-case 73:
+               goto _test_eof75;
+case 75:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st74;
-               case 110: goto st74;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st76;
+               case 110: goto st76;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st74:
+st76:
        if ( ++p == pe )
-               goto _test_eof74;
-case 74:
+               goto _test_eof76;
+case 76:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 71: goto st75;
-               case 103: goto st75;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 71: goto st77;
+               case 103: goto st77;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st75:
+st77:
        if ( ++p == pe )
-               goto _test_eof75;
-case 75:
+               goto _test_eof77;
+case 77:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 84: goto st76;
-               case 116: goto st76;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 84: goto st78;
+               case 116: goto st78;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st76:
+st78:
        if ( ++p == pe )
-               goto _test_eof76;
-case 76:
+               goto _test_eof78;
+case 78:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 72: goto st77;
-               case 104: goto st77;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 72: goto st79;
+               case 104: goto st79;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-st77:
+st79:
        if ( ++p == pe )
-               goto _test_eof77;
-case 77:
+               goto _test_eof79;
+case 79:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr92;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr97;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-tr92:
-#line 143 "http_parser.rl"
+tr97:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st78;
-st78:
+       goto st80;
+st80:
        if ( ++p == pe )
-               goto _test_eof78;
-case 78:
-#line 2286 "http_parser.c"
+               goto _test_eof80;
+case 80:
+#line 2293 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr49;
-               case 32: goto st78;
+               case 13: goto tr54;
+               case 32: goto st80;
        }
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr94;
-       goto tr48;
-tr94:
-#line 223 "http_parser.rl"
+               goto tr99;
+       goto tr53;
+tr99:
+#line 209 "http_parser.rl"
        {
+    if (parser->content_length == -1) parser->content_length = 0;
     if (parser->content_length > INT_MAX) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
     parser->content_length *= 10;
     parser->content_length += *p - '0';
   }
-#line 118 "http_parser.rl"
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st79;
-tr95:
-#line 223 "http_parser.rl"
+       goto st81;
+tr100:
+#line 209 "http_parser.rl"
        {
+    if (parser->content_length == -1) parser->content_length = 0;
     if (parser->content_length > INT_MAX) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
     parser->content_length *= 10;
     parser->content_length += *p - '0';
   }
-       goto st79;
-st79:
+       goto st81;
+st81:
        if ( ++p == pe )
-               goto _test_eof79;
-case 79:
-#line 2325 "http_parser.c"
+               goto _test_eof81;
+case 81:
+#line 2334 "http_parser.c"
        if ( (*p) == 13 )
-               goto tr52;
+               goto tr57;
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr95;
-       goto st40;
-tr44:
-#line 113 "http_parser.rl"
+               goto tr100;
+       goto st42;
+tr49:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st80;
-st80:
-       if ( ++p == pe )
-               goto _test_eof80;
-case 80:
-#line 2342 "http_parser.c"
-       switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 82: goto st81;
-               case 114: goto st81;
-               case 124: goto st38;
-               case 126: goto st38;
-       }
-       if ( (*p) < 45 ) {
-               if ( (*p) > 39 ) {
-                       if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
-               } else if ( (*p) >= 35 )
-                       goto st38;
-       } else if ( (*p) > 46 ) {
-               if ( (*p) < 65 ) {
-                       if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
-               } else if ( (*p) > 90 ) {
-                       if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
-               } else
-                       goto st38;
-       } else
-               goto st38;
-       goto st0;
-st81:
-       if ( ++p == pe )
-               goto _test_eof81;
-case 81:
-       switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 65: goto st82;
-               case 97: goto st82;
-               case 124: goto st38;
-               case 126: goto st38;
-       }
-       if ( (*p) < 45 ) {
-               if ( (*p) > 39 ) {
-                       if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
-               } else if ( (*p) >= 35 )
-                       goto st38;
-       } else if ( (*p) > 46 ) {
-               if ( (*p) < 66 ) {
-                       if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
-               } else if ( (*p) > 90 ) {
-                       if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
-               } else
-                       goto st38;
-       } else
-               goto st38;
-       goto st0;
+       goto st82;
 st82:
        if ( ++p == pe )
                goto _test_eof82;
 case 82:
+#line 2351 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st83;
-               case 110: goto st83;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 82: goto st83;
+               case 114: goto st83;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st83:
        if ( ++p == pe )
                goto _test_eof83;
 case 83:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 83: goto st84;
-               case 115: goto st84;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 65: goto st84;
+               case 97: goto st84;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
-               if ( (*p) < 65 ) {
+               if ( (*p) < 66 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st84:
        if ( ++p == pe )
                goto _test_eof84;
 case 84:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 70: goto st85;
-               case 102: goto st85;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st85;
+               case 110: goto st85;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st85:
        if ( ++p == pe )
                goto _test_eof85;
 case 85:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 69: goto st86;
-               case 101: goto st86;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 83: goto st86;
+               case 115: goto st86;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st86:
        if ( ++p == pe )
                goto _test_eof86;
 case 86:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 82: goto st87;
-               case 114: goto st87;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 70: goto st87;
+               case 102: goto st87;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st87:
        if ( ++p == pe )
                goto _test_eof87;
 case 87:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 45: goto st88;
-               case 46: goto st38;
-               case 58: goto tr47;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 69: goto st88;
+               case 101: goto st88;
+               case 124: goto st40;
+               case 126: goto st40;
        }
-       if ( (*p) < 48 ) {
+       if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
-       } else if ( (*p) > 57 ) {
-               if ( (*p) > 90 ) {
+                       goto st40;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st40;
+               } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
-               } else if ( (*p) >= 65 )
-                       goto st38;
+                               goto st40;
+               } else
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st88:
        if ( ++p == pe )
                goto _test_eof88;
 case 88:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 69: goto st89;
-               case 101: goto st89;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 82: goto st89;
+               case 114: goto st89;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st89:
        if ( ++p == pe )
                goto _test_eof89;
 case 89:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st90;
-               case 110: goto st90;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 45: goto st90;
+               case 46: goto st40;
+               case 58: goto tr52;
+               case 124: goto st40;
+               case 126: goto st40;
        }
-       if ( (*p) < 45 ) {
+       if ( (*p) < 48 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
-       } else if ( (*p) > 46 ) {
-               if ( (*p) < 65 ) {
-                       if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
-               } else if ( (*p) > 90 ) {
+                       goto st40;
+       } else if ( (*p) > 57 ) {
+               if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
-               } else
-                       goto st38;
+                               goto st40;
+               } else if ( (*p) >= 65 )
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st90:
        if ( ++p == pe )
                goto _test_eof90;
 case 90:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 67: goto st91;
-               case 99: goto st91;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 69: goto st91;
+               case 101: goto st91;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st91:
        if ( ++p == pe )
                goto _test_eof91;
 case 91:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 79: goto st92;
-               case 111: goto st92;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st92;
+               case 110: goto st92;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st92:
        if ( ++p == pe )
                goto _test_eof92;
 case 92:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 68: goto st93;
-               case 100: goto st93;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 67: goto st93;
+               case 99: goto st93;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st93:
        if ( ++p == pe )
                goto _test_eof93;
 case 93:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 73: goto st94;
-               case 105: goto st94;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 79: goto st94;
+               case 111: goto st94;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st94:
        if ( ++p == pe )
                goto _test_eof94;
 case 94:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 78: goto st95;
-               case 110: goto st95;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 68: goto st95;
+               case 100: goto st95;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st95:
        if ( ++p == pe )
                goto _test_eof95;
 case 95:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr47;
-               case 71: goto st96;
-               case 103: goto st96;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 73: goto st96;
+               case 105: goto st96;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
 st96:
        if ( ++p == pe )
                goto _test_eof96;
 case 96:
        switch( (*p) ) {
-               case 33: goto st38;
-               case 58: goto tr112;
-               case 124: goto st38;
-               case 126: goto st38;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 78: goto st97;
+               case 110: goto st97;
+               case 124: goto st40;
+               case 126: goto st40;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) >= 35 )
-                       goto st38;
+                       goto st40;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st38;
+                               goto st40;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st38;
+                               goto st40;
                } else
-                       goto st38;
+                       goto st40;
        } else
-               goto st38;
+               goto st40;
        goto st0;
-tr112:
-#line 238 "http_parser.rl"
-       { parser->transfer_encoding = HTTP_CHUNKED;  }
-#line 143 "http_parser.rl"
-       {
-    CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
-    parser->header_field_mark = NULL;
-    parser->header_field_size = 0;
-  }
-       goto st97;
 st97:
        if ( ++p == pe )
                goto _test_eof97;
 case 97:
-#line 2862 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr49;
-               case 32: goto st97;
-               case 105: goto tr114;
+               case 33: goto st40;
+               case 58: goto tr52;
+               case 71: goto st98;
+               case 103: goto st98;
+               case 124: goto st40;
+               case 126: goto st40;
        }
-       goto tr48;
-tr114:
-#line 118 "http_parser.rl"
-       {
-    parser->header_value_mark = p;
-    parser->header_value_size = 0;
-  }
-       goto st98;
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st40;
+               } else if ( (*p) >= 35 )
+                       goto st40;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st40;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st40;
+               } else
+                       goto st40;
+       } else
+               goto st40;
+       goto st0;
 st98:
        if ( ++p == pe )
                goto _test_eof98;
 case 98:
-#line 2880 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 100: goto st99;
+               case 33: goto st40;
+               case 58: goto tr117;
+               case 124: goto st40;
+               case 126: goto st40;
        }
-       goto st40;
+       if ( (*p) < 45 ) {
+               if ( (*p) > 39 ) {
+                       if ( 42 <= (*p) && (*p) <= 43 )
+                               goto st40;
+               } else if ( (*p) >= 35 )
+                       goto st40;
+       } else if ( (*p) > 46 ) {
+               if ( (*p) < 65 ) {
+                       if ( 48 <= (*p) && (*p) <= 57 )
+                               goto st40;
+               } else if ( (*p) > 90 ) {
+                       if ( 94 <= (*p) && (*p) <= 122 )
+                               goto st40;
+               } else
+                       goto st40;
+       } else
+               goto st40;
+       goto st0;
+tr117:
+#line 153 "http_parser.rl"
+       {
+    CALLBACK(header_field);
+    parser->header_field_mark = NULL;
+    parser->header_field_size = 0;
+  }
+       goto st99;
 st99:
        if ( ++p == pe )
                goto _test_eof99;
 case 99:
+#line 2865 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 101: goto st100;
+               case 13: goto tr54;
+               case 32: goto st99;
+               case 67: goto tr119;
+               case 99: goto tr119;
        }
-       goto st40;
+       goto tr53;
+tr119:
+#line 128 "http_parser.rl"
+       {
+    parser->header_value_mark = p;
+    parser->header_value_size = 0;
+  }
+       goto st100;
 st100:
        if ( ++p == pe )
                goto _test_eof100;
 case 100:
+#line 2884 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 110: goto st101;
+               case 13: goto tr57;
+               case 72: goto st101;
+               case 104: goto st101;
        }
-       goto st40;
+       goto st42;
 st101:
        if ( ++p == pe )
                goto _test_eof101;
 case 101:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 116: goto st102;
+               case 13: goto tr57;
+               case 85: goto st102;
+               case 117: goto st102;
        }
-       goto st40;
+       goto st42;
 st102:
        if ( ++p == pe )
                goto _test_eof102;
 case 102:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 105: goto st103;
+               case 13: goto tr57;
+               case 78: goto st103;
+               case 110: goto st103;
        }
-       goto st40;
+       goto st42;
 st103:
        if ( ++p == pe )
                goto _test_eof103;
 case 103:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 116: goto st104;
+               case 13: goto tr57;
+               case 75: goto st104;
+               case 107: goto st104;
        }
-       goto st40;
+       goto st42;
 st104:
        if ( ++p == pe )
                goto _test_eof104;
 case 104:
        switch( (*p) ) {
-               case 13: goto tr52;
-               case 121: goto st105;
+               case 13: goto tr57;
+               case 69: goto st105;
+               case 101: goto st105;
        }
-       goto st40;
+       goto st42;
 st105:
        if ( ++p == pe )
                goto _test_eof105;
 case 105:
+       switch( (*p) ) {
+               case 13: goto tr57;
+               case 68: goto st106;
+               case 100: goto st106;
+       }
+       goto st42;
+st106:
+       if ( ++p == pe )
+               goto _test_eof106;
+case 106:
        if ( (*p) == 13 )
-               goto tr122;
-       goto st40;
-tr30:
-#line 163 "http_parser.rl"
-       { 
-    CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
-    parser->uri_mark = NULL;
-    parser->uri_size = 0;
+               goto tr126;
+       goto st42;
+st107:
+       if ( ++p == pe )
+               goto _test_eof107;
+case 107:
+       if ( (*p) == 13 )
+               goto tr127;
+       goto st0;
+st108:
+       if ( ++p == pe )
+               goto _test_eof108;
+case 108:
+       if ( (*p) == 46 )
+               goto st109;
+       goto st0;
+st109:
+       if ( ++p == pe )
+               goto _test_eof109;
+case 109:
+       switch( (*p) ) {
+               case 48: goto st110;
+               case 49: goto st111;
+       }
+       if ( 50 <= (*p) && (*p) <= 57 )
+               goto st36;
+       goto st0;
+st110:
+       if ( ++p == pe )
+               goto _test_eof110;
+case 110:
+       if ( (*p) == 13 )
+               goto tr131;
+       goto st0;
+st111:
+       if ( ++p == pe )
+               goto _test_eof111;
+case 111:
+       if ( (*p) == 13 )
+               goto tr132;
+       goto st0;
+st112:
+       if ( ++p == pe )
+               goto _test_eof112;
+case 112:
+       if ( (*p) == 46 )
+               goto st113;
+       goto st0;
+st113:
+       if ( ++p == pe )
+               goto _test_eof113;
+case 113:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st36;
+       goto st0;
+tr32:
+#line 165 "http_parser.rl"
+       {
+    CALLBACK(uri);
+    parser->uri_mark = NULL;
+    parser->uri_size = 0;
   }
-       goto st106;
-tr136:
-#line 193 "http_parser.rl"
+       goto st114;
+tr147:
+#line 183 "http_parser.rl"
        {
     CALLBACK(path);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->path_mark = NULL;
     parser->path_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st106;
-tr142:
-#line 128 "http_parser.rl"
+       goto st114;
+tr153:
+#line 138 "http_parser.rl"
        {
     parser->query_string_mark = p;
     parser->query_string_size = 0;
   }
-#line 183 "http_parser.rl"
-       { 
+#line 177 "http_parser.rl"
+       {
     CALLBACK(query_string);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->query_string_mark = NULL;
     parser->query_string_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st106;
-tr146:
-#line 183 "http_parser.rl"
-       { 
+       goto st114;
+tr157:
+#line 177 "http_parser.rl"
+       {
     CALLBACK(query_string);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->query_string_mark = NULL;
     parser->query_string_size = 0;
   }
-#line 163 "http_parser.rl"
-       { 
+#line 165 "http_parser.rl"
+       {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
-       goto st106;
-st106:
+       goto st114;
+st114:
        if ( ++p == pe )
-               goto _test_eof106;
-case 106:
-#line 3034 "http_parser.c"
+               goto _test_eof114;
+case 114:
+#line 3060 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr124;
+               case 32: goto tr135;
                case 35: goto st0;
-               case 37: goto tr125;
+               case 37: goto tr136;
                case 60: goto st0;
                case 62: goto st0;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto tr123;
-tr123:
-#line 123 "http_parser.rl"
+       goto tr134;
+tr134:
+#line 133 "http_parser.rl"
        {
     parser->fragment_mark = p;
     parser->fragment_size = 0;
   }
-       goto st107;
-st107:
+       goto st115;
+st115:
        if ( ++p == pe )
-               goto _test_eof107;
-case 107:
-#line 3057 "http_parser.c"
+               goto _test_eof115;
+case 115:
+#line 3083 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr127;
+               case 32: goto tr138;
                case 35: goto st0;
-               case 37: goto st108;
+               case 37: goto st116;
                case 60: goto st0;
                case 62: goto st0;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto st107;
-tr125:
-#line 123 "http_parser.rl"
+       goto st115;
+tr136:
+#line 133 "http_parser.rl"
        {
     parser->fragment_mark = p;
     parser->fragment_size = 0;
   }
-       goto st108;
-st108:
+       goto st116;
+st116:
        if ( ++p == pe )
-               goto _test_eof108;
-case 108:
-#line 3080 "http_parser.c"
+               goto _test_eof116;
+case 116:
+#line 3106 "http_parser.c"
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st109;
+                       goto st117;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st109;
+                       goto st117;
        } else
-               goto st109;
+               goto st117;
        goto st0;
-st109:
+st117:
        if ( ++p == pe )
-               goto _test_eof109;
-case 109:
+               goto _test_eof117;
+case 117:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st107;
+                       goto st115;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st107;
+                       goto st115;
        } else
-               goto st107;
+               goto st115;
        goto st0;
-tr26:
-#line 138 "http_parser.rl"
+tr28:
+#line 148 "http_parser.rl"
        {
     parser->uri_mark = p;
     parser->uri_size = 0;
   }
-       goto st110;
-st110:
+       goto st118;
+st118:
        if ( ++p == pe )
-               goto _test_eof110;
-case 110:
-#line 3114 "http_parser.c"
+               goto _test_eof118;
+case 118:
+#line 3140 "http_parser.c"
        switch( (*p) ) {
-               case 43: goto st110;
-               case 58: goto st111;
+               case 43: goto st118;
+               case 58: goto st119;
        }
        if ( (*p) < 48 ) {
                if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st110;
+                       goto st118;
        } else if ( (*p) > 57 ) {
                if ( (*p) > 90 ) {
                        if ( 97 <= (*p) && (*p) <= 122 )
-                               goto st110;
+                               goto st118;
                } else if ( (*p) >= 65 )
-                       goto st110;
+                       goto st118;
        } else
-               goto st110;
+               goto st118;
        goto st0;
-tr28:
-#line 138 "http_parser.rl"
+tr30:
+#line 148 "http_parser.rl"
        {
     parser->uri_mark = p;
     parser->uri_size = 0;
   }
-       goto st111;
-st111:
+       goto st119;
+st119:
        if ( ++p == pe )
-               goto _test_eof111;
-case 111:
-#line 3142 "http_parser.c"
+               goto _test_eof119;
+case 119:
+#line 3168 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr29;
-               case 35: goto tr30;
-               case 37: goto st112;
+               case 32: goto tr31;
+               case 35: goto tr32;
+               case 37: goto st120;
                case 60: goto st0;
                case 62: goto st0;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto st111;
-st112:
+       goto st119;
+st120:
        if ( ++p == pe )
-               goto _test_eof112;
-case 112:
+               goto _test_eof120;
+case 120:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st113;
+                       goto st121;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st113;
+                       goto st121;
        } else
-               goto st113;
+               goto st121;
        goto st0;
-st113:
+st121:
        if ( ++p == pe )
-               goto _test_eof113;
-case 113:
+               goto _test_eof121;
+case 121:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st111;
+                       goto st119;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st111;
+                       goto st119;
        } else
-               goto st111;
+               goto st119;
        goto st0;
-tr27:
-#line 138 "http_parser.rl"
+tr29:
+#line 148 "http_parser.rl"
        {
     parser->uri_mark = p;
     parser->uri_size = 0;
   }
-#line 133 "http_parser.rl"
+#line 143 "http_parser.rl"
        {
     parser->path_mark = p;
     parser->path_size = 0;
   }
-       goto st114;
-st114:
+       goto st122;
+st122:
        if ( ++p == pe )
-               goto _test_eof114;
-case 114:
-#line 3196 "http_parser.c"
+               goto _test_eof122;
+case 122:
+#line 3222 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr135;
-               case 35: goto tr136;
-               case 37: goto st115;
+               case 32: goto tr146;
+               case 35: goto tr147;
+               case 37: goto st123;
                case 60: goto st0;
                case 62: goto st0;
-               case 63: goto tr138;
+               case 63: goto tr149;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto st114;
-st115:
+       goto st122;
+st123:
        if ( ++p == pe )
-               goto _test_eof115;
-case 115:
+               goto _test_eof123;
+case 123:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st116;
+                       goto st124;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st116;
+                       goto st124;
        } else
-               goto st116;
+               goto st124;
        goto st0;
-st116:
+st124:
        if ( ++p == pe )
-               goto _test_eof116;
-case 116:
+               goto _test_eof124;
+case 124:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st114;
+                       goto st122;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st114;
+                       goto st122;
        } else
-               goto st114;
+               goto st122;
        goto st0;
-tr138:
-#line 193 "http_parser.rl"
+tr149:
+#line 183 "http_parser.rl"
        {
     CALLBACK(path);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->path_mark = NULL;
     parser->path_size = 0;
   }
-       goto st117;
-st117:
+       goto st125;
+st125:
        if ( ++p == pe )
-               goto _test_eof117;
-case 117:
-#line 3251 "http_parser.c"
+               goto _test_eof125;
+case 125:
+#line 3273 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr141;
-               case 35: goto tr142;
-               case 37: goto tr143;
+               case 32: goto tr152;
+               case 35: goto tr153;
+               case 37: goto tr154;
                case 60: goto st0;
                case 62: goto st0;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto tr140;
-tr140:
-#line 128 "http_parser.rl"
+       goto tr151;
+tr151:
+#line 138 "http_parser.rl"
        {
     parser->query_string_mark = p;
     parser->query_string_size = 0;
   }
-       goto st118;
-st118:
+       goto st126;
+st126:
        if ( ++p == pe )
-               goto _test_eof118;
-case 118:
-#line 3274 "http_parser.c"
+               goto _test_eof126;
+case 126:
+#line 3296 "http_parser.c"
        switch( (*p) ) {
-               case 32: goto tr145;
-               case 35: goto tr146;
-               case 37: goto st119;
+               case 32: goto tr156;
+               case 35: goto tr157;
+               case 37: goto st127;
                case 60: goto st0;
                case 62: goto st0;
                case 127: goto st0;
        }
        if ( 0 <= (*p) && (*p) <= 31 )
                goto st0;
-       goto st118;
-tr143:
-#line 128 "http_parser.rl"
+       goto st126;
+tr154:
+#line 138 "http_parser.rl"
        {
     parser->query_string_mark = p;
     parser->query_string_size = 0;
   }
-       goto st119;
-st119:
+       goto st127;
+st127:
        if ( ++p == pe )
-               goto _test_eof119;
-case 119:
-#line 3297 "http_parser.c"
+               goto _test_eof127;
+case 127:
+#line 3319 "http_parser.c"
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st120;
+                       goto st128;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st120;
+                       goto st128;
        } else
-               goto st120;
+               goto st128;
        goto st0;
-st120:
+st128:
        if ( ++p == pe )
-               goto _test_eof120;
-case 120:
+               goto _test_eof128;
+case 128:
        if ( (*p) < 65 ) {
                if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st118;
+                       goto st126;
        } else if ( (*p) > 70 ) {
                if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st118;
+                       goto st126;
        } else
-               goto st118;
-       goto st0;
-tr311:
-#line 213 "http_parser.rl"
-       {
-    if(parser->on_message_begin) {
-      callback_return_value = parser->on_message_begin(parser);
-      if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
-      }
-    }
-  }
-       goto st121;
-st121:
-       if ( ++p == pe )
-               goto _test_eof121;
-case 121:
-#line 3336 "http_parser.c"
-       if ( (*p) == 69 )
-               goto st122;
-       goto st0;
-st122:
-       if ( ++p == pe )
-               goto _test_eof122;
-case 122:
-       if ( (*p) == 76 )
-               goto st123;
-       goto st0;
-st123:
-       if ( ++p == pe )
-               goto _test_eof123;
-case 123:
-       if ( (*p) == 69 )
-               goto st124;
-       goto st0;
-st124:
-       if ( ++p == pe )
-               goto _test_eof124;
-case 124:
-       if ( (*p) == 84 )
-               goto st125;
-       goto st0;
-st125:
-       if ( ++p == pe )
-               goto _test_eof125;
-case 125:
-       if ( (*p) == 69 )
                goto st126;
        goto st0;
-st126:
-       if ( ++p == pe )
-               goto _test_eof126;
-case 126:
-       if ( (*p) == 32 )
-               goto tr154;
-       goto st0;
-tr312:
-#line 213 "http_parser.rl"
+tr331:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st127;
-st127:
-       if ( ++p == pe )
-               goto _test_eof127;
-case 127:
-#line 3391 "http_parser.c"
-       if ( (*p) == 69 )
-               goto st128;
-       goto st0;
-st128:
-       if ( ++p == pe )
-               goto _test_eof128;
-case 128:
-       if ( (*p) == 84 )
-               goto st129;
-       goto st0;
+       goto st129;
 st129:
        if ( ++p == pe )
                goto _test_eof129;
 case 129:
-       if ( (*p) == 32 )
-               goto tr157;
+#line 3358 "http_parser.c"
+       if ( (*p) == 69 )
+               goto st130;
        goto st0;
-tr313:
-#line 213 "http_parser.rl"
-       {
-    if(parser->on_message_begin) {
-      callback_return_value = parser->on_message_begin(parser);
-      if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
-      }
-    }
-  }
-       goto st130;
 st130:
        if ( ++p == pe )
                goto _test_eof130;
 case 130:
-#line 3425 "http_parser.c"
-       if ( (*p) == 69 )
+       if ( (*p) == 76 )
                goto st131;
        goto st0;
 st131:
        if ( ++p == pe )
                goto _test_eof131;
 case 131:
-       if ( (*p) == 65 )
+       if ( (*p) == 69 )
                goto st132;
        goto st0;
 st132:
        if ( ++p == pe )
                goto _test_eof132;
 case 132:
-       if ( (*p) == 68 )
+       if ( (*p) == 84 )
                goto st133;
        goto st0;
 st133:
        if ( ++p == pe )
                goto _test_eof133;
 case 133:
+       if ( (*p) == 69 )
+               goto st134;
+       goto st0;
+st134:
+       if ( ++p == pe )
+               goto _test_eof134;
+case 134:
        if ( (*p) == 32 )
-               goto tr161;
+               goto tr165;
        goto st0;
-tr314:
-#line 213 "http_parser.rl"
+tr332:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st134;
-st134:
-       if ( ++p == pe )
-               goto _test_eof134;
-case 134:
-#line 3466 "http_parser.c"
-       if ( (*p) == 79 )
-               goto st135;
-       goto st0;
+       goto st135;
 st135:
        if ( ++p == pe )
                goto _test_eof135;
 case 135:
-       if ( (*p) == 67 )
+#line 3413 "http_parser.c"
+       if ( (*p) == 69 )
                goto st136;
        goto st0;
 st136:
        if ( ++p == pe )
                goto _test_eof136;
 case 136:
-       if ( (*p) == 75 )
+       if ( (*p) == 84 )
                goto st137;
        goto st0;
 st137:
@@ -3485,16 +3425,16 @@ st137:
                goto _test_eof137;
 case 137:
        if ( (*p) == 32 )
-               goto tr165;
+               goto tr168;
        goto st0;
-tr315:
-#line 213 "http_parser.rl"
+tr333:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
@@ -3503,52 +3443,63 @@ st138:
        if ( ++p == pe )
                goto _test_eof138;
 case 138:
-#line 3507 "http_parser.c"
-       switch( (*p) ) {
-               case 75: goto st139;
-               case 79: goto st143;
-       }
+#line 3447 "http_parser.c"
+       if ( (*p) == 69 )
+               goto st139;
        goto st0;
 st139:
        if ( ++p == pe )
                goto _test_eof139;
 case 139:
-       if ( (*p) == 67 )
+       if ( (*p) == 65 )
                goto st140;
        goto st0;
 st140:
        if ( ++p == pe )
                goto _test_eof140;
 case 140:
-       if ( (*p) == 79 )
+       if ( (*p) == 68 )
                goto st141;
        goto st0;
 st141:
        if ( ++p == pe )
                goto _test_eof141;
 case 141:
-       if ( (*p) == 76 )
-               goto st142;
+       if ( (*p) == 32 )
+               goto tr172;
        goto st0;
+tr334:
+#line 199 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {
+        parser->flags |= ERROR;
+        return;
+      }
+    }
+  }
+       goto st142;
 st142:
        if ( ++p == pe )
                goto _test_eof142;
 case 142:
-       if ( (*p) == 32 )
-               goto tr171;
+#line 3488 "http_parser.c"
+       if ( (*p) == 79 )
+               goto st143;
        goto st0;
 st143:
        if ( ++p == pe )
                goto _test_eof143;
 case 143:
-       if ( (*p) == 86 )
+       if ( (*p) == 67 )
                goto st144;
        goto st0;
 st144:
        if ( ++p == pe )
                goto _test_eof144;
 case 144:
-       if ( (*p) == 69 )
+       if ( (*p) == 75 )
                goto st145;
        goto st0;
 st145:
@@ -3556,16 +3507,16 @@ st145:
                goto _test_eof145;
 case 145:
        if ( (*p) == 32 )
-               goto tr174;
+               goto tr176;
        goto st0;
-tr316:
-#line 213 "http_parser.rl"
+tr335:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
@@ -3574,80 +3525,79 @@ st146:
        if ( ++p == pe )
                goto _test_eof146;
 case 146:
-#line 3578 "http_parser.c"
-       if ( (*p) == 80 )
-               goto st147;
+#line 3529 "http_parser.c"
+       switch( (*p) ) {
+               case 75: goto st147;
+               case 79: goto st151;
+       }
        goto st0;
 st147:
        if ( ++p == pe )
                goto _test_eof147;
 case 147:
-       if ( (*p) == 84 )
+       if ( (*p) == 67 )
                goto st148;
        goto st0;
 st148:
        if ( ++p == pe )
                goto _test_eof148;
 case 148:
-       if ( (*p) == 73 )
+       if ( (*p) == 79 )
                goto st149;
        goto st0;
 st149:
        if ( ++p == pe )
                goto _test_eof149;
 case 149:
-       if ( (*p) == 79 )
+       if ( (*p) == 76 )
                goto st150;
        goto st0;
 st150:
        if ( ++p == pe )
                goto _test_eof150;
 case 150:
-       if ( (*p) == 78 )
-               goto st151;
+       if ( (*p) == 32 )
+               goto tr182;
        goto st0;
 st151:
        if ( ++p == pe )
                goto _test_eof151;
 case 151:
-       if ( (*p) == 83 )
+       if ( (*p) == 86 )
                goto st152;
        goto st0;
 st152:
        if ( ++p == pe )
                goto _test_eof152;
 case 152:
+       if ( (*p) == 69 )
+               goto st153;
+       goto st0;
+st153:
+       if ( ++p == pe )
+               goto _test_eof153;
+case 153:
        if ( (*p) == 32 )
-               goto tr181;
+               goto tr185;
        goto st0;
-tr317:
-#line 213 "http_parser.rl"
+tr336:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st153;
-st153:
-       if ( ++p == pe )
-               goto _test_eof153;
-case 153:
-#line 3640 "http_parser.c"
-       switch( (*p) ) {
-               case 79: goto st154;
-               case 82: goto st157;
-               case 85: goto st169;
-       }
-       goto st0;
+       goto st154;
 st154:
        if ( ++p == pe )
                goto _test_eof154;
 case 154:
-       if ( (*p) == 83 )
+#line 3600 "http_parser.c"
+       if ( (*p) == 80 )
                goto st155;
        goto st0;
 st155:
@@ -3661,8 +3611,8 @@ st156:
        if ( ++p == pe )
                goto _test_eof156;
 case 156:
-       if ( (*p) == 32 )
-               goto tr187;
+       if ( (*p) == 73 )
+               goto st157;
        goto st0;
 st157:
        if ( ++p == pe )
@@ -3675,224 +3625,310 @@ st158:
        if ( ++p == pe )
                goto _test_eof158;
 case 158:
-       if ( (*p) == 80 )
+       if ( (*p) == 78 )
                goto st159;
        goto st0;
 st159:
        if ( ++p == pe )
                goto _test_eof159;
 case 159:
-       switch( (*p) ) {
-               case 70: goto st160;
-               case 80: goto st164;
-       }
+       if ( (*p) == 83 )
+               goto st160;
        goto st0;
 st160:
        if ( ++p == pe )
                goto _test_eof160;
 case 160:
-       if ( (*p) == 73 )
-               goto st161;
+       if ( (*p) == 32 )
+               goto tr192;
        goto st0;
+tr337:
+#line 199 "http_parser.rl"
+       {
+    if(parser->on_message_begin) {
+      callback_return_value = parser->on_message_begin(parser);
+      if (callback_return_value != 0) {
+        parser->flags |= ERROR;
+        return;
+      }
+    }
+  }
+       goto st161;
 st161:
        if ( ++p == pe )
                goto _test_eof161;
 case 161:
-       if ( (*p) == 78 )
-               goto st162;
+#line 3662 "http_parser.c"
+       switch( (*p) ) {
+               case 79: goto st162;
+               case 82: goto st165;
+               case 85: goto st177;
+       }
        goto st0;
 st162:
        if ( ++p == pe )
                goto _test_eof162;
 case 162:
-       if ( (*p) == 68 )
+       if ( (*p) == 83 )
                goto st163;
        goto st0;
 st163:
        if ( ++p == pe )
                goto _test_eof163;
 case 163:
-       if ( (*p) == 32 )
-               goto tr195;
+       if ( (*p) == 84 )
+               goto st164;
        goto st0;
 st164:
        if ( ++p == pe )
                goto _test_eof164;
 case 164:
-       if ( (*p) == 65 )
-               goto st165;
+       if ( (*p) == 32 )
+               goto tr198;
        goto st0;
 st165:
        if ( ++p == pe )
                goto _test_eof165;
 case 165:
-       if ( (*p) == 84 )
+       if ( (*p) == 79 )
                goto st166;
        goto st0;
 st166:
        if ( ++p == pe )
                goto _test_eof166;
 case 166:
-       if ( (*p) == 67 )
+       if ( (*p) == 80 )
                goto st167;
        goto st0;
 st167:
        if ( ++p == pe )
                goto _test_eof167;
 case 167:
-       if ( (*p) == 72 )
-               goto st168;
+       switch( (*p) ) {
+               case 70: goto st168;
+               case 80: goto st172;
+       }
        goto st0;
 st168:
        if ( ++p == pe )
                goto _test_eof168;
 case 168:
-       if ( (*p) == 32 )
-               goto tr200;
+       if ( (*p) == 73 )
+               goto st169;
        goto st0;
 st169:
        if ( ++p == pe )
                goto _test_eof169;
 case 169:
-       if ( (*p) == 84 )
+       if ( (*p) == 78 )
                goto st170;
        goto st0;
 st170:
        if ( ++p == pe )
                goto _test_eof170;
 case 170:
+       if ( (*p) == 68 )
+               goto st171;
+       goto st0;
+st171:
+       if ( ++p == pe )
+               goto _test_eof171;
+case 171:
+       if ( (*p) == 32 )
+               goto tr206;
+       goto st0;
+st172:
+       if ( ++p == pe )
+               goto _test_eof172;
+case 172:
+       if ( (*p) == 65 )
+               goto st173;
+       goto st0;
+st173:
+       if ( ++p == pe )
+               goto _test_eof173;
+case 173:
+       if ( (*p) == 84 )
+               goto st174;
+       goto st0;
+st174:
+       if ( ++p == pe )
+               goto _test_eof174;
+case 174:
+       if ( (*p) == 67 )
+               goto st175;
+       goto st0;
+st175:
+       if ( ++p == pe )
+               goto _test_eof175;
+case 175:
+       if ( (*p) == 72 )
+               goto st176;
+       goto st0;
+st176:
+       if ( ++p == pe )
+               goto _test_eof176;
+case 176:
        if ( (*p) == 32 )
-               goto tr202;
+               goto tr211;
+       goto st0;
+st177:
+       if ( ++p == pe )
+               goto _test_eof177;
+case 177:
+       if ( (*p) == 84 )
+               goto st178;
+       goto st0;
+st178:
+       if ( ++p == pe )
+               goto _test_eof178;
+case 178:
+       if ( (*p) == 32 )
+               goto tr213;
        goto st0;
-tr318:
-#line 213 "http_parser.rl"
+tr338:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st171;
-st171:
+       goto st179;
+st179:
        if ( ++p == pe )
-               goto _test_eof171;
-case 171:
-#line 3784 "http_parser.c"
+               goto _test_eof179;
+case 179:
+#line 3806 "http_parser.c"
        if ( (*p) == 82 )
-               goto st172;
+               goto st180;
        goto st0;
-st172:
+st180:
        if ( ++p == pe )
-               goto _test_eof172;
-case 172:
+               goto _test_eof180;
+case 180:
        if ( (*p) == 65 )
-               goto st173;
+               goto st181;
        goto st0;
-st173:
+st181:
        if ( ++p == pe )
-               goto _test_eof173;
-case 173:
+               goto _test_eof181;
+case 181:
        if ( (*p) == 67 )
-               goto st174;
+               goto st182;
        goto st0;
-st174:
+st182:
        if ( ++p == pe )
-               goto _test_eof174;
-case 174:
+               goto _test_eof182;
+case 182:
        if ( (*p) == 69 )
-               goto st175;
+               goto st183;
        goto st0;
-st175:
+st183:
        if ( ++p == pe )
-               goto _test_eof175;
-case 175:
+               goto _test_eof183;
+case 183:
        if ( (*p) == 32 )
-               goto tr207;
+               goto tr218;
        goto st0;
-tr319:
-#line 213 "http_parser.rl"
+tr339:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st176;
-st176:
+       goto st184;
+st184:
        if ( ++p == pe )
-               goto _test_eof176;
-case 176:
-#line 3832 "http_parser.c"
+               goto _test_eof184;
+case 184:
+#line 3854 "http_parser.c"
        if ( (*p) == 78 )
-               goto st177;
+               goto st185;
        goto st0;
-st177:
+st185:
        if ( ++p == pe )
-               goto _test_eof177;
-case 177:
+               goto _test_eof185;
+case 185:
        if ( (*p) == 76 )
-               goto st178;
+               goto st186;
        goto st0;
-st178:
+st186:
        if ( ++p == pe )
-               goto _test_eof178;
-case 178:
+               goto _test_eof186;
+case 186:
        if ( (*p) == 79 )
-               goto st179;
+               goto st187;
        goto st0;
-st179:
+st187:
        if ( ++p == pe )
-               goto _test_eof179;
-case 179:
+               goto _test_eof187;
+case 187:
        if ( (*p) == 67 )
-               goto st180;
+               goto st188;
        goto st0;
-st180:
+st188:
        if ( ++p == pe )
-               goto _test_eof180;
-case 180:
+               goto _test_eof188;
+case 188:
        if ( (*p) == 75 )
-               goto st181;
+               goto st189;
        goto st0;
-st181:
+st189:
        if ( ++p == pe )
-               goto _test_eof181;
-case 181:
+               goto _test_eof189;
+case 189:
        if ( (*p) == 32 )
-               goto tr213;
+               goto tr224;
        goto st0;
-tr232:
-       cs = 269;
-#line 203 "http_parser.rl"
+tr246:
+       cs = 283;
+#line 189 "http_parser.rl"
        {
     if(parser->on_headers_complete) {
       callback_return_value = parser->on_headers_complete(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-#line 282 "http_parser.rl"
+#line 262 "http_parser.rl"
        {
-    if (parser->transfer_encoding == HTTP_CHUNKED) {
+    if (parser->flags & CHUNKED) {
       cs = 2;
     } else {
-      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
-      parser->chunk_size = parser->content_length;
-      p += 1;  
+      /* this is pretty stupid. i'd prefer to combine this with
+       * skip_chunk_data */
+      if (parser->content_length < 0) {
+        /* If we didn't get a content length; if not keep-alive
+         * just read body until EOF */
+        if (!http_parser_should_keep_alive(parser)) {
+          parser->flags |= EAT_FOREVER;
+          parser->chunk_size = REMAINING;
+        } else {
+          /* Otherwise, if keep-alive, then assume the message
+           * has no body. */
+          parser->chunk_size = parser->content_length = 0;
+        }
+      } else {
+        parser->chunk_size = parser->content_length;
+      }
+      p += 1;
 
-      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      SKIP_BODY(MIN(REMAINING, parser->chunk_size));
 
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
 
       p--;
@@ -3902,1860 +3938,1878 @@ tr232:
     }
   }
        goto _again;
-st269:
+st283:
        if ( ++p == pe )
-               goto _test_eof269;
-case 269:
-#line 3910 "http_parser.c"
+               goto _test_eof283;
+case 283:
+#line 3946 "http_parser.c"
        if ( (*p) == 72 )
-               goto tr320;
+               goto tr340;
        goto st0;
-tr320:
-#line 213 "http_parser.rl"
+tr340:
+#line 199 "http_parser.rl"
        {
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
-       goto st182;
-st182:
+       goto st190;
+st190:
        if ( ++p == pe )
-               goto _test_eof182;
-case 182:
-#line 3930 "http_parser.c"
+               goto _test_eof190;
+case 190:
+#line 3966 "http_parser.c"
        if ( (*p) == 84 )
-               goto st183;
+               goto st191;
        goto st0;
-st183:
+st191:
        if ( ++p == pe )
-               goto _test_eof183;
-case 183:
+               goto _test_eof191;
+case 191:
        if ( (*p) == 84 )
-               goto st184;
+               goto st192;
        goto st0;
-st184:
+st192:
        if ( ++p == pe )
-               goto _test_eof184;
-case 184:
+               goto _test_eof192;
+case 192:
        if ( (*p) == 80 )
-               goto st185;
+               goto st193;
        goto st0;
-st185:
+st193:
        if ( ++p == pe )
-               goto _test_eof185;
-case 185:
+               goto _test_eof193;
+case 193:
        if ( (*p) == 47 )
-               goto st186;
+               goto st194;
        goto st0;
-st186:
+st194:
        if ( ++p == pe )
-               goto _test_eof186;
-case 186:
-       if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr218;
+               goto _test_eof194;
+case 194:
+       switch( (*p) ) {
+               case 48: goto st195;
+               case 49: goto st274;
+       }
+       if ( 50 <= (*p) && (*p) <= 57 )
+               goto st278;
        goto st0;
-tr218:
-#line 243 "http_parser.rl"
-       {
-    parser->version_major *= 10;
-    parser->version_major += *p - '0';
-  }
-       goto st187;
-st187:
+st195:
        if ( ++p == pe )
-               goto _test_eof187;
-case 187:
-#line 3973 "http_parser.c"
+               goto _test_eof195;
+case 195:
        if ( (*p) == 46 )
-               goto st188;
+               goto st196;
        goto st0;
-st188:
+st196:
        if ( ++p == pe )
-               goto _test_eof188;
-case 188:
-       if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr220;
+               goto _test_eof196;
+case 196:
+       if ( (*p) == 57 )
+               goto st273;
+       if ( 48 <= (*p) && (*p) <= 56 )
+               goto st197;
        goto st0;
-tr220:
-#line 248 "http_parser.rl"
-       {
-    parser->version_minor *= 10;
-    parser->version_minor += *p - '0';
-  }
-       goto st189;
-st189:
+st197:
        if ( ++p == pe )
-               goto _test_eof189;
-case 189:
-#line 3995 "http_parser.c"
+               goto _test_eof197;
+case 197:
        if ( (*p) == 32 )
-               goto st190;
+               goto st198;
        goto st0;
-st190:
+tr323:
+#line 231 "http_parser.rl"
+       { parser->version = HTTP_VERSION_09; }
+       goto st198;
+tr327:
+#line 230 "http_parser.rl"
+       { parser->version = HTTP_VERSION_10; }
+       goto st198;
+tr328:
+#line 229 "http_parser.rl"
+       { parser->version = HTTP_VERSION_11; }
+       goto st198;
+st198:
        if ( ++p == pe )
-               goto _test_eof190;
-case 190:
+               goto _test_eof198;
+case 198:
+#line 4041 "http_parser.c"
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr222;
+               goto tr236;
        goto st0;
-tr222:
-#line 232 "http_parser.rl"
+tr236:
+#line 219 "http_parser.rl"
        {
     parser->status_code *= 10;
     parser->status_code += *p - '0';
   }
-       goto st191;
-st191:
+       goto st199;
+st199:
        if ( ++p == pe )
-               goto _test_eof191;
-case 191:
-#line 4017 "http_parser.c"
+               goto _test_eof199;
+case 199:
+#line 4056 "http_parser.c"
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr223;
+               goto tr237;
        goto st0;
-tr223:
-#line 232 "http_parser.rl"
+tr237:
+#line 219 "http_parser.rl"
        {
     parser->status_code *= 10;
     parser->status_code += *p - '0';
   }
-       goto st192;
-st192:
+       goto st200;
+st200:
        if ( ++p == pe )
-               goto _test_eof192;
-case 192:
-#line 4032 "http_parser.c"
+               goto _test_eof200;
+case 200:
+#line 4071 "http_parser.c"
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr224;
+               goto tr238;
        goto st0;
-tr224:
-#line 232 "http_parser.rl"
+tr238:
+#line 219 "http_parser.rl"
        {
     parser->status_code *= 10;
     parser->status_code += *p - '0';
   }
-       goto st193;
-st193:
+       goto st201;
+st201:
        if ( ++p == pe )
-               goto _test_eof193;
-case 193:
-#line 4047 "http_parser.c"
+               goto _test_eof201;
+case 201:
+#line 4086 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto st194;
-               case 32: goto st265;
+               case 13: goto st202;
+               case 32: goto st272;
        }
        goto st0;
-tr236:
-#line 118 "http_parser.rl"
+tr250:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-#line 153 "http_parser.rl"
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st194;
-tr239:
-#line 153 "http_parser.rl"
+       goto st202;
+tr253:
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st194;
-tr258:
-#line 241 "http_parser.rl"
-       { parser->keep_alive = FALSE; }
-#line 153 "http_parser.rl"
+       goto st202;
+tr272:
+#line 227 "http_parser.rl"
+       { parser->keep_alive = 0; }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st194;
-tr268:
-#line 240 "http_parser.rl"
-       { parser->keep_alive = TRUE; }
-#line 153 "http_parser.rl"
+       goto st202;
+tr282:
+#line 226 "http_parser.rl"
+       { parser->keep_alive = 1; }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st194;
-tr309:
-#line 237 "http_parser.rl"
-       { parser->transfer_encoding = HTTP_IDENTITY; }
-#line 153 "http_parser.rl"
+       goto st202;
+tr322:
+#line 224 "http_parser.rl"
+       { parser->flags |= CHUNKED;  }
+#line 159 "http_parser.rl"
        {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
-       goto st194;
-st194:
+       goto st202;
+st202:
        if ( ++p == pe )
-               goto _test_eof194;
-case 194:
-#line 4128 "http_parser.c"
+               goto _test_eof202;
+case 202:
+#line 4147 "http_parser.c"
        if ( (*p) == 10 )
-               goto st195;
+               goto st203;
        goto st0;
-st195:
+st203:
        if ( ++p == pe )
-               goto _test_eof195;
-case 195:
+               goto _test_eof203;
+case 203:
        switch( (*p) ) {
-               case 13: goto st196;
-               case 33: goto tr229;
-               case 67: goto tr230;
-               case 84: goto tr231;
-               case 99: goto tr230;
-               case 116: goto tr231;
-               case 124: goto tr229;
-               case 126: goto tr229;
+               case 13: goto st204;
+               case 33: goto tr243;
+               case 67: goto tr244;
+               case 84: goto tr245;
+               case 99: goto tr244;
+               case 116: goto tr245;
+               case 124: goto tr243;
+               case 126: goto tr243;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto tr229;
+                               goto tr243;
                } else if ( (*p) >= 35 )
-                       goto tr229;
+                       goto tr243;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto tr229;
+                               goto tr243;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto tr229;
+                               goto tr243;
                } else
-                       goto tr229;
+                       goto tr243;
        } else
-               goto tr229;
+               goto tr243;
        goto st0;
-st196:
+st204:
        if ( ++p == pe )
-               goto _test_eof196;
-case 196:
+               goto _test_eof204;
+case 204:
        if ( (*p) == 10 )
-               goto tr232;
+               goto tr246;
        goto st0;
-tr229:
-#line 113 "http_parser.rl"
+tr243:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st197;
-st197:
+       goto st205;
+st205:
        if ( ++p == pe )
-               goto _test_eof197;
-case 197:
-#line 4182 "http_parser.c"
+               goto _test_eof205;
+case 205:
+#line 4201 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-tr234:
-#line 143 "http_parser.rl"
+tr248:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st198;
-st198:
+       goto st206;
+st206:
        if ( ++p == pe )
-               goto _test_eof198;
-case 198:
-#line 4223 "http_parser.c"
+               goto _test_eof206;
+case 206:
+#line 4238 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr236;
-               case 32: goto st198;
+               case 13: goto tr250;
+               case 32: goto st206;
        }
-       goto tr235;
-tr235:
-#line 118 "http_parser.rl"
+       goto tr249;
+tr249:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st199;
-st199:
+       goto st207;
+st207:
        if ( ++p == pe )
-               goto _test_eof199;
-case 199:
-#line 4240 "http_parser.c"
+               goto _test_eof207;
+case 207:
+#line 4255 "http_parser.c"
        if ( (*p) == 13 )
-               goto tr239;
-       goto st199;
-tr230:
-#line 113 "http_parser.rl"
+               goto tr253;
+       goto st207;
+tr244:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st200;
-st200:
+       goto st208;
+st208:
        if ( ++p == pe )
-               goto _test_eof200;
-case 200:
-#line 4255 "http_parser.c"
+               goto _test_eof208;
+case 208:
+#line 4270 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 79: goto st201;
-               case 111: goto st201;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 79: goto st209;
+               case 111: goto st209;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st201:
+st209:
        if ( ++p == pe )
-               goto _test_eof201;
-case 201:
+               goto _test_eof209;
+case 209:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st202;
-               case 110: goto st202;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st210;
+               case 110: goto st210;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st202:
+st210:
        if ( ++p == pe )
-               goto _test_eof202;
-case 202:
+               goto _test_eof210;
+case 210:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st203;
-               case 84: goto st226;
-               case 110: goto st203;
-               case 116: goto st226;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st211;
+               case 84: goto st234;
+               case 110: goto st211;
+               case 116: goto st234;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st203:
+st211:
        if ( ++p == pe )
-               goto _test_eof203;
-case 203:
+               goto _test_eof211;
+case 211:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 69: goto st204;
-               case 101: goto st204;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 69: goto st212;
+               case 101: goto st212;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st204:
+st212:
        if ( ++p == pe )
-               goto _test_eof204;
-case 204:
+               goto _test_eof212;
+case 212:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 67: goto st205;
-               case 99: goto st205;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 67: goto st213;
+               case 99: goto st213;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st205:
+st213:
        if ( ++p == pe )
-               goto _test_eof205;
-case 205:
+               goto _test_eof213;
+case 213:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 84: goto st206;
-               case 116: goto st206;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 84: goto st214;
+               case 116: goto st214;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st206:
+st214:
        if ( ++p == pe )
-               goto _test_eof206;
-case 206:
+               goto _test_eof214;
+case 214:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 73: goto st207;
-               case 105: goto st207;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 73: goto st215;
+               case 105: goto st215;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st207:
+st215:
        if ( ++p == pe )
-               goto _test_eof207;
-case 207:
+               goto _test_eof215;
+case 215:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 79: goto st208;
-               case 111: goto st208;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 79: goto st216;
+               case 111: goto st216;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st208:
+st216:
        if ( ++p == pe )
-               goto _test_eof208;
-case 208:
+               goto _test_eof216;
+case 216:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st209;
-               case 110: goto st209;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st217;
+               case 110: goto st217;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st209:
+st217:
        if ( ++p == pe )
-               goto _test_eof209;
-case 209:
+               goto _test_eof217;
+case 217:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr250;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr264;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-tr250:
-#line 143 "http_parser.rl"
+tr264:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st210;
-st210:
+       goto st218;
+st218:
        if ( ++p == pe )
-               goto _test_eof210;
-case 210:
-#line 4568 "http_parser.c"
-       switch( (*p) ) {
-               case 13: goto tr236;
-               case 32: goto st210;
-               case 67: goto tr252;
-               case 75: goto tr253;
-               case 99: goto tr252;
-               case 107: goto tr253;
-       }
-       goto tr235;
-tr252:
-#line 118 "http_parser.rl"
+               goto _test_eof218;
+case 218:
+#line 4579 "http_parser.c"
+       switch( (*p) ) {
+               case 13: goto tr250;
+               case 32: goto st218;
+               case 67: goto tr266;
+               case 75: goto tr267;
+               case 99: goto tr266;
+               case 107: goto tr267;
+       }
+       goto tr249;
+tr266:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st211;
-st211:
+       goto st219;
+st219:
        if ( ++p == pe )
-               goto _test_eof211;
-case 211:
-#line 4589 "http_parser.c"
+               goto _test_eof219;
+case 219:
+#line 4600 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 76: goto st212;
-               case 108: goto st212;
+               case 13: goto tr253;
+               case 76: goto st220;
+               case 108: goto st220;
        }
-       goto st199;
-st212:
+       goto st207;
+st220:
        if ( ++p == pe )
-               goto _test_eof212;
-case 212:
+               goto _test_eof220;
+case 220:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 79: goto st213;
-               case 111: goto st213;
+               case 13: goto tr253;
+               case 79: goto st221;
+               case 111: goto st221;
        }
-       goto st199;
-st213:
+       goto st207;
+st221:
        if ( ++p == pe )
-               goto _test_eof213;
-case 213:
+               goto _test_eof221;
+case 221:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 83: goto st214;
-               case 115: goto st214;
+               case 13: goto tr253;
+               case 83: goto st222;
+               case 115: goto st222;
        }
-       goto st199;
-st214:
+       goto st207;
+st222:
        if ( ++p == pe )
-               goto _test_eof214;
-case 214:
+               goto _test_eof222;
+case 222:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 69: goto st215;
-               case 101: goto st215;
+               case 13: goto tr253;
+               case 69: goto st223;
+               case 101: goto st223;
        }
-       goto st199;
-st215:
+       goto st207;
+st223:
        if ( ++p == pe )
-               goto _test_eof215;
-case 215:
+               goto _test_eof223;
+case 223:
        if ( (*p) == 13 )
-               goto tr258;
-       goto st199;
-tr253:
-#line 118 "http_parser.rl"
+               goto tr272;
+       goto st207;
+tr267:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st216;
-st216:
+       goto st224;
+st224:
        if ( ++p == pe )
-               goto _test_eof216;
-case 216:
-#line 4644 "http_parser.c"
+               goto _test_eof224;
+case 224:
+#line 4655 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 69: goto st217;
-               case 101: goto st217;
+               case 13: goto tr253;
+               case 69: goto st225;
+               case 101: goto st225;
        }
-       goto st199;
-st217:
+       goto st207;
+st225:
        if ( ++p == pe )
-               goto _test_eof217;
-case 217:
+               goto _test_eof225;
+case 225:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 69: goto st218;
-               case 101: goto st218;
+               case 13: goto tr253;
+               case 69: goto st226;
+               case 101: goto st226;
        }
-       goto st199;
-st218:
+       goto st207;
+st226:
        if ( ++p == pe )
-               goto _test_eof218;
-case 218:
+               goto _test_eof226;
+case 226:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 80: goto st219;
-               case 112: goto st219;
+               case 13: goto tr253;
+               case 80: goto st227;
+               case 112: goto st227;
        }
-       goto st199;
-st219:
+       goto st207;
+st227:
        if ( ++p == pe )
-               goto _test_eof219;
-case 219:
+               goto _test_eof227;
+case 227:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 45: goto st220;
+               case 13: goto tr253;
+               case 45: goto st228;
        }
-       goto st199;
-st220:
+       goto st207;
+st228:
        if ( ++p == pe )
-               goto _test_eof220;
-case 220:
+               goto _test_eof228;
+case 228:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 65: goto st221;
-               case 97: goto st221;
+               case 13: goto tr253;
+               case 65: goto st229;
+               case 97: goto st229;
        }
-       goto st199;
-st221:
+       goto st207;
+st229:
        if ( ++p == pe )
-               goto _test_eof221;
-case 221:
+               goto _test_eof229;
+case 229:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 76: goto st222;
-               case 108: goto st222;
+               case 13: goto tr253;
+               case 76: goto st230;
+               case 108: goto st230;
        }
-       goto st199;
-st222:
+       goto st207;
+st230:
        if ( ++p == pe )
-               goto _test_eof222;
-case 222:
+               goto _test_eof230;
+case 230:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 73: goto st223;
-               case 105: goto st223;
+               case 13: goto tr253;
+               case 73: goto st231;
+               case 105: goto st231;
        }
-       goto st199;
-st223:
+       goto st207;
+st231:
        if ( ++p == pe )
-               goto _test_eof223;
-case 223:
+               goto _test_eof231;
+case 231:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 86: goto st224;
-               case 118: goto st224;
+               case 13: goto tr253;
+               case 86: goto st232;
+               case 118: goto st232;
        }
-       goto st199;
-st224:
+       goto st207;
+st232:
        if ( ++p == pe )
-               goto _test_eof224;
-case 224:
+               goto _test_eof232;
+case 232:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 69: goto st225;
-               case 101: goto st225;
+               case 13: goto tr253;
+               case 69: goto st233;
+               case 101: goto st233;
        }
-       goto st199;
-st225:
+       goto st207;
+st233:
        if ( ++p == pe )
-               goto _test_eof225;
-case 225:
+               goto _test_eof233;
+case 233:
        if ( (*p) == 13 )
-               goto tr268;
-       goto st199;
-st226:
+               goto tr282;
+       goto st207;
+st234:
        if ( ++p == pe )
-               goto _test_eof226;
-case 226:
+               goto _test_eof234;
+case 234:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 69: goto st227;
-               case 101: goto st227;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 69: goto st235;
+               case 101: goto st235;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st227:
+st235:
        if ( ++p == pe )
-               goto _test_eof227;
-case 227:
+               goto _test_eof235;
+case 235:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st228;
-               case 110: goto st228;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st236;
+               case 110: goto st236;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st228:
+st236:
        if ( ++p == pe )
-               goto _test_eof228;
-case 228:
+               goto _test_eof236;
+case 236:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 84: goto st229;
-               case 116: goto st229;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 84: goto st237;
+               case 116: goto st237;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st229:
+st237:
        if ( ++p == pe )
-               goto _test_eof229;
-case 229:
+               goto _test_eof237;
+case 237:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 45: goto st230;
-               case 46: goto st197;
-               case 58: goto tr234;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 45: goto st238;
+               case 46: goto st205;
+               case 58: goto tr248;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 48 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 57 ) {
                if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 65 )
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st230:
+st238:
        if ( ++p == pe )
-               goto _test_eof230;
-case 230:
+               goto _test_eof238;
+case 238:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 76: goto st231;
-               case 108: goto st231;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 76: goto st239;
+               case 108: goto st239;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st231:
+st239:
        if ( ++p == pe )
-               goto _test_eof231;
-case 231:
+               goto _test_eof239;
+case 239:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 69: goto st232;
-               case 101: goto st232;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 69: goto st240;
+               case 101: goto st240;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st232:
+st240:
        if ( ++p == pe )
-               goto _test_eof232;
-case 232:
+               goto _test_eof240;
+case 240:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st233;
-               case 110: goto st233;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st241;
+               case 110: goto st241;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st233:
+st241:
        if ( ++p == pe )
-               goto _test_eof233;
-case 233:
+               goto _test_eof241;
+case 241:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 71: goto st234;
-               case 103: goto st234;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 71: goto st242;
+               case 103: goto st242;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st234:
+st242:
        if ( ++p == pe )
-               goto _test_eof234;
-case 234:
+               goto _test_eof242;
+case 242:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 84: goto st235;
-               case 116: goto st235;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 84: goto st243;
+               case 116: goto st243;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st235:
+st243:
        if ( ++p == pe )
-               goto _test_eof235;
-case 235:
+               goto _test_eof243;
+case 243:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 72: goto st236;
-               case 104: goto st236;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 72: goto st244;
+               case 104: goto st244;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st236:
+st244:
        if ( ++p == pe )
-               goto _test_eof236;
-case 236:
+               goto _test_eof244;
+case 244:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr279;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr293;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-tr279:
-#line 143 "http_parser.rl"
+tr293:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st237;
-st237:
+       goto st245;
+st245:
        if ( ++p == pe )
-               goto _test_eof237;
-case 237:
-#line 5078 "http_parser.c"
+               goto _test_eof245;
+case 245:
+#line 5085 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr236;
-               case 32: goto st237;
+               case 13: goto tr250;
+               case 32: goto st245;
        }
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr281;
-       goto tr235;
-tr281:
-#line 223 "http_parser.rl"
+               goto tr295;
+       goto tr249;
+tr295:
+#line 209 "http_parser.rl"
        {
+    if (parser->content_length == -1) parser->content_length = 0;
     if (parser->content_length > INT_MAX) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
     parser->content_length *= 10;
     parser->content_length += *p - '0';
   }
-#line 118 "http_parser.rl"
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st238;
-tr282:
-#line 223 "http_parser.rl"
+       goto st246;
+tr296:
+#line 209 "http_parser.rl"
        {
+    if (parser->content_length == -1) parser->content_length = 0;
     if (parser->content_length > INT_MAX) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
     parser->content_length *= 10;
     parser->content_length += *p - '0';
   }
-       goto st238;
-st238:
+       goto st246;
+st246:
        if ( ++p == pe )
-               goto _test_eof238;
-case 238:
-#line 5117 "http_parser.c"
+               goto _test_eof246;
+case 246:
+#line 5126 "http_parser.c"
        if ( (*p) == 13 )
-               goto tr239;
+               goto tr253;
        if ( 48 <= (*p) && (*p) <= 57 )
-               goto tr282;
-       goto st199;
-tr231:
-#line 113 "http_parser.rl"
+               goto tr296;
+       goto st207;
+tr245:
+#line 123 "http_parser.rl"
        {
     parser->header_field_mark = p;
     parser->header_field_size = 0;
   }
-       goto st239;
-st239:
+       goto st247;
+st247:
        if ( ++p == pe )
-               goto _test_eof239;
-case 239:
-#line 5134 "http_parser.c"
+               goto _test_eof247;
+case 247:
+#line 5143 "http_parser.c"
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 82: goto st240;
-               case 114: goto st240;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 82: goto st248;
+               case 114: goto st248;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st240:
+st248:
        if ( ++p == pe )
-               goto _test_eof240;
-case 240:
+               goto _test_eof248;
+case 248:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 65: goto st241;
-               case 97: goto st241;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 65: goto st249;
+               case 97: goto st249;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 66 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st241:
+st249:
        if ( ++p == pe )
-               goto _test_eof241;
-case 241:
+               goto _test_eof249;
+case 249:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st242;
-               case 110: goto st242;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st250;
+               case 110: goto st250;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st242:
+st250:
        if ( ++p == pe )
-               goto _test_eof242;
-case 242:
+               goto _test_eof250;
+case 250:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 83: goto st243;
-               case 115: goto st243;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 83: goto st251;
+               case 115: goto st251;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st243:
+st251:
        if ( ++p == pe )
-               goto _test_eof243;
-case 243:
+               goto _test_eof251;
+case 251:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 70: goto st244;
-               case 102: goto st244;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 70: goto st252;
+               case 102: goto st252;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st244:
+st252:
        if ( ++p == pe )
-               goto _test_eof244;
-case 244:
+               goto _test_eof252;
+case 252:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 69: goto st245;
-               case 101: goto st245;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 69: goto st253;
+               case 101: goto st253;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st245:
+st253:
        if ( ++p == pe )
-               goto _test_eof245;
-case 245:
+               goto _test_eof253;
+case 253:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 82: goto st246;
-               case 114: goto st246;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 82: goto st254;
+               case 114: goto st254;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st246:
+st254:
        if ( ++p == pe )
-               goto _test_eof246;
-case 246:
+               goto _test_eof254;
+case 254:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 45: goto st247;
-               case 46: goto st197;
-               case 58: goto tr234;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 45: goto st255;
+               case 46: goto st205;
+               case 58: goto tr248;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 48 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 57 ) {
                if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 65 )
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st247:
+st255:
        if ( ++p == pe )
-               goto _test_eof247;
-case 247:
+               goto _test_eof255;
+case 255:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 69: goto st248;
-               case 101: goto st248;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 69: goto st256;
+               case 101: goto st256;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st248:
+st256:
        if ( ++p == pe )
-               goto _test_eof248;
-case 248:
+               goto _test_eof256;
+case 256:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st249;
-               case 110: goto st249;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st257;
+               case 110: goto st257;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st249:
+st257:
        if ( ++p == pe )
-               goto _test_eof249;
-case 249:
+               goto _test_eof257;
+case 257:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 67: goto st250;
-               case 99: goto st250;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 67: goto st258;
+               case 99: goto st258;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st250:
+st258:
        if ( ++p == pe )
-               goto _test_eof250;
-case 250:
+               goto _test_eof258;
+case 258:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 79: goto st251;
-               case 111: goto st251;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 79: goto st259;
+               case 111: goto st259;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st251:
+st259:
        if ( ++p == pe )
-               goto _test_eof251;
-case 251:
+               goto _test_eof259;
+case 259:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 68: goto st252;
-               case 100: goto st252;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 68: goto st260;
+               case 100: goto st260;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st252:
+st260:
        if ( ++p == pe )
-               goto _test_eof252;
-case 252:
+               goto _test_eof260;
+case 260:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 73: goto st253;
-               case 105: goto st253;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 73: goto st261;
+               case 105: goto st261;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st253:
+st261:
        if ( ++p == pe )
-               goto _test_eof253;
-case 253:
+               goto _test_eof261;
+case 261:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 78: goto st254;
-               case 110: goto st254;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 78: goto st262;
+               case 110: goto st262;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st254:
+st262:
        if ( ++p == pe )
-               goto _test_eof254;
-case 254:
+               goto _test_eof262;
+case 262:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr234;
-               case 71: goto st255;
-               case 103: goto st255;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr248;
+               case 71: goto st263;
+               case 103: goto st263;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-st255:
+st263:
        if ( ++p == pe )
-               goto _test_eof255;
-case 255:
+               goto _test_eof263;
+case 263:
        switch( (*p) ) {
-               case 33: goto st197;
-               case 58: goto tr299;
-               case 124: goto st197;
-               case 126: goto st197;
+               case 33: goto st205;
+               case 58: goto tr313;
+               case 124: goto st205;
+               case 126: goto st205;
        }
        if ( (*p) < 45 ) {
                if ( (*p) > 39 ) {
                        if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) >= 35 )
-                       goto st197;
+                       goto st205;
        } else if ( (*p) > 46 ) {
                if ( (*p) < 65 ) {
                        if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st197;
+                               goto st205;
                } else if ( (*p) > 90 ) {
                        if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st197;
+                               goto st205;
                } else
-                       goto st197;
+                       goto st205;
        } else
-               goto st197;
+               goto st205;
        goto st0;
-tr299:
-#line 238 "http_parser.rl"
-       { parser->transfer_encoding = HTTP_CHUNKED;  }
-#line 143 "http_parser.rl"
+tr313:
+#line 153 "http_parser.rl"
        {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
-       goto st256;
-st256:
+       goto st264;
+st264:
        if ( ++p == pe )
-               goto _test_eof256;
-case 256:
-#line 5654 "http_parser.c"
+               goto _test_eof264;
+case 264:
+#line 5657 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr236;
-               case 32: goto st256;
-               case 105: goto tr301;
+               case 13: goto tr250;
+               case 32: goto st264;
+               case 67: goto tr315;
+               case 99: goto tr315;
        }
-       goto tr235;
-tr301:
-#line 118 "http_parser.rl"
+       goto tr249;
+tr315:
+#line 128 "http_parser.rl"
        {
     parser->header_value_mark = p;
     parser->header_value_size = 0;
   }
-       goto st257;
-st257:
-       if ( ++p == pe )
-               goto _test_eof257;
-case 257:
-#line 5672 "http_parser.c"
-       switch( (*p) ) {
-               case 13: goto tr239;
-               case 100: goto st258;
-       }
-       goto st199;
-st258:
+       goto st265;
+st265:
        if ( ++p == pe )
-               goto _test_eof258;
-case 258:
+               goto _test_eof265;
+case 265:
+#line 5676 "http_parser.c"
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 101: goto st259;
+               case 13: goto tr253;
+               case 72: goto st266;
+               case 104: goto st266;
        }
-       goto st199;
-st259:
+       goto st207;
+st266:
        if ( ++p == pe )
-               goto _test_eof259;
-case 259:
+               goto _test_eof266;
+case 266:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 110: goto st260;
+               case 13: goto tr253;
+               case 85: goto st267;
+               case 117: goto st267;
        }
-       goto st199;
-st260:
+       goto st207;
+st267:
        if ( ++p == pe )
-               goto _test_eof260;
-case 260:
+               goto _test_eof267;
+case 267:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 116: goto st261;
+               case 13: goto tr253;
+               case 78: goto st268;
+               case 110: goto st268;
        }
-       goto st199;
-st261:
+       goto st207;
+st268:
        if ( ++p == pe )
-               goto _test_eof261;
-case 261:
+               goto _test_eof268;
+case 268:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 105: goto st262;
+               case 13: goto tr253;
+               case 75: goto st269;
+               case 107: goto st269;
        }
-       goto st199;
-st262:
+       goto st207;
+st269:
        if ( ++p == pe )
-               goto _test_eof262;
-case 262:
+               goto _test_eof269;
+case 269:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 116: goto st263;
+               case 13: goto tr253;
+               case 69: goto st270;
+               case 101: goto st270;
        }
-       goto st199;
-st263:
+       goto st207;
+st270:
        if ( ++p == pe )
-               goto _test_eof263;
-case 263:
+               goto _test_eof270;
+case 270:
        switch( (*p) ) {
-               case 13: goto tr239;
-               case 121: goto st264;
+               case 13: goto tr253;
+               case 68: goto st271;
+               case 100: goto st271;
        }
-       goto st199;
-st264:
+       goto st207;
+st271:
        if ( ++p == pe )
-               goto _test_eof264;
-case 264:
+               goto _test_eof271;
+case 271:
        if ( (*p) == 13 )
-               goto tr309;
-       goto st199;
-st265:
+               goto tr322;
+       goto st207;
+st272:
        if ( ++p == pe )
-               goto _test_eof265;
-case 265:
+               goto _test_eof272;
+case 272:
        if ( (*p) == 13 )
-               goto st194;
+               goto st202;
        if ( (*p) > 9 ) {
                if ( 11 <= (*p) )
-                       goto st265;
+                       goto st272;
        } else if ( (*p) >= 0 )
-               goto st265;
+               goto st272;
+       goto st0;
+st273:
+       if ( ++p == pe )
+               goto _test_eof273;
+case 273:
+       if ( (*p) == 32 )
+               goto tr323;
+       goto st0;
+st274:
+       if ( ++p == pe )
+               goto _test_eof274;
+case 274:
+       if ( (*p) == 46 )
+               goto st275;
+       goto st0;
+st275:
+       if ( ++p == pe )
+               goto _test_eof275;
+case 275:
+       switch( (*p) ) {
+               case 48: goto st276;
+               case 49: goto st277;
+       }
+       if ( 50 <= (*p) && (*p) <= 57 )
+               goto st197;
+       goto st0;
+st276:
+       if ( ++p == pe )
+               goto _test_eof276;
+case 276:
+       if ( (*p) == 32 )
+               goto tr327;
+       goto st0;
+st277:
+       if ( ++p == pe )
+               goto _test_eof277;
+case 277:
+       if ( (*p) == 32 )
+               goto tr328;
+       goto st0;
+st278:
+       if ( ++p == pe )
+               goto _test_eof278;
+case 278:
+       if ( (*p) == 46 )
+               goto st279;
+       goto st0;
+st279:
+       if ( ++p == pe )
+               goto _test_eof279;
+case 279:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st197;
        goto st0;
        }
        _test_eof1: cs = 1; goto _test_eof; 
-       _test_eof266: cs = 266; goto _test_eof; 
+       _test_eof280: cs = 280; goto _test_eof; 
        _test_eof2: cs = 2; goto _test_eof; 
        _test_eof3: cs = 3; goto _test_eof; 
        _test_eof4: cs = 4; goto _test_eof; 
        _test_eof5: cs = 5; goto _test_eof; 
        _test_eof6: cs = 6; goto _test_eof; 
-       _test_eof267: cs = 267; goto _test_eof; 
+       _test_eof281: cs = 281; goto _test_eof; 
        _test_eof7: cs = 7; goto _test_eof; 
        _test_eof8: cs = 8; goto _test_eof; 
        _test_eof9: cs = 9; goto _test_eof; 
@@ -5769,9 +5823,9 @@ case 265:
        _test_eof17: cs = 17; goto _test_eof; 
        _test_eof18: cs = 18; goto _test_eof; 
        _test_eof19: cs = 19; goto _test_eof; 
-       _test_eof268: cs = 268; goto _test_eof; 
        _test_eof20: cs = 20; goto _test_eof; 
        _test_eof21: cs = 21; goto _test_eof; 
+       _test_eof282: cs = 282; goto _test_eof; 
        _test_eof22: cs = 22; goto _test_eof; 
        _test_eof23: cs = 23; goto _test_eof; 
        _test_eof24: cs = 24; goto _test_eof; 
@@ -5932,7 +5986,6 @@ case 265:
        _test_eof179: cs = 179; goto _test_eof; 
        _test_eof180: cs = 180; goto _test_eof; 
        _test_eof181: cs = 181; goto _test_eof; 
-       _test_eof269: cs = 269; goto _test_eof; 
        _test_eof182: cs = 182; goto _test_eof; 
        _test_eof183: cs = 183; goto _test_eof; 
        _test_eof184: cs = 184; goto _test_eof; 
@@ -5941,6 +5994,7 @@ case 265:
        _test_eof187: cs = 187; goto _test_eof; 
        _test_eof188: cs = 188; goto _test_eof; 
        _test_eof189: cs = 189; goto _test_eof; 
+       _test_eof283: cs = 283; goto _test_eof; 
        _test_eof190: cs = 190; goto _test_eof; 
        _test_eof191: cs = 191; goto _test_eof; 
        _test_eof192: cs = 192; goto _test_eof; 
@@ -6017,11 +6071,25 @@ case 265:
        _test_eof263: cs = 263; goto _test_eof; 
        _test_eof264: cs = 264; goto _test_eof; 
        _test_eof265: cs = 265; goto _test_eof; 
+       _test_eof266: cs = 266; goto _test_eof; 
+       _test_eof267: cs = 267; goto _test_eof; 
+       _test_eof268: cs = 268; goto _test_eof; 
+       _test_eof269: cs = 269; goto _test_eof; 
+       _test_eof270: cs = 270; goto _test_eof; 
+       _test_eof271: cs = 271; goto _test_eof; 
+       _test_eof272: cs = 272; goto _test_eof; 
+       _test_eof273: cs = 273; goto _test_eof; 
+       _test_eof274: cs = 274; goto _test_eof; 
+       _test_eof275: cs = 275; goto _test_eof; 
+       _test_eof276: cs = 276; goto _test_eof; 
+       _test_eof277: cs = 277; goto _test_eof; 
+       _test_eof278: cs = 278; goto _test_eof; 
+       _test_eof279: cs = 279; goto _test_eof; 
 
        _test_eof: {}
        _out: {}
        }
-#line 469 "http_parser.rl"
+#line 482 "http_parser.rl"
 
   parser->cs = cs;
 
@@ -6033,26 +6101,11 @@ case 265:
   CALLBACK(uri);
 
   assert(p <= pe && "buffer overflow after parsing execute");
-  return(p - buffer);
 }
 
 int
-http_parser_has_error (http_parser *parser) 
+http_parser_has_error (http_parser *parser)
 {
-  if (parser->error) return TRUE;
+  if (parser->flags & ERROR) return 1;
   return parser->cs == http_parser_error;
 }
-
-int
-http_parser_should_keep_alive (http_parser *parser)
-{
-  if (parser->keep_alive == -1)
-    if (parser->version_major == 1)
-      return (parser->version_minor != 0);
-    else if (parser->version_major == 0)
-      return FALSE;
-    else
-      return TRUE;
-  else
-    return parser->keep_alive;
-}
index 9b699dc..4787a65 100644 (file)
@@ -2,7 +2,7 @@
  * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
  *
  * All rights reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #ifndef http_parser_h
 #define http_parser_h
 #ifdef __cplusplus
 extern "C" {
-#endif 
+#endif
 
-#include <sys/types.h> 
+#ifdef _MSC_VER
+#  include <stddef.h>
+#endif
+#include <sys/types.h>
 
 typedef struct http_parser http_parser;
 
 /* Callbacks should return non-zero to indicate an error. The parse will
- * then halt execution. 
- * 
+ * then halt execution.
+ *
  * http_data_cb does not return data chunks. It will be call arbitrarally
  * many times for each string. E.G. you might get 10 callbacks for "on_path"
  * each providing just a few characters more data.
@@ -58,60 +61,42 @@ typedef int (*http_cb) (http_parser*);
 #define HTTP_TRACE      0x1000
 #define HTTP_UNLOCK     0x2000
 
-/* Transfer Encodings */
-#define HTTP_IDENTITY   0x01
-#define HTTP_CHUNKED    0x02
-
 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE };
 
+#define HTTP_VERSION_OTHER 0x00
+#define HTTP_VERSION_11    0x01
+#define HTTP_VERSION_10    0x02
+#define HTTP_VERSION_09    0x04
+
 struct http_parser {
   /** PRIVATE **/
   int cs;
   enum http_parser_type type;
 
   size_t chunk_size;
-
-  /**
-    XXX
-    do this so no other code has to change, but make the field only 1 byte wide
-    instead of 2 (on x86/x86_64).
-
-    doing this not only shrinks the sizeof this struct by a byte but it ALSO
-    makes wrapping this in FFI way easier.
-   */
-  union {
-    struct {
-      unsigned eating:1;
-      unsigned error:1;
-    };
-    struct {
-      unsigned char _flags;
-    };
-  };
+  char flags;
 
   size_t body_read;
 
-  const char *header_field_mark; 
-  size_t      header_field_size; 
-  const char *header_value_mark; 
-  size_t      header_value_size; 
-  const char *query_string_mark; 
-  size_t      query_string_size; 
-  const char *path_mark; 
-  size_t      path_size; 
-  const char *uri_mark; 
-  size_t      uri_size; 
-  const char *fragment_mark; 
-  size_t      fragment_size; 
+  const char *header_field_mark;
+  size_t      header_field_size;
+  const char *header_value_mark;
+  size_t      header_value_size;
+  const char *query_string_mark;
+  size_t      query_string_size;
+  const char *path_mark;
+  size_t      path_size;
+  const char *uri_mark;
+  size_t      uri_size;
+  const char *fragment_mark;
+  size_t      fragment_size;
 
   /** READ-ONLY **/
   unsigned short status_code; /* responses only */
   unsigned short method;      /* requests only */
-  short transfer_encoding;
-  unsigned short version_major;
-  unsigned short version_minor;
+  short version;
   short keep_alive;
-  size_t content_length;
+  ssize_t content_length;
 
   /** PUBLIC **/
   void *data; /* A pointer to get hook to the "connection" or "socket" object */
@@ -134,17 +119,23 @@ struct http_parser {
 };
 
 /* Initializes an http_parser structure.  The second argument specifies if
- * it will be parsing requests or responses. 
+ * it will be parsing requests or responses.
  */
 void http_parser_init (http_parser *parser, enum http_parser_type);
 
-size_t http_parser_execute (http_parser *parser, const char *data, size_t len);
+void http_parser_execute (http_parser *parser, const char *data, size_t len);
 
 int http_parser_has_error (http_parser *parser);
 
-int http_parser_should_keep_alive (http_parser *parser);
+static inline int
+http_parser_should_keep_alive (http_parser *parser)
+{
+  if (parser->keep_alive == -1) return (parser->version == HTTP_VERSION_11);
+  return parser->keep_alive;
+}
+
 
 #ifdef __cplusplus
 }
-#endif 
+#endif
 #endif
index bf2da13..e9d014a 100644 (file)
@@ -2,7 +2,7 @@
  * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
  *
  * All rights reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "http_parser.h"
 #include <limits.h>
 #include <assert.h>
 
+/* parser->flags */
+#define EATING      0x01
+#define ERROR       0x02
+#define CHUNKED     0x04
+#define EAT_FOREVER 0x10
+
 static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
@@ -35,12 +41,14 @@ static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                      };
-#define TRUE 1
-#define FALSE 0
-#define MIN(a,b) (a < b ? a : b)
-#define NULL (void*)(0)
 
-#define MAX_FIELD_SIZE 80*1024
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#undef NULL
+#define NULL ((void*)(0))
+
+#define MAX_FIELD_SIZE (80*1024)
 
 #define REMAINING (unsigned long)(pe - p)
 #define CALLBACK(FOR)                                                \
@@ -48,34 +56,36 @@ do {                                                                 \
   if (parser->FOR##_mark) {                                          \
     parser->FOR##_size += p - parser->FOR##_mark;                    \
     if (parser->FOR##_size > MAX_FIELD_SIZE) {                       \
-      parser->error = TRUE;                                          \
-      return 0;                                                      \
+      parser->flags |= ERROR;                                        \
+      return;                                                        \
     }                                                                \
     if (parser->on_##FOR) {                                          \
       callback_return_value = parser->on_##FOR(parser,               \
         parser->FOR##_mark,                                          \
         p - parser->FOR##_mark);                                     \
     }                                                                \
+    if (callback_return_value != 0) {                                \
+      parser->flags |= ERROR;                                        \
+      return;                                                        \
+    }                                                                \
   }                                                                  \
 } while(0)
 
 #define RESET_PARSER(parser)                                         \
-    parser->chunk_size = 0;                                          \
-    parser->eating = 0;                                              \
-    parser->header_field_mark = NULL;                                \
-    parser->header_value_mark = NULL;                                \
-    parser->query_string_mark = NULL;                                \
-    parser->path_mark = NULL;                                        \
-    parser->uri_mark = NULL;                                         \
-    parser->fragment_mark = NULL;                                    \
-    parser->status_code = 0;                                         \
-    parser->method = 0;                                              \
-    parser->transfer_encoding = HTTP_IDENTITY;                       \
-    parser->version_major = 0;                                       \
-    parser->version_minor = 0;                                       \
-    parser->keep_alive = -1;                                         \
-    parser->content_length = 0;                                      \
-    parser->body_read = 0; 
+  parser->chunk_size = 0;                                            \
+  parser->flags = 0;                                                 \
+  parser->header_field_mark = NULL;                                  \
+  parser->header_value_mark = NULL;                                  \
+  parser->query_string_mark = NULL;                                  \
+  parser->path_mark = NULL;                                          \
+  parser->uri_mark = NULL;                                           \
+  parser->fragment_mark = NULL;                                      \
+  parser->status_code = 0;                                           \
+  parser->method = 0;                                                \
+  parser->version = HTTP_VERSION_OTHER;                              \
+  parser->keep_alive = -1;                                           \
+  parser->content_length = -1;                                       \
+  parser->body_read = 0
 
 #define END_REQUEST                                                  \
 do {                                                                 \
@@ -97,12 +107,12 @@ do {                                                                 \
     parser->body_read += tmp;                                        \
     parser->chunk_size -= tmp;                                       \
     if (0 == parser->chunk_size) {                                   \
-      parser->eating = FALSE;                                        \
-      if (parser->transfer_encoding == HTTP_IDENTITY) {              \
+      parser->flags &= ~EATING;                                      \
+      if (!(parser->flags & CHUNKED)) {                              \
         END_REQUEST;                                                 \
       }                                                              \
     } else {                                                         \
-      parser->eating = TRUE;                                         \
+      parser->flags |= EATING;                                       \
     }                                                                \
   }                                                                  \
 } while (0)
@@ -142,60 +152,36 @@ do {                                                                 \
 
   action header_field {
     CALLBACK(header_field);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_field_mark = NULL;
     parser->header_field_size = 0;
   }
 
   action header_value {
     CALLBACK(header_value);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->header_value_mark = NULL;
     parser->header_value_size = 0;
   }
 
-  action request_uri { 
+  action request_uri {
     CALLBACK(uri);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->uri_mark = NULL;
     parser->uri_size = 0;
   }
 
-  action fragment { 
+  action fragment {
     CALLBACK(fragment);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->fragment_mark = NULL;
     parser->fragment_size = 0;
   }
 
-  action query_string { 
+  action query_string {
     CALLBACK(query_string);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->query_string_mark = NULL;
     parser->query_string_size = 0;
   }
 
   action request_path {
     CALLBACK(path);
-    if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
-    }
     parser->path_mark = NULL;
     parser->path_size = 0;
   }
@@ -204,8 +190,8 @@ do {                                                                 \
     if(parser->on_headers_complete) {
       callback_return_value = parser->on_headers_complete(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
@@ -214,16 +200,17 @@ do {                                                                 \
     if(parser->on_message_begin) {
       callback_return_value = parser->on_message_begin(parser);
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
     }
   }
 
   action content_length {
+    if (parser->content_length == -1) parser->content_length = 0;
     if (parser->content_length > INT_MAX) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
     parser->content_length *= 10;
     parser->content_length += *p - '0';
@@ -234,21 +221,14 @@ do {                                                                 \
     parser->status_code += *p - '0';
   }
 
-  action use_identity_encoding { parser->transfer_encoding = HTTP_IDENTITY; }
-  action use_chunked_encoding  { parser->transfer_encoding = HTTP_CHUNKED;  }
+  action use_chunked_encoding { parser->flags |= CHUNKED;  }
 
-  action set_keep_alive { parser->keep_alive = TRUE; }
-  action set_not_keep_alive { parser->keep_alive = FALSE; }
+  action set_keep_alive { parser->keep_alive = 1; }
+  action set_not_keep_alive { parser->keep_alive = 0; }
 
-  action version_major {
-    parser->version_major *= 10;
-    parser->version_major += *p - '0';
-  }
-
-  action version_minor {
-    parser->version_minor *= 10;
-    parser->version_minor += *p - '0';
-  }
+  action version_11 { parser->version = HTTP_VERSION_11; }
+  action version_10 { parser->version = HTTP_VERSION_10; }
+  action version_09 { parser->version = HTTP_VERSION_09; }
 
   action add_to_chunk_size {
     parser->chunk_size *= 16;
@@ -258,15 +238,15 @@ do {                                                                 \
   action skip_chunk_data {
     SKIP_BODY(MIN(parser->chunk_size, REMAINING));
     if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
 
-    fhold; 
+    fhold;
     if (parser->chunk_size > REMAINING) {
       fbreak;
     } else {
-      fgoto chunk_end; 
+      fgoto chunk_end;
     }
   }
 
@@ -280,18 +260,32 @@ do {                                                                 \
   }
 
   action body_logic {
-    if (parser->transfer_encoding == HTTP_CHUNKED) {
+    if (parser->flags & CHUNKED) {
       fnext ChunkedBody;
     } else {
-      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
-      parser->chunk_size = parser->content_length;
-      p += 1;  
+      /* this is pretty stupid. i'd prefer to combine this with
+       * skip_chunk_data */
+      if (parser->content_length < 0) {
+        /* If we didn't get a content length; if not keep-alive
+         * just read body until EOF */
+        if (!http_parser_should_keep_alive(parser)) {
+          parser->flags |= EAT_FOREVER;
+          parser->chunk_size = REMAINING;
+        } else {
+          /* Otherwise, if keep-alive, then assume the message
+           * has no body. */
+          parser->chunk_size = parser->content_length = 0;
+        }
+      } else {
+        parser->chunk_size = parser->content_length;
+      }
+      p += 1;
 
-      SKIP_BODY(MIN(REMAINING, parser->content_length));
+      SKIP_BODY(MIN(REMAINING, parser->chunk_size));
 
       if (callback_return_value != 0) {
-        parser->error = TRUE;
-        return 0;
+        parser->flags |= ERROR;
+        return;
       }
 
       fhold;
@@ -314,13 +308,13 @@ do {                                                                 \
   escape = ("%" xdigit xdigit);
   uchar = (unreserved | escape | "\"");
   pchar = (uchar | ":" | "@" | "&" | "=" | "+");
-  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" 
+  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\""
               | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
 
 # elements
   token = (ascii -- (CTL | tspecials));
   quote = "\"";
-#  qdtext = token -- "\""; 
+#  qdtext = token -- "\"";
 #  quoted_pair = "\" ascii;
 #  quoted_string = "\"" (qdtext | quoted_pair )* "\"";
 
@@ -342,7 +336,11 @@ do {                                                                 \
            | "UNLOCK"    %{ parser->method = HTTP_UNLOCK;    }
            ); # Not allowing extension methods
 
-  HTTP_Version = "HTTP/" digit $version_major "." digit $version_minor;
+  HTTP_Version = "HTTP/" ( "1.1" %version_11
+                         | "1.0" %version_10
+                         | "0.9" %version_09
+                         | (digit "." digit)
+                         );
 
   scheme = ( alpha | digit | "+" | "-" | "." )* ;
   absolute_uri = (scheme ":" (uchar | reserved )*);
@@ -364,12 +362,12 @@ do {                                                                 \
   hsep = ":" " "*;
   header = (field_name hsep field_value) :> CRLF;
   Header = ( ("Content-Length"i hsep digit+ $content_length)
-           | ("Connection"i hsep 
+           | ("Connection"i hsep
                ( "Keep-Alive"i %set_keep_alive
                | "close"i %set_not_keep_alive
                )
              )
-           | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding)
+           | ("Transfer-Encoding"i hsep "chunked"i %use_chunked_encoding)
            | (Field_Name hsep Field_Value)
            ) :> CRLF;
 
@@ -387,11 +385,11 @@ do {                                                                 \
   chunk_ext_val = token*;
   chunk_ext_name = token*;
   chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
-  last_chunk = "0"+ chunk_extension CRLF;
-  chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
+  last_chunk = "0"+ ( chunk_extension | " "+) CRLF;
+  chunk_size = (xdigit* [1-9a-fA-F] xdigit* ) $add_to_chunk_size;
   chunk_end  = CRLF;
   chunk_body = any >skip_chunk_data;
-  chunk_begin = chunk_size chunk_extension CRLF;
+  chunk_begin = chunk_size ( chunk_extension | " "+ ) CRLF;
   chunk = chunk_begin chunk_body chunk_end;
   ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body;
 
@@ -415,13 +413,12 @@ do {                                                                 \
 %% write data;
 
 void
-http_parser_init (http_parser *parser, enum http_parser_type type) 
+http_parser_init (http_parser *parser, enum http_parser_type type)
 {
   int cs = 0;
   %% write init;
   parser->cs = cs;
   parser->type = type;
-  parser->error = 0;
 
   parser->on_message_begin = NULL;
   parser->on_path = NULL;
@@ -438,23 +435,39 @@ http_parser_init (http_parser *parser, enum http_parser_type type)
 }
 
 /** exec **/
-size_t
+void
 http_parser_execute (http_parser *parser, const char *buffer, size_t len)
 {
   size_t tmp; // REMOVE ME this is extremely hacky
   int callback_return_value = 0;
-  const char *p, *pe;
+  const char *p, *pe, *eof;
   int cs = parser->cs;
 
   p = buffer;
   pe = buffer+len;
+  eof = len ? NULL : pe;
 
-  if (0 < parser->chunk_size && parser->eating) {
+  if (parser->flags & EAT_FOREVER) {
+    if (len == 0) {
+      if (parser->on_message_complete) {
+        callback_return_value = parser->on_message_complete(parser);
+        if (callback_return_value != 0) parser->flags |= ERROR;
+      }
+    } else {
+      if (parser->on_body) {
+        callback_return_value = parser->on_body(parser, p, len);
+        if (callback_return_value != 0) parser->flags |= ERROR;
+      }
+    }
+    return;
+  }
+
+  if (0 < parser->chunk_size && (parser->flags & EATING)) {
     /* eat body */
     SKIP_BODY(MIN(len, parser->chunk_size));
     if (callback_return_value != 0) {
-      parser->error = TRUE;
-      return 0;
+      parser->flags |= ERROR;
+      return;
     }
   }
 
@@ -477,26 +490,11 @@ http_parser_execute (http_parser *parser, const char *buffer, size_t len)
   CALLBACK(uri);
 
   assert(p <= pe && "buffer overflow after parsing execute");
-  return(p - buffer);
 }
 
 int
-http_parser_has_error (http_parser *parser) 
+http_parser_has_error (http_parser *parser)
 {
-  if (parser->error) return TRUE;
+  if (parser->flags & ERROR) return 1;
   return parser->cs == http_parser_error;
 }
-
-int
-http_parser_should_keep_alive (http_parser *parser)
-{
-  if (parser->keep_alive == -1)
-    if (parser->version_major == 1)
-      return (parser->version_minor != 0);
-    else if (parser->version_major == 0)
-      return FALSE;
-    else
-      return TRUE;
-  else
-    return parser->keep_alive;
-}
index 5405f63..58bc7df 100644 (file)
@@ -38,7 +38,7 @@ struct message {
 static struct message messages[5];
 static int num_messages;
 
-/* * R E Q U E S T S * */ 
+/* * R E Q U E S T S * */
 const struct message requests[] =
 #define CURL_GET 0
 { {.name= "curl get"
@@ -55,7 +55,7 @@ const struct message requests[] =
   ,.request_path= "/test"
   ,.request_uri= "/test"
   ,.num_headers= 3
-  ,.headers= 
+  ,.headers=
     { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }
     , { "Host", "0.0.0.0=5000" }
     , { "Accept", "*/*" }
@@ -83,7 +83,7 @@ const struct message requests[] =
   ,.request_path= "/favicon.ico"
   ,.request_uri= "/favicon.ico"
   ,.num_headers= 8
-  ,.headers= 
+  ,.headers=
     { { "Host", "0.0.0.0=5000" }
     , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }
     , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }
@@ -109,7 +109,7 @@ const struct message requests[] =
   ,.request_path= "/dumbfuck"
   ,.request_uri= "/dumbfuck"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "aaaaaaaaaaaaa",  "++++++++++" }
     }
   ,.body= ""
@@ -126,7 +126,7 @@ const struct message requests[] =
   ,.fragment= "posts-17408"
   ,.request_path= "/forums/1/topics/2375"
   /* XXX request uri does not include fragment? */
-  ,.request_uri= "/forums/1/topics/2375?page=1" 
+  ,.request_uri= "/forums/1/topics/2375?page=1"
   ,.num_headers= 0
   ,.body= ""
   }
@@ -159,7 +159,7 @@ const struct message requests[] =
   ,.request_path= "/get_one_header_no_body"
   ,.request_uri= "/get_one_header_no_body"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "Accept" , "*/*" }
     }
   ,.body= ""
@@ -179,7 +179,7 @@ const struct message requests[] =
   ,.request_path= "/get_funky_content_length_body_hello"
   ,.request_uri= "/get_funky_content_length_body_hello"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "conTENT-Length" , "5" }
     }
   ,.body= "HELLO"
@@ -201,10 +201,10 @@ const struct message requests[] =
   ,.request_path= "/post_identity_body_world"
   ,.request_uri= "/post_identity_body_world?q=search"
   ,.num_headers= 3
-  ,.headers= 
+  ,.headers=
     { { "Accept", "*/*" }
     , { "Transfer-Encoding", "identity" }
-    , { "Content-Length", "5" } 
+    , { "Content-Length", "5" }
     }
   ,.body= "World"
   }
@@ -225,7 +225,7 @@ const struct message requests[] =
   ,.request_path= "/post_chunked_all_your_base"
   ,.request_uri= "/post_chunked_all_your_base"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "Transfer-Encoding" , "chunked" }
     }
   ,.body= "all your base are belong to us"
@@ -248,13 +248,13 @@ const struct message requests[] =
   ,.request_path= "/two_chunks_mult_zero_end"
   ,.request_uri= "/two_chunks_mult_zero_end"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "Transfer-Encoding", "chunked" }
     }
   ,.body= "hello world"
   }
 
-#define CHUNKED_W_TRAILING_HEADERS 10 
+#define CHUNKED_W_TRAILING_HEADERS 10
 , {.name= "chunked with trailing headers. blech."
   ,.type= HTTP_REQUEST
   ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
@@ -273,13 +273,13 @@ const struct message requests[] =
   ,.request_path= "/chunked_w_trailing_headers"
   ,.request_uri= "/chunked_w_trailing_headers"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "Transfer-Encoding",  "chunked" }
     }
   ,.body= "hello world"
   }
 
-#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11 
+#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
 , {.name= "with bullshit after the length"
   ,.type= HTTP_REQUEST
   ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
@@ -296,7 +296,7 @@ const struct message requests[] =
   ,.request_path= "/chunked_w_bullshit_after_length"
   ,.request_uri= "/chunked_w_bullshit_after_length"
   ,.num_headers= 1
-  ,.headers= 
+  ,.headers=
     { { "Transfer-Encoding", "chunked" }
     }
   ,.body= "hello world"
@@ -320,8 +320,8 @@ const struct message requests[] =
 , {.name= NULL } /* sentinel */
 };
 
-/* * R E S P O N S E S * */ 
-const struct message responses[] = 
+/* * R E S P O N S E S * */
+const struct message responses[] =
 { {.name= "google 301"
   ,.type= HTTP_RESPONSE
   ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"
@@ -342,7 +342,7 @@ const struct message responses[] =
   ,.should_keep_alive= TRUE
   ,.status_code= 301
   ,.num_headers= 7
-  ,.headers= 
+  ,.headers=
     { { "Location", "http://www.google.com/" }
     , { "Content-Type", "text/html; charset=UTF-8" }
     , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }
@@ -359,6 +359,45 @@ const struct message responses[] =
           "</BODY></HTML>\r\n"
   }
 
+, {.name= "no content-length response"
+  ,.type= HTTP_RESPONSE
+  ,.raw= "HTTP/1.1 200 OK\r\n"
+         "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"
+         "Server: Apache\r\n"
+         "X-Powered-By: Servlet/2.5 JSP/2.1\r\n"
+         "Content-Type: text/xml; charset=utf-8\r\n"
+         "Connection: close\r\n"
+         "\r\n"
+         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+         "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+         "  <SOAP-ENV:Body>\n"
+         "    <SOAP-ENV:Fault>\n"
+         "       <faultcode>SOAP-ENV:Client</faultcode>\n"
+         "       <faultstring>Client Error</faultstring>\n"
+         "    </SOAP-ENV:Fault>\n"
+         "  </SOAP-ENV:Body>\n"
+         "</SOAP-ENV:Envelope>"
+  ,.should_keep_alive= FALSE
+  ,.status_code= 200
+  ,.num_headers= 5
+  ,.headers=
+    { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
+    , { "Server", "Apache" }
+    , { "X-Powered-By", "Servlet/2.5 JSP/2.1" }
+    , { "Content-Type", "text/xml; charset=utf-8" }
+    , { "Connection", "close" }
+    }
+  ,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+          "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+          "  <SOAP-ENV:Body>\n"
+          "    <SOAP-ENV:Fault>\n"
+          "       <faultcode>SOAP-ENV:Client</faultcode>\n"
+          "       <faultstring>Client Error</faultstring>\n"
+          "    </SOAP-ENV:Fault>\n"
+          "  </SOAP-ENV:Body>\n"
+          "</SOAP-ENV:Envelope>"
+  }
+
 , {.name= "404 no headers no body"
   ,.type= HTTP_RESPONSE
   ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
@@ -377,7 +416,34 @@ const struct message responses[] =
   ,.num_headers= 0
   ,.headers= {}
   ,.body= ""
-}
+  }
+
+, {.name="200 trailing space on chunked body"
+  ,.type= HTTP_RESPONSE
+  ,.raw= "HTTP/1.1 200 OK\r\n"
+         "Content-Type: text/plain\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "25  \r\n"
+         "This is the data in the first chunk\r\n"
+         "\r\n"
+         "1C\r\n"
+         "and this is the second one\r\n"
+         "\r\n"
+         "0  \r\n"
+         "\r\n"
+  ,.should_keep_alive= TRUE
+  ,.status_code= 200
+  ,.num_headers= 2
+  ,.headers=
+    { {"Content-Type", "text/plain" }
+    , {"Transfer-Encoding", "chunked" }
+    }
+  ,.body =
+         "This is the data in the first chunk\r\n"
+         "and this is the second one\r\n"
+
+  }
 
 , {.name= NULL } /* sentinel */
 };
@@ -543,12 +609,14 @@ parse_messages (int message_count, const struct message *input_messages[])
   }
 
   // Parse the stream
-  size_t traversed = 0;
   parser_init(HTTP_REQUEST);
 
-  traversed = http_parser_execute(&parser, total, length);
+  http_parser_execute(&parser, total, length);
+  assert(!http_parser_has_error(&parser));
 
+  http_parser_execute(&parser, NULL, 0);
   assert(!http_parser_has_error(&parser));
+
   assert(num_messages == message_count);
 
   for (i = 0; i < message_count; i++) {
@@ -560,11 +628,14 @@ parse_messages (int message_count, const struct message *input_messages[])
 void
 test_message (const struct message *message)
 {
-  size_t traversed = 0;
   parser_init(message->type);
 
-  traversed = http_parser_execute(&parser, message->raw, strlen(message->raw));
+  http_parser_execute(&parser, message->raw, strlen(message->raw));
   assert(!http_parser_has_error(&parser));
+
+  http_parser_execute(&parser, NULL, 0);
+  assert(!http_parser_has_error(&parser));
+
   assert(num_messages == 1);
 
   message_eq(0, message);
@@ -573,10 +644,10 @@ test_message (const struct message *message)
 void
 test_error (const char *buf)
 {
-  size_t traversed = 0;
   parser_init(HTTP_REQUEST);
 
-  traversed = http_parser_execute(&parser, buf, strlen(buf));
+  http_parser_execute(&parser, buf, strlen(buf));
+  http_parser_execute(&parser, NULL, 0);
 
   assert(http_parser_has_error(&parser));
 }
@@ -584,30 +655,32 @@ test_error (const char *buf)
 void
 test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
 {
-  char total[ strlen(r1->raw) 
-            + strlen(r2->raw) 
-            + strlen(r3->raw) 
+  char total[ strlen(r1->raw)
+            + strlen(r2->raw)
+            + strlen(r3->raw)
             + 1
             ];
   total[0] = '\0';
 
-  strcat(total, r1->raw); 
-  strcat(total, r2->raw); 
-  strcat(total, r3->raw); 
+  strcat(total, r1->raw);
+  strcat(total, r2->raw);
+  strcat(total, r3->raw);
 
-  size_t traversed = 0;
   parser_init(HTTP_REQUEST);
 
-  traversed = http_parser_execute(&parser, total, strlen(total));
+  http_parser_execute(&parser, total, strlen(total));
+  assert(!http_parser_has_error(&parser) );
+
+  http_parser_execute(&parser, NULL, 0);
+  assert(!http_parser_has_error(&parser) );
 
-  assert(! http_parser_has_error(&parser) );
   assert(num_messages == 3);
   message_eq(0, r1);
   message_eq(1, r2);
   message_eq(2, r3);
 }
 
-/* SCAN through every possible breaking to make sure the 
+/* SCAN through every possible breaking to make sure the
  * parser can handle getting the content in any chunks that
  * might come from the socket
  */
@@ -619,13 +692,13 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
   char buf2[80*1024] = "\0";
   char buf3[80*1024] = "\0";
 
-  strcat(total, r1->raw); 
-  strcat(total, r2->raw); 
-  strcat(total, r3->raw); 
+  strcat(total, r1->raw);
+  strcat(total, r2->raw);
+  strcat(total, r3->raw);
 
   int total_len = strlen(total);
 
-  int total_ops = (total_len - 1) * (total_len - 2) / 2; 
+  int total_ops = (total_len - 1) * (total_len - 2) / 2;
   int ops = 0 ;
 
   int i,j;
@@ -659,16 +732,16 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
       */
 
       http_parser_execute(&parser, buf1, buf1_len);
-
       assert(!http_parser_has_error(&parser));
 
       http_parser_execute(&parser, buf2, buf2_len);
-
       assert(!http_parser_has_error(&parser));
 
       http_parser_execute(&parser, buf3, buf3_len);
+      assert(!http_parser_has_error(&parser));
 
-      assert(! http_parser_has_error(&parser));
+      http_parser_execute(&parser, NULL, 0);
+      assert(!http_parser_has_error(&parser));
 
       assert(3 == num_messages);
 
@@ -687,14 +760,14 @@ main (void)
 
   printf("sizeof(http_parser) = %d\n", sizeof(http_parser));
 
-  int request_count; 
+  int request_count;
   for (request_count = 0; requests[request_count].name; request_count++);
 
-  int response_count; 
+  int response_count;
   for (response_count = 0; responses[response_count].name; response_count++);
 
 
-  //// RESPONSES  
+  //// RESPONSES
 
   for (i = 0; i < response_count; i++) {
     test_message(&responses[i]);
@@ -755,7 +828,7 @@ main (void)
                                            "Accept: */*\r\n"
                                            "\r\n"
                                            "HELLO";
-  test_error(bad_get_no_headers_no_body); 
+  test_error(bad_get_no_headers_no_body);
 
 
   /* TODO sending junk and large headers gets rejected */
index 6225aa7..0e66c67 100644 (file)
@@ -333,7 +333,7 @@ function ClientRequest (method, uri, headers) {
   }
   this.closeOnFinish = true;
 
-  this.sendHeaderLines(method + " " + uri + " HTTP/1.1\r\n", headers);
+  this.sendHeaderLines(method + " " + uri + " HTTP/1.0\r\n", headers);
 }
 node.inherits(ClientRequest, OutgoingMessage);
 
@@ -476,7 +476,6 @@ function connectionListener (connection) {
     }
   });
 
-
   createIncomingMessageStream(connection, function (incoming, should_keep_alive) {
     var req = incoming;
 
@@ -507,7 +506,9 @@ exports.createClient = function (port, host) {
         return;
       }
       //sys.debug("client flush  readyState = " + client.readyState);
-      if (req == requests[0]) flushMessageQueue(client, [req]);
+      if (req == requests[0]) {
+        if(flushMessageQueue(client, [req])) client.close();
+      }
     });
     requests.push(req);
   };
index 53edb57..1c80cea 100644 (file)
@@ -66,6 +66,21 @@ HTTPConnection::OnReceive (const void *buf, size_t len)
   if (http_parser_has_error(&parser_)) ForceClose();
 }
 
+void
+HTTPConnection::OnEOF ()
+{
+  HandleScope scope;
+
+  assert(attached_);
+  http_parser_execute(&parser_, NULL, 0);
+
+  if (http_parser_has_error(&parser_)) {
+    ForceClose();
+  } else {
+    Emit("eof", 0, NULL);
+  }
+}
+
 int
 HTTPConnection::on_message_begin (http_parser *parser)
 {
@@ -211,14 +226,25 @@ HTTPConnection::on_headers_complete (http_parser *parser)
         Integer::New(connection->parser_.status_code));
 
   // VERSION
-  char version[10];
-  snprintf( version
-          , 10
-          , "%d.%d"
-          , connection->parser_.version_major
-          , connection->parser_.version_minor
-          );
-  message_info->Set(HTTP_VERSION_SYMBOL, String::New(version));
+  Local<String> version;
+  switch (connection->parser_.version) {
+    case HTTP_VERSION_OTHER:
+      version = String::NewSymbol("Other");
+      break;
+
+    case HTTP_VERSION_09:
+      version = String::NewSymbol("0.9");
+      break;
+
+    case HTTP_VERSION_10:
+      version = String::NewSymbol("1.0");
+      break;
+
+    case HTTP_VERSION_11:
+      version = String::NewSymbol("1.1");
+      break;
+  }
+  message_info->Set(HTTP_VERSION_SYMBOL, version);
 
   message_info->Set(SHOULD_KEEP_ALIVE_SYMBOL,
       http_parser_should_keep_alive(&connection->parser_) ? True() : False());
index d464832..d1ca404 100644 (file)
@@ -36,6 +36,7 @@ protected:
   }
 
   void OnReceive (const void *buf, size_t len);
+  void OnEOF ();
 
   static int on_message_begin (http_parser *parser);
   static int on_uri (http_parser *parser, const char *at, size_t length);
index 3c7173c..ec8bd88 100644 (file)
@@ -7,26 +7,30 @@ http = require("/http.js");
 port = 9999;
 
 nrequests_completed = 0;
-nrequests_expected = 1;
+nrequests_expected = 2;
 
-var s = http.createServer(function (req, res) {
+var server = http.createServer(function (req, res) {
   puts("req: " + JSON.stringify(req.uri));
 
   res.sendHeader(200, {"Content-Type": "text/plain"});
   res.sendBody("Hello World");
   res.finish();
 
-  if (++nrequests_completed == nrequests_expected) s.close();
+  if (++nrequests_completed == nrequests_expected) server.close();
+
+  puts("nrequests_completed: " + nrequests_completed);
 });
-s.listen(port);
+server.listen(port);
 
-var c = tcp.createConnection(port);
-c.addListener("connect", function () {
-  c.send("GET /hello?foo=%99bar HTTP/1.1\r\n\r\n");
-  c.close();
+tcp.createConnection(port).addListener("connect", function () {
+  this.send("GET /hello?foo=%99bar HTTP/1.1\r\nConnection: close\r\n\r\n");
+  this.close();
 });
 
-//  TODO add more!
+tcp.createConnection(port).addListener("connect", function () {
+  this.send("GET /with_\"stupid\"_quotes?in_the=\"uri\" HTTP/1.1\r\nConnection: close\r\n\r\n");
+  this.close();
+});
 
 process.addListener("exit", function () {
   assertEquals(nrequests_expected, nrequests_completed);
index 94fa4f0..c1024b1 100644 (file)
@@ -5,12 +5,12 @@ var PROXY_PORT = 8869;
 var BACKEND_PORT = 8870;
 
 var backend = http.createServer(function (req, res) {
-  // debug("backend");
+  debug("backend");
   res.sendHeader(200, {"content-type": "text/plain"});
   res.sendBody("hello world\n");
   res.finish();
 });
-// debug("listen backend")
+debug("listen backend")
 backend.listen(BACKEND_PORT);
 
 var proxy_client = http.createClient(BACKEND_PORT);
@@ -24,30 +24,30 @@ var proxy = http.createServer(function (req, res) {
     });
     proxy_res.addListener("complete", function() {
       res.finish();
-      // debug("proxy res");
+      debug("proxy res");
     });
   });
 });
-// debug("listen proxy")
+debug("listen proxy")
 proxy.listen(PROXY_PORT);
 
 var body = "";
 
 var client = http.createClient(PROXY_PORT);
 var req = client.get("/test");
-// debug("client req")
+debug("client req")
 req.finish(function (res) {
-  // debug("got res");
+  debug("got res: " + JSON.stringify(res.headers));
   assertEquals(200, res.statusCode);
   res.setBodyEncoding("utf8");
   res.addListener("body", function (chunk) { body += chunk; });
   res.addListener("complete", function () {
     proxy.close();
     backend.close();
-    // debug("closed both");
+    debug("closed both");
   });
 });
 
 process.addListener("exit", function () {
-  assertEquals(body, "hello world\n");
+  assertEquals("hello world\n", body);
 });
index 3d3bb50..62a72fb 100644 (file)
@@ -13,6 +13,12 @@ http.createServer(function (req, res) {
   res.id = request_number;
   req.id = request_number++;
 
+  puts("server got request " + req.id);
+
+  req.addListener("complete", function () {
+    puts("request complete " + req.id);
+  });
+
   if (req.id == 0) {
     assertEquals("GET", req.method);
     assertEquals("/hello", req.uri.path);
@@ -24,10 +30,11 @@ http.createServer(function (req, res) {
     assertEquals("POST", req.method);
     assertEquals("/quit", req.uri.path);
     this.close();
-    //puts("server closed");
+    puts("server closed");
   }
 
   setTimeout(function () {
+    puts("send response " + req.id);
     res.sendHeader(200, {"Content-Type": "text/plain"});
     res.sendBody(req.uri.path);
     res.finish();
@@ -40,7 +47,8 @@ var c = tcp.createConnection(port);
 c.setEncoding("utf8");
 
 c.addListener("connect", function () {
-  c.send( "GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n" );
+  puts("client connected. sending first request");
+  c.send("GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n" );
   requests_sent += 1;
 });
 
@@ -48,7 +56,9 @@ c.addListener("receive", function (chunk) {
   server_response += chunk;
 
   if (requests_sent == 1) {
+    puts("send request 2");
     c.send("POST /quit HTTP/1.1\r\n\r\n");
+    puts("close client");
     c.close();
     assertEquals(c.readyState, "readOnly");
     requests_sent += 1;
@@ -56,10 +66,12 @@ c.addListener("receive", function (chunk) {
 });
 
 c.addListener("eof", function () {
+  puts("client got eof");
   client_got_eof = true;
 });
 
 c.addListener("close", function () {
+  puts("client closed");
   assertEquals(c.readyState, "closed");
 });