From c9e21435c02d07c052d02b1b1a55732fdbc880e2 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Sat, 9 Jan 2010 01:52:49 -0800 Subject: [PATCH] Upgrade http-parser --- deps/http_parser/LICENSE-MIT | 2 +- deps/http_parser/README.md | 10 +-- deps/http_parser/http_parser.c | 50 ++++++----- deps/http_parser/http_parser.h | 10 ++- deps/http_parser/test.c | 158 +++++++++++++++++++-------------- src/node_http.cc | 15 +--- src/node_http.h | 10 +-- 7 files changed, 137 insertions(+), 118 deletions(-) diff --git a/deps/http_parser/LICENSE-MIT b/deps/http_parser/LICENSE-MIT index cb938cd089..f30a31de94 100644 --- a/deps/http_parser/LICENSE-MIT +++ b/deps/http_parser/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright 2009 Ryan Dahl +Copyright 2009,2010 Ryan Dahl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/deps/http_parser/README.md b/deps/http_parser/README.md index bca5aeaa43..6684cfeff2 100644 --- a/deps/http_parser/README.md +++ b/deps/http_parser/README.md @@ -29,10 +29,10 @@ Usage One `http_parser` object is used per TCP connection. Initialize the struct using `http_parser_init()` and set the callbacks. That might look something -like this: +like this for a request parser: http_parser *parser = malloc(sizeof(http_parser)); - http_parser_init(parser); + http_parser_init(parser, HTTP_REQUEST); parser->on_path = my_path_callback; parser->on_header_field = my_header_field_callback; /* ... */ @@ -54,7 +54,7 @@ When data is received on the socket execute the parser and check for errors. * Note we pass the recved==0 to http_parse_requests to signal * that EOF has been recieved. */ - nparsed = http_parse_requests(parser, buf, recved); + nparsed = http_parser_execute(parser, buf, recved); if (nparsed != recved) { /* Handle error. Usually just close the connection. */ @@ -63,7 +63,7 @@ When data is received on the socket execute the parser and check for errors. 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_parse_requests()`. Callbacks and errors +`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. @@ -85,7 +85,7 @@ parser, for example, would not want such a feature. Callbacks --------- -During the `http_parse_requests()` call, the callbacks set in `http_parser` +During the `http_parser_execute()` call, the callbacks set in `http_parser` will be executed. The parser maintains state and never looks behind, so buffering the data is not necessary. If you need to save certain data for later usage, you can do that from the callbacks. diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 9088af72c1..95afa18142 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/http_parser/http_parser.c @@ -1,4 +1,4 @@ -/* Copyright 2009 Ryan Dahl +/* Copyright 2009,2010 Ryan Dahl * * Some parts of this source file were taken from NGINX * (src/http/ngx_http_parser.c) copyright (C) 2002-2009 Igor Sysoev. @@ -97,6 +97,7 @@ static inline int message_complete_callback (http_parser *parser) return parser->on_message_complete(parser); } +#define PROXY_CONNECTION "proxy-connection" #define CONNECTION "connection" #define CONTENT_LENGTH "content-length" #define TRANSFER_ENCODING "transfer-encoding" @@ -218,6 +219,7 @@ enum header_states , h_CON , h_matching_connection + , h_matching_proxy_connection , h_matching_content_length , h_matching_transfer_encoding @@ -245,6 +247,8 @@ enum flags #define LF '\n' #define LOWER(c) (unsigned char)(c | 0x20) +#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) + #if HTTP_PARSER_STRICT # define STRICT_CHECK(cond) if (cond) goto error # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) @@ -253,8 +257,9 @@ enum flags # define NEW_MESSAGE() start_state #endif -static inline -size_t parse (http_parser *parser, const char *data, size_t len, int start_state) +size_t http_parser_execute (http_parser *parser, + const char *data, + size_t len) { char c, ch; const char *p, *pe; @@ -950,6 +955,10 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state header_state = h_C; break; + case 'p': + header_state = h_matching_proxy_connection; + break; + case 't': header_state = h_matching_transfer_encoding; break; @@ -1007,6 +1016,18 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state } break; + /* proxy-connection */ + + case h_matching_proxy_connection: + index++; + if (index > sizeof(PROXY_CONNECTION)-1 + || c != PROXY_CONNECTION[index]) { + header_state = h_general; + } else if (index == sizeof(PROXY_CONNECTION)-2) { + header_state = h_connection; + } + break; + /* content-length */ case h_matching_content_length: @@ -1256,7 +1277,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state /* Content-Length header given and non-zero */ state = s_body_identity; } else { - if (start_state == s_start_req || http_should_keep_alive(parser)) { + if (parser->type == HTTP_REQUEST || http_should_keep_alive(parser)) { /* Assume content-length 0 - read the next */ CALLBACK2(message_complete); state = NEW_MESSAGE(); @@ -1408,22 +1429,6 @@ error: } -size_t -http_parse_requests (http_parser *parser, const char *data, size_t len) -{ - if (!parser->state) parser->state = s_start_req; - return parse(parser, data, len, s_start_req); -} - - -size_t -http_parse_responses (http_parser *parser, const char *data, size_t len) -{ - if (!parser->state) parser->state = s_start_res; - return parse(parser, data, len, s_start_res); -} - - int http_should_keep_alive (http_parser *parser) { @@ -1446,9 +1451,10 @@ http_should_keep_alive (http_parser *parser) void -http_parser_init (http_parser *parser) +http_parser_init (http_parser *parser, enum http_parser_type t) { - parser->state = 0; + parser->type = t; + parser->state = (t == HTTP_REQUEST ? s_start_req : s_start_res); parser->on_message_begin = NULL; parser->on_path = NULL; parser->on_query_string = NULL; diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h index 5855e89405..a1439ea364 100644 --- a/deps/http_parser/http_parser.h +++ b/deps/http_parser/http_parser.h @@ -1,4 +1,4 @@ -/* Copyright 2009 Ryan Dahl +/* Copyright 2009,2010 Ryan Dahl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -74,8 +74,11 @@ enum http_method , HTTP_UNLOCK = 0x4000 }; +enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE }; + struct http_parser { /** PRIVATE **/ + enum http_parser_type type; unsigned short state; unsigned short header_state; size_t index; @@ -125,9 +128,8 @@ struct http_parser { http_cb on_message_complete; }; -void http_parser_init(http_parser *parser); -size_t http_parse_requests(http_parser *parser, const char *data, size_t len); -size_t http_parse_responses(http_parser *parser, const char *data, size_t len); +void http_parser_init(http_parser *parser, enum http_parser_type type); +size_t http_parser_execute(http_parser *parser, const char *data, size_t len); /* Call this in the on_headers_complete or on_message_complete callback to * determine if this will be the last message on the connection. * If you are the server, respond with the "Connection: close" header diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c index 5f4c418f09..07f0f8119e 100644 --- a/deps/http_parser/test.c +++ b/deps/http_parser/test.c @@ -1,4 +1,4 @@ -/* Copyright 2009 Ryan Dahl +/* Copyright 2009,2010 Ryan Dahl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -34,14 +34,12 @@ #define MAX_HEADERS 10 #define MAX_ELEMENT_SIZE 500 -enum message_type { REQUEST, RESPONSE }; - static http_parser *parser; struct message { const char *name; // for debugging purposes const char *raw; - enum message_type type; + enum http_parser_type type; enum http_method method; int status_code; char request_path[MAX_ELEMENT_SIZE]; @@ -60,17 +58,16 @@ struct message { int message_begin_cb_called; int headers_complete_cb_called; int message_complete_cb_called; - int message_complete_on_eof; + int eof_indicates_message_end; }; static int currently_parsing_eof; -inline size_t parse (enum message_type t, const char *buf, size_t len) +inline size_t parse (const char *buf, size_t len) { size_t nparsed; currently_parsing_eof = (len == 0); - nparsed = (t == REQUEST ? http_parse_requests(parser, buf, len) - : http_parse_responses(parser, buf, len)); + nparsed = http_parser_execute(parser, buf, len); return nparsed; } @@ -81,14 +78,14 @@ static int num_messages; const struct message requests[] = #define CURL_GET 0 { {.name= "curl get" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /test HTTP/1.1\r\n" "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\r\n" "Host: 0.0.0.0=5000\r\n" "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -107,7 +104,7 @@ const struct message requests[] = #define FIREFOX_GET 1 , {.name= "firefox get" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /favicon.ico HTTP/1.1\r\n" "Host: 0.0.0.0=5000\r\n" "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" @@ -119,7 +116,7 @@ const struct message requests[] = "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -143,12 +140,12 @@ const struct message requests[] = #define DUMBFUCK 2 , {.name= "dumbfuck" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /dumbfuck HTTP/1.1\r\n" "aaaaaaaaaaaaa:++++++++++\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -165,11 +162,11 @@ const struct message requests[] = #define FRAGMENT_IN_URI 3 , {.name= "fragment in url" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -184,11 +181,11 @@ const struct message requests[] = #define GET_NO_HEADERS_NO_BODY 4 , {.name= "get no headers no body" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ + ,.eof_indicates_message_end= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -202,12 +199,12 @@ const struct message requests[] = #define GET_ONE_HEADER_NO_BODY 5 , {.name= "get one header no body" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n" "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ + ,.eof_indicates_message_end= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -224,13 +221,13 @@ const struct message requests[] = #define GET_FUNKY_CONTENT_LENGTH 6 , {.name= "get funky content length body hello" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" "conTENT-Length: 5\r\n" "\r\n" "HELLO" ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET @@ -247,7 +244,7 @@ const struct message requests[] = #define POST_IDENTITY_BODY_WORLD 7 , {.name= "post identity body world" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" "Accept: */*\r\n" "Transfer-Encoding: identity\r\n" @@ -255,7 +252,7 @@ const struct message requests[] = "\r\n" "World" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -274,7 +271,7 @@ const struct message requests[] = #define POST_CHUNKED_ALL_YOUR_BASE 8 , {.name= "post - chunked body: all your base are belong to us" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" @@ -282,7 +279,7 @@ const struct message requests[] = "0\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -299,7 +296,7 @@ const struct message requests[] = #define TWO_CHUNKS_MULT_ZERO_END 9 , {.name= "two chunks ; triple zero ending" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" @@ -308,7 +305,7 @@ const struct message requests[] = "000\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -325,7 +322,7 @@ const struct message requests[] = #define CHUNKED_W_TRAILING_HEADERS 10 , {.name= "chunked with trailing headers. blech." - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" @@ -336,7 +333,7 @@ const struct message requests[] = "Content-Type: text/plain\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -355,7 +352,7 @@ const struct message requests[] = #define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11 , {.name= "with bullshit after the length" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" @@ -364,7 +361,7 @@ const struct message requests[] = "0\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -381,10 +378,10 @@ const struct message requests[] = #define WITH_QUOTES 12 , {.name= "with quotes" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -400,17 +397,17 @@ const struct message requests[] = #define APACHEBENCH_GET 13 /* The server receiving this request SHOULD NOT wait for EOF * to know that content-length == 0. - * How to represent this in a unit test? message_complete_on_eof + * How to represent this in a unit test? eof_indicates_message_end * Compare with NO_CONTENT_LENGTH_RESPONSE. */ , {.name = "apachebench get" - ,.type= REQUEST + ,.type= HTTP_REQUEST ,.raw= "GET /test HTTP/1.0\r\n" "Host: 0.0.0.0:5000\r\n" "User-Agent: ApacheBench/2.3\r\n" "Accept: */*\r\n\r\n" ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET @@ -433,7 +430,7 @@ const struct message requests[] = const struct message responses[] = #define GOOGLE_301 0 { {.name= "google 301" - ,.type= RESPONSE + ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301 Moved Permanently\r\n" "Location: http://www.google.com/\r\n" "Content-Type: text/html; charset=UTF-8\r\n" @@ -450,7 +447,7 @@ const struct message responses[] = "here.\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 @@ -479,7 +476,7 @@ const struct message responses[] = * Compare with APACHEBENCH_GET */ , {.name= "no content-length response" - ,.type= 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" @@ -497,7 +494,7 @@ const struct message responses[] = " \n" "" ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE + ,.eof_indicates_message_end= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -522,10 +519,10 @@ const struct message responses[] = #define NO_HEADERS_NO_BODY_404 2 , {.name= "404 no headers no body" - ,.type= RESPONSE + ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 404 @@ -536,10 +533,10 @@ const struct message responses[] = #define NO_REASON_PHRASE 3 , {.name= "301 no response phrase" - ,.type= RESPONSE + ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301\r\n\r\n" ,.should_keep_alive = TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 @@ -550,7 +547,7 @@ const struct message responses[] = #define TRAILING_SPACE_ON_CHUNKED_BODY 4 , {.name="200 trailing space on chunked body" - ,.type= RESPONSE + ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Transfer-Encoding: chunked\r\n" @@ -564,7 +561,7 @@ const struct message responses[] = "0 \r\n" "\r\n" ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE + ,.eof_indicates_message_end= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -581,14 +578,14 @@ const struct message responses[] = #define NO_CARRIAGE_RET 5 , {.name="no carriage ret" - ,.type= RESPONSE + ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\n" "Content-Type: text/html; charset=utf-8\n" "Connection: close\n" "\n" "these headers are from http://news.ycombinator.com/" ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE + ,.eof_indicates_message_end= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -600,6 +597,31 @@ const struct message responses[] = ,.body= "these headers are from http://news.ycombinator.com/" } +#define PROXY_CONNECTION 6 +, {.name="proxy connection" + ,.type= HTTP_RESPONSE + ,.raw= "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "Content-Length: 11\r\n" + "Proxy-Connection: close\r\n" + "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n" + "\r\n" + "hello world" + ,.should_keep_alive= FALSE + ,.eof_indicates_message_end= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.status_code= 200 + ,.num_headers= 4 + ,.headers= + { {"Content-Type", "text/html; charset=UTF-8" } + , {"Content-Length", "11" } + , {"Proxy-Connection", "close" } + , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"} + } + ,.body= "hello world" + } + , {.name= NULL } /* sentinel */ }; @@ -708,14 +730,14 @@ message_complete_cb (http_parser *p) } messages[num_messages].message_complete_cb_called = TRUE; - messages[num_messages].message_complete_on_eof = currently_parsing_eof; + messages[num_messages].eof_indicates_message_end = currently_parsing_eof; num_messages++; return 0; } void -parser_init () +parser_init (enum http_parser_type type) { num_messages = 0; @@ -723,7 +745,7 @@ parser_init () parser = malloc(sizeof(http_parser)); - http_parser_init(parser); + http_parser_init(parser, type); memset(&messages, 0, sizeof messages); @@ -791,14 +813,14 @@ message_eq (int index, const struct message *expected) MESSAGE_CHECK_NUM_EQ(expected, m, http_major); MESSAGE_CHECK_NUM_EQ(expected, m, http_minor); - if (expected->type == REQUEST) { + if (expected->type == HTTP_REQUEST) { MESSAGE_CHECK_NUM_EQ(expected, m, method); } else { MESSAGE_CHECK_NUM_EQ(expected, m, status_code); } MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); - MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); + MESSAGE_CHECK_NUM_EQ(expected, m, eof_indicates_message_end); assert(m->message_begin_cb_called); assert(m->headers_complete_cb_called); @@ -869,17 +891,17 @@ print_error (const char *raw, size_t error_location) void test_message (const struct message *message) { - parser_init(); + parser_init(message->type); size_t read; - read = parse(message->type, message->raw, strlen(message->raw)); + read = parse(message->raw, strlen(message->raw)); if (read != strlen(message->raw)) { print_error(message->raw, read); exit(1); } - read = parse(message->type, NULL, 0); + read = parse(NULL, 0); if (read != 0) { print_error(message->raw, read); exit(1); @@ -898,13 +920,13 @@ test_message (const struct message *message) void test_error (const char *buf) { - parser_init(); + parser_init(HTTP_REQUEST); size_t parsed; - parsed = parse(REQUEST, buf, strlen(buf)); + parsed = parse(buf, strlen(buf)); if (parsed != strlen(buf)) goto out; - parsed = parse(REQUEST, NULL, 0); + parsed = parse(NULL, 0); if (parsed != 0) goto out; fprintf(stderr, "\n*** Error expected but none found ***\n\n%s", buf); @@ -929,17 +951,17 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct strcat(total, r2->raw); strcat(total, r3->raw); - parser_init(); + parser_init(r1->type); size_t read; - read = parse(r1->type, total, strlen(total)); + read = parse(total, strlen(total)); if (read != strlen(total)) { print_error(total, read); exit(1); } - read = parse(REQUEST, NULL, 0); + read = parse(NULL, 0); if (read != 0) { print_error(total, read); exit(1); @@ -992,7 +1014,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess } ops += 1; - parser_init(); + parser_init(r1->type); buf1_len = i; strncpy(buf1, total, buf1_len); @@ -1006,25 +1028,25 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess strncpy(buf3, total+j, buf3_len); buf3[buf3_len] = 0; - read = parse(r1->type, buf1, buf1_len); + read = parse(buf1, buf1_len); if (read != buf1_len) { print_error(buf1, read); goto error; } - read = parse(r1->type, buf2, buf2_len); + read = parse(buf2, buf2_len); if (read != buf2_len) { print_error(buf2, read); goto error; } - read = parse(r1->type, buf3, buf3_len); + read = parse(buf3, buf3_len); if (read != buf3_len) { print_error(buf3, read); goto error; } - parse(r1->type, NULL, 0); + parse(NULL, 0); if (3 != num_messages) { fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages); diff --git a/src/node_http.cc b/src/node_http.cc index 230b27200c..2ba9a08fc2 100644 --- a/src/node_http.cc +++ b/src/node_http.cc @@ -127,13 +127,9 @@ HTTPConnection::OnReceive (const void *buf, size_t len) HandleScope scope; assert(refs_); - size_t nparsed; + size_t nparsed; - if (type_ == HTTP_REQUEST) { - nparsed = http_parse_requests(&parser_, static_cast(buf), len); - } else { - nparsed = http_parse_responses(&parser_, static_cast(buf), len); - } + nparsed = http_parser_execute(&parser_, static_cast(buf), len); if (nparsed != len) { ForceClose(); @@ -145,11 +141,8 @@ HTTPConnection::OnEOF () { HandleScope scope; assert(refs_); - if (type_ == HTTP_REQUEST) { - http_parse_requests(&parser_, NULL, 0); - } else { - http_parse_responses(&parser_, NULL, 0); - } + size_t nparsed; + nparsed = http_parser_execute(&parser_, NULL, 0); Emit(eof_symbol, 0, NULL); } diff --git a/src/node_http.h b/src/node_http.h index 1e36df0fab..ad368b3a1f 100644 --- a/src/node_http.h +++ b/src/node_http.h @@ -7,8 +7,6 @@ namespace node { -enum http_connection_type { HTTP_RESPONSE, HTTP_REQUEST }; - class HTTPConnection : public Connection { public: static void Initialize (v8::Handle target); @@ -21,7 +19,7 @@ protected: static v8::Handle NewServer (const v8::Arguments& args); static v8::Handle ResetParser(const v8::Arguments& args); - HTTPConnection (enum http_connection_type t) + HTTPConnection (enum http_parser_type t) : Connection() { type_ = t; @@ -29,7 +27,7 @@ protected: } void ResetParser() { - http_parser_init (&parser_); + http_parser_init (&parser_, type_); parser_.on_message_begin = on_message_begin; parser_.on_url = on_url; parser_.on_path = on_path; @@ -57,10 +55,8 @@ protected: static int on_body (http_parser *parser, const char *buf, size_t len); static int on_message_complete (http_parser *parser); + enum http_parser_type type_; http_parser parser_; - enum http_connection_type type_; // should probably use subclass - // but going to refactor this all soon - // so won't worry about it. friend class HTTPServer; };