diff --git a/deps/http_parser/README.md b/deps/http_parser/README.md index abee9469338424..eedd7f8c9a4d0f 100644 --- a/deps/http_parser/README.md +++ b/deps/http_parser/README.md @@ -1,7 +1,7 @@ HTTP Parser =========== -[![Build Status](https://travis-ci.org/joyent/http-parser.png?branch=master)](https://travis-ci.org/joyent/http-parser) +[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) 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 diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 852bed042e9b21..d51a2e7bcdf30a 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/http_parser/http_parser.c @@ -123,7 +123,7 @@ do { \ FOR##_mark = NULL; \ } \ } while (0) - + /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) @@ -646,7 +646,7 @@ size_t http_parser_execute (http_parser *parser, const char *status_mark = 0; enum state p_state = (enum state) parser->state; const unsigned int lenient = parser->lenient_http_headers; - + /* We're in an error state. Don't bother doing anything. */ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { return 0; @@ -1007,89 +1007,40 @@ size_t http_parser_execute (http_parser *parser, UPDATE_STATE(s_req_spaces_before_url); } else if (ch == matcher[parser->index]) { ; /* nada */ - } else if (parser->method == HTTP_CONNECT) { - if (parser->index == 1 && ch == 'H') { - parser->method = HTTP_CHECKOUT; - } else if (parser->index == 2 && ch == 'P') { - parser->method = HTTP_COPY; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_MKCOL) { - if (parser->index == 1 && ch == 'O') { - parser->method = HTTP_MOVE; - } else if (parser->index == 1 && ch == 'E') { - parser->method = HTTP_MERGE; - } else if (parser->index == 1 && ch == '-') { - parser->method = HTTP_MSEARCH; - } else if (parser->index == 2 && ch == 'A') { - parser->method = HTTP_MKACTIVITY; - } else if (parser->index == 3 && ch == 'A') { - parser->method = HTTP_MKCALENDAR; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_SUBSCRIBE) { - if (parser->index == 1 && ch == 'E') { - parser->method = HTTP_SEARCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_REPORT) { - if (parser->index == 2 && ch == 'B') { - parser->method = HTTP_REBIND; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->index == 1) { - if (parser->method == HTTP_POST) { - if (ch == 'R') { - parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ - } else if (ch == 'U') { - parser->method = HTTP_PUT; /* or HTTP_PURGE */ - } else if (ch == 'A') { - parser->method = HTTP_PATCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_LOCK) { - if (ch == 'I') { - parser->method = HTTP_LINK; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } - } else if (parser->index == 2) { - if (parser->method == HTTP_PUT) { - if (ch == 'R') { - parser->method = HTTP_PURGE; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_UNLOCK) { - if (ch == 'S') { - parser->method = HTTP_UNSUBSCRIBE; - } else if(ch == 'B') { - parser->method = HTTP_UNBIND; - } else { + } else if (IS_ALPHA(ch)) { + + switch (parser->method << 16 | parser->index << 8 | ch) { +#define XX(meth, pos, ch, new_meth) \ + case (HTTP_##meth << 16 | pos << 8 | ch): \ + parser->method = HTTP_##new_meth; break; + + XX(POST, 1, 'U', PUT) + XX(POST, 1, 'A', PATCH) + XX(CONNECT, 1, 'H', CHECKOUT) + XX(CONNECT, 2, 'P', COPY) + XX(MKCOL, 1, 'O', MOVE) + XX(MKCOL, 1, 'E', MERGE) + XX(MKCOL, 2, 'A', MKACTIVITY) + XX(MKCOL, 3, 'A', MKCALENDAR) + XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(REPORT, 2, 'B', REBIND) + XX(POST, 1, 'R', PROPFIND) + XX(PROPFIND, 4, 'P', PROPPATCH) + XX(PUT, 2, 'R', PURGE) + XX(LOCK, 1, 'I', LINK) + XX(UNLOCK, 2, 'S', UNSUBSCRIBE) + XX(UNLOCK, 2, 'B', UNBIND) + XX(UNLOCK, 3, 'I', UNLINK) +#undef XX + + default: SET_ERRNO(HPE_INVALID_METHOD); goto error; - } - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; } - } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { - parser->method = HTTP_PROPPATCH; - } else if (parser->index == 3 && parser->method == HTTP_UNLOCK && ch == 'I') { - parser->method = HTTP_UNLINK; + } else if (ch == '-' && + parser->index == 1 && + parser->method == HTTP_MKCOL) { + parser->method = HTTP_MSEARCH; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c index 26092411c7e16a..7b01dc346b63d9 100644 --- a/deps/http_parser/test.c +++ b/deps/http_parser/test.c @@ -2444,7 +2444,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { va_list ap; size_t i; size_t off = 0; - + va_start(ap, nmsgs); for (i = 0; i < nmsgs; i++) { @@ -3282,10 +3282,10 @@ test_invalid_header_content (int req, const char* str) "HTTP/1.1 200 OK\r\n"; parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); assert(parsed == strlen(buf)); - + buf = str; size_t buflen = strlen(buf); - + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); @@ -3316,10 +3316,10 @@ test_invalid_header_field (int req, const char* str) "HTTP/1.1 200 OK\r\n"; parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); assert(parsed == strlen(buf)); - + buf = str; size_t buflen = strlen(buf); - + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); @@ -3383,7 +3383,7 @@ test_chunked_content_length_error (int req) parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_CHUNKED_WITH_CONTENT_LENGTH); + assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); return; } @@ -3933,6 +3933,11 @@ main (void) test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION); + // Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js + test_simple("GET / HTTP/1.1\r\n" + "Test: Düsseldorf\r\n", + HPE_OK); + // Well-formed but incomplete test_simple("GET / HTTP/1.1\r\n" "Content-Type: text/plain\r\n"