summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2013-12-20 17:33:29 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2013-12-20 17:33:29 +0400
commita35a2f0192f78c762ed1009025e673cf09862d4d (patch)
tree23d1d23eff9bbc2d0737f8ca70923ca8be936b23 /deps
parenta15c44b1756f05c4445151268378ea990a1f5dad (diff)
downloadandroid-node-v8-a35a2f0192f78c762ed1009025e673cf09862d4d.tar.gz
android-node-v8-a35a2f0192f78c762ed1009025e673cf09862d4d.tar.bz2
android-node-v8-a35a2f0192f78c762ed1009025e673cf09862d4d.zip
deps: update http_parser to 2.2
Main changes: * Added support for http statusMessage
Diffstat (limited to 'deps')
-rw-r--r--deps/http_parser/.gitignore5
-rw-r--r--deps/http_parser/.mailmap2
-rw-r--r--deps/http_parser/.travis.yml13
-rw-r--r--deps/http_parser/AUTHORS12
-rw-r--r--deps/http_parser/Makefile61
-rw-r--r--deps/http_parser/README.md53
-rw-r--r--deps/http_parser/contrib/parsertrace.c156
-rw-r--r--deps/http_parser/contrib/url_parser.c (renamed from deps/http_parser/url_parser.c)0
-rw-r--r--deps/http_parser/http_parser.c68
-rw-r--r--deps/http_parser/http_parser.gyp36
-rw-r--r--deps/http_parser/http_parser.h65
-rw-r--r--deps/http_parser/test.c272
12 files changed, 647 insertions, 96 deletions
diff --git a/deps/http_parser/.gitignore b/deps/http_parser/.gitignore
index 3b868c5073..5d12d158a6 100644
--- a/deps/http_parser/.gitignore
+++ b/deps/http_parser/.gitignore
@@ -1,3 +1,4 @@
+/out/
core
tags
*.o
@@ -5,7 +6,9 @@ test
test_g
test_fast
url_parser
+parsertrace
+parsertrace_g
*.mk
*.Makefile
-*.so
+*.so.*
*.a
diff --git a/deps/http_parser/.mailmap b/deps/http_parser/.mailmap
index c73c0f93e4..75a187c568 100644
--- a/deps/http_parser/.mailmap
+++ b/deps/http_parser/.mailmap
@@ -3,3 +3,5 @@
Ryan Dahl <ry@tinyclouds.org>
Salman Haq <salman.haq@asti-usa.com>
Simon Zimmermann <simonz05@gmail.com>
+Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>
+Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>
diff --git a/deps/http_parser/.travis.yml b/deps/http_parser/.travis.yml
new file mode 100644
index 0000000000..ae85af020a
--- /dev/null
+++ b/deps/http_parser/.travis.yml
@@ -0,0 +1,13 @@
+language: c
+
+compiler:
+ - clang
+ - gcc
+
+script:
+ - "make"
+
+notifications:
+ email: false
+ irc:
+ - "irc.freenode.net#libuv"
diff --git a/deps/http_parser/AUTHORS b/deps/http_parser/AUTHORS
index c0d2fe4d52..3527d16e82 100644
--- a/deps/http_parser/AUTHORS
+++ b/deps/http_parser/AUTHORS
@@ -28,10 +28,20 @@ Andre Caron <andre.l.caron@gmail.com>
Ivo Raisr <ivosh@ivosh.net>
James McLaughlin <jamie@lacewing-project.org>
David Gwynne <loki@animata.net>
-LE ROUX Thomas <thomas@procheo.fr>
+Thomas LE ROUX <thomas@november-eleven.fr>
Randy Rizun <rrizun@ortivawireless.com>
Andre Louis Caron <andre.louis.caron@usherbrooke.ca>
Simon Zimmermann <simonz05@gmail.com>
Erik Dubbelboer <erik@dubbelboer.com>
Martell Malone <martellmalone@gmail.com>
Bertrand Paquet <bpaquet@octo.com>
+BogDan Vatra <bogdan@kde.org>
+Peter Faiman <peter@thepicard.org>
+Corey Richardson <corey@octayn.net>
+Tóth Tamás <tomika_nospam@freemail.hu>
+Patrik Stutz <patrik.stutz@gmail.com>
+Cam Swords <cam.swords@gmail.com>
+Chris Dickinson <christopher.s.dickinson@gmail.com>
+Uli Köhler <ukoehler@btronik.de>
+Charlie Somerville <charlie@charliesomerville.com>
+Fedor Indutny <fedor.indutny@gmail.com>
diff --git a/deps/http_parser/Makefile b/deps/http_parser/Makefile
index d9bf839b20..0fd07d8f4a 100644
--- a/deps/http_parser/Makefile
+++ b/deps/http_parser/Makefile
@@ -1,10 +1,33 @@
+# Copyright Joyent, Inc. and other Node contributors. 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
+# rights to use, copy, modify, merge, publish, 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.
+
+PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
+SONAME ?= libhttp_parser.so.2.2
+
CC?=gcc
AR?=ar
CPPFLAGS += -I.
-CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1 -DHTTP_PARSER_DEBUG=1
+CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
-CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0 -DHTTP_PARSER_DEBUG=0
+CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
CFLAGS += -Wall -Wextra -Werror
@@ -12,6 +35,13 @@ CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
+LDFLAGS_LIB = $(LDFLAGS) -shared
+
+ifneq (darwin,$(PLATFORM))
+# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
+LDFLAGS_LIB += -Wl,-soname=$(SONAME)
+endif
+
test: test_g test_fast
./test_g
./test_fast
@@ -31,12 +61,6 @@ test_fast: http_parser.o test.o http_parser.h
test.o: test.c http_parser.h Makefile
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
-url_parser: http_parser_g.o url_parser.o
- $(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o url_parser.o -o $@
-
-url_parser.o: url_parser.c http_parser.h Makefile
- $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c url_parser.c -o $@
-
http_parser.o: http_parser.c http_parser.h Makefile
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
@@ -50,15 +74,32 @@ libhttp_parser.o: http_parser.c http_parser.h Makefile
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
library: libhttp_parser.o
- $(CC) -shared -o libhttp_parser.so libhttp_parser.o
+ $(CC) $(LDFLAGS_LIB) -o $(SONAME) $<
package: http_parser.o
$(AR) rcs libhttp_parser.a http_parser.o
+url_parser: http_parser.o contrib/url_parser.c
+ $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@
+
+url_parser_g: http_parser_g.o contrib/url_parser.c
+ $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
+
+parsertrace: http_parser.o contrib/parsertrace.c
+ $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace
+
+parsertrace_g: http_parser_g.o contrib/parsertrace.c
+ $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g
+
tags: http_parser.c http_parser.h test.c
ctags $^
clean:
- rm -f *.o *.a test test_fast test_g url_parser http_parser.tar tags libhttp_parser.so libhttp_parser.o
+ rm -f *.o *.a tags test test_fast test_g \
+ http_parser.tar libhttp_parser.so.* \
+ url_parser url_parser_g parsertrace parsertrace_g
+
+contrib/url_parser.c: http_parser.h
+contrib/parsertrace.c: http_parser.h
.PHONY: clean package test-run test-run-timed test-valgrind
diff --git a/deps/http_parser/README.md b/deps/http_parser/README.md
index 3815e36131..0bf5d359ac 100644
--- a/deps/http_parser/README.md
+++ b/deps/http_parser/README.md
@@ -1,6 +1,8 @@
HTTP Parser
===========
+[![Build Status](https://travis-ci.org/joyent/http-parser.png?branch=master)](https://travis-ci.org/joyent/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
applications. It does not make any syscalls nor allocations, it does not
@@ -34,38 +36,41 @@ 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 for a request parser:
+```c
+http_parser_settings settings;
+settings.on_url = my_url_callback;
+settings.on_header_field = my_header_field_callback;
+/* ... */
- http_parser_settings settings;
- settings.on_path = my_path_callback;
- settings.on_header_field = my_header_field_callback;
- /* ... */
-
- http_parser *parser = malloc(sizeof(http_parser));
- http_parser_init(parser, HTTP_REQUEST);
- parser->data = my_socket;
+http_parser *parser = malloc(sizeof(http_parser));
+http_parser_init(parser, HTTP_REQUEST);
+parser->data = my_socket;
+```
When data is received on the socket execute the parser and check for errors.
- size_t len = 80*1024, nparsed;
- char buf[len];
- ssize_t recved;
+```c
+size_t len = 80*1024, nparsed;
+char buf[len];
+ssize_t recved;
- recved = recv(fd, buf, len, 0);
+recved = recv(fd, buf, len, 0);
- if (recved < 0) {
- /* Handle error. */
- }
+if (recved < 0) {
+ /* Handle error. */
+}
- /* Start up / continue the parser.
- * Note we pass recved==0 to signal that EOF has been recieved.
- */
- nparsed = http_parser_execute(parser, &settings, buf, recved);
+/* Start up / continue the parser.
+ * Note we pass recved==0 to signal that EOF has been recieved.
+ */
+nparsed = http_parser_execute(parser, &settings, buf, recved);
- if (parser->upgrade) {
- /* handle new protocol */
- } else if (nparsed != recved) {
- /* Handle error. Usually just close the connection. */
- }
+if (parser->upgrade) {
+ /* handle new protocol */
+} else if (nparsed != recved) {
+ /* 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
diff --git a/deps/http_parser/contrib/parsertrace.c b/deps/http_parser/contrib/parsertrace.c
new file mode 100644
index 0000000000..c9bc71ec01
--- /dev/null
+++ b/deps/http_parser/contrib/parsertrace.c
@@ -0,0 +1,156 @@
+/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
+ *
+ * Additional changes are licensed under the same terms as NGINX and
+ * copyright Joyent, Inc. and other Node contributors. 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
+ * rights to use, copy, modify, merge, publish, 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.
+ */
+
+/* Dump what the parser finds to stdout as it happen */
+
+#include "http_parser.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int on_message_begin(http_parser* _) {
+ (void)_;
+ printf("\n***MESSAGE BEGIN***\n\n");
+ return 0;
+}
+
+int on_headers_complete(http_parser* _) {
+ (void)_;
+ printf("\n***HEADERS COMPLETE***\n\n");
+ return 0;
+}
+
+int on_message_complete(http_parser* _) {
+ (void)_;
+ printf("\n***MESSAGE COMPLETE***\n\n");
+ return 0;
+}
+
+int on_url(http_parser* _, const char* at, size_t length) {
+ (void)_;
+ printf("Url: %.*s\n", (int)length, at);
+ return 0;
+}
+
+int on_header_field(http_parser* _, const char* at, size_t length) {
+ (void)_;
+ printf("Header field: %.*s\n", (int)length, at);
+ return 0;
+}
+
+int on_header_value(http_parser* _, const char* at, size_t length) {
+ (void)_;
+ printf("Header value: %.*s\n", (int)length, at);
+ return 0;
+}
+
+int on_body(http_parser* _, const char* at, size_t length) {
+ (void)_;
+ printf("Body: %.*s\n", (int)length, at);
+ return 0;
+}
+
+void usage(const char* name) {
+ fprintf(stderr,
+ "Usage: %s $type $filename\n"
+ " type: -x, where x is one of {r,b,q}\n"
+ " parses file as a Response, reQuest, or Both\n",
+ name);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char* argv[]) {
+ enum http_parser_type file_type;
+
+ if (argc != 3) {
+ usage(argv[0]);
+ }
+
+ char* type = argv[1];
+ if (type[0] != '-') {
+ usage(argv[0]);
+ }
+
+ switch (type[1]) {
+ /* in the case of "-", type[1] will be NUL */
+ case 'r':
+ file_type = HTTP_RESPONSE;
+ break;
+ case 'q':
+ file_type = HTTP_REQUEST;
+ break;
+ case 'b':
+ file_type = HTTP_BOTH;
+ break;
+ default:
+ usage(argv[0]);
+ }
+
+ char* filename = argv[2];
+ FILE* file = fopen(filename, "r");
+ if (file == NULL) {
+ perror("fopen");
+ return EXIT_FAILURE;
+ }
+
+ fseek(file, 0, SEEK_END);
+ long file_length = ftell(file);
+ if (file_length == -1) {
+ perror("ftell");
+ return EXIT_FAILURE;
+ }
+ fseek(file, 0, SEEK_SET);
+
+ char* data = malloc(file_length);
+ if (fread(data, 1, file_length, file) != (size_t)file_length) {
+ fprintf(stderr, "couldn't read entire file\n");
+ free(data);
+ return EXIT_FAILURE;
+ }
+
+ http_parser_settings settings;
+ memset(&settings, 0, sizeof(settings));
+ settings.on_message_begin = on_message_begin;
+ settings.on_url = on_url;
+ settings.on_header_field = on_header_field;
+ settings.on_header_value = on_header_value;
+ settings.on_headers_complete = on_headers_complete;
+ settings.on_body = on_body;
+ settings.on_message_complete = on_message_complete;
+
+ http_parser parser;
+ http_parser_init(&parser, file_type);
+ size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);
+ free(data);
+
+ if (nparsed != (size_t)file_length) {
+ fprintf(stderr,
+ "Error: %s (%s)\n",
+ http_errno_description(HTTP_PARSER_ERRNO(&parser)),
+ http_errno_name(HTTP_PARSER_ERRNO(&parser)));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/deps/http_parser/url_parser.c b/deps/http_parser/contrib/url_parser.c
index b1f9c979f2..b1f9c979f2 100644
--- a/deps/http_parser/url_parser.c
+++ b/deps/http_parser/contrib/url_parser.c
diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c
index 55d7716228..b9dabb870c 100644
--- a/deps/http_parser/http_parser.c
+++ b/deps/http_parser/http_parser.c
@@ -51,18 +51,10 @@
# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
#endif
-#if HTTP_PARSER_DEBUG
-#define SET_ERRNO(e) \
-do { \
- parser->http_errno = (e); \
- parser->error_lineno = __LINE__; \
-} while (0)
-#else
#define SET_ERRNO(e) \
do { \
parser->http_errno = (e); \
} while(0)
-#endif
/* Run the notify callback FOR, returning ER if it fails */
@@ -256,6 +248,7 @@ enum state
, s_res_http_minor
, s_res_first_status_code
, s_res_status_code
+ , s_res_status_start
, s_res_status
, s_res_line_almost_done
@@ -589,6 +582,7 @@ size_t http_parser_execute (http_parser *parser,
const char *header_value_mark = 0;
const char *url_mark = 0;
const char *body_mark = 0;
+ const char *status_mark = 0;
/* We're in an error state. Don't bother doing anything. */
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
@@ -635,6 +629,9 @@ size_t http_parser_execute (http_parser *parser,
case s_req_fragment:
url_mark = data;
break;
+ case s_res_status:
+ status_mark = data;
+ break;
}
for (p=data; p != data + len; p++) {
@@ -642,7 +639,17 @@ size_t http_parser_execute (http_parser *parser,
if (PARSING_HEADER(parser->state)) {
++parser->nread;
- /* Buffer overflow attack */
+ /* Don't allow the total size of the HTTP headers (including the status
+ * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect
+ * embedders against denial-of-service attacks where the attacker feeds
+ * us a never-ending header that the embedder keeps buffering.
+ *
+ * This check is arguably the responsibility of embedders but we're doing
+ * it on the embedder's behalf because most won't bother and this way we
+ * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger
+ * than any reasonable request or response so this should never affect
+ * day-to-day operation.
+ */
if (parser->nread > HTTP_MAX_HEADER_SIZE) {
SET_ERRNO(HPE_HEADER_OVERFLOW);
goto error;
@@ -831,7 +838,7 @@ size_t http_parser_execute (http_parser *parser,
if (!IS_NUM(ch)) {
switch (ch) {
case ' ':
- parser->state = s_res_status;
+ parser->state = s_res_status_start;
break;
case CR:
parser->state = s_res_line_almost_done;
@@ -857,18 +864,37 @@ size_t http_parser_execute (http_parser *parser,
break;
}
+ case s_res_status_start:
+ {
+ if (ch == CR) {
+ parser->state = s_res_line_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ parser->state = s_header_field_start;
+ break;
+ }
+
+ MARK(status);
+ parser->state = s_res_status;
+ parser->index = 0;
+ break;
+ }
+
case s_res_status:
- /* the human readable status. e.g. "NOT FOUND"
- * we are not humans so just ignore this */
if (ch == CR) {
parser->state = s_res_line_almost_done;
+ CALLBACK_DATA(status);
break;
}
if (ch == LF) {
parser->state = s_header_field_start;
+ CALLBACK_DATA(status);
break;
}
+
break;
case s_res_line_almost_done:
@@ -1851,12 +1877,14 @@ size_t http_parser_execute (http_parser *parser,
assert(((header_field_mark ? 1 : 0) +
(header_value_mark ? 1 : 0) +
(url_mark ? 1 : 0) +
- (body_mark ? 1 : 0)) <= 1);
+ (body_mark ? 1 : 0) +
+ (status_mark ? 1 : 0)) <= 1);
CALLBACK_DATA_NOADVANCE(header_field);
CALLBACK_DATA_NOADVANCE(header_value);
CALLBACK_DATA_NOADVANCE(url);
CALLBACK_DATA_NOADVANCE(body);
+ CALLBACK_DATA_NOADVANCE(status);
return len;
@@ -1987,7 +2015,7 @@ http_parse_host_char(enum http_host_state s, const char ch) {
/* FALLTHROUGH */
case s_http_host_v6_start:
- if (IS_HEX(ch) || ch == ':') {
+ if (IS_HEX(ch) || ch == ':' || ch == '.') {
return s_http_host_v6;
}
@@ -2192,3 +2220,15 @@ http_parser_pause(http_parser *parser, int paused) {
assert(0 && "Attempting to pause parser in error state");
}
}
+
+int
+http_body_is_final(const struct http_parser *parser) {
+ return parser->state == s_message_done;
+}
+
+unsigned long
+http_parser_version(void) {
+ return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
+ HTTP_PARSER_VERSION_MINOR * 0x00100 |
+ HTTP_PARSER_VERSION_PATCH * 0x00001;
+}
diff --git a/deps/http_parser/http_parser.gyp b/deps/http_parser/http_parser.gyp
index c6eada707f..ef34ecaeae 100644
--- a/deps/http_parser/http_parser.gyp
+++ b/deps/http_parser/http_parser.gyp
@@ -12,6 +12,7 @@
# RuntimeLibrary MUST MATCH across the entire project
'Debug': {
'defines': [ 'DEBUG', '_DEBUG' ],
+ 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 1, # static debug
@@ -20,6 +21,7 @@
},
'Release': {
'defines': [ 'NDEBUG' ],
+ 'cflags': [ '-Wall', '-Wextra', '-O3' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 0, # static release
@@ -51,6 +53,7 @@
'type': 'static_library',
'include_dirs': [ '.' ],
'direct_dependent_settings': {
+ 'defines': [ 'HTTP_PARSER_STRICT=0' ],
'include_dirs': [ '.' ],
},
'defines': [ 'HTTP_PARSER_STRICT=0' ],
@@ -69,11 +72,40 @@
},
{
- 'target_name': 'test',
+ 'target_name': 'http_parser_strict',
+ 'type': 'static_library',
+ 'include_dirs': [ '.' ],
+ 'direct_dependent_settings': {
+ 'defines': [ 'HTTP_PARSER_STRICT=1' ],
+ 'include_dirs': [ '.' ],
+ },
+ 'defines': [ 'HTTP_PARSER_STRICT=1' ],
+ 'sources': [ './http_parser.c', ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ # Compile as C++. http_parser.c is actually C99, but C++ is
+ # close enough in this case.
+ 'CompileAs': 2,
+ },
+ },
+ }]
+ ],
+ },
+
+ {
+ 'target_name': 'test-nonstrict',
'type': 'executable',
'dependencies': [ 'http_parser' ],
'sources': [ 'test.c' ]
+ },
+
+ {
+ 'target_name': 'test-strict',
+ 'type': 'executable',
+ 'dependencies': [ 'http_parser_strict' ],
+ 'sources': [ 'test.c' ]
}
]
}
-
diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h
index 7908ad03bb..1a91c23f2b 100644
--- a/deps/http_parser/http_parser.h
+++ b/deps/http_parser/http_parser.h
@@ -24,12 +24,15 @@
extern "C" {
#endif
-#define HTTP_PARSER_VERSION_MAJOR 1
-#define HTTP_PARSER_VERSION_MINOR 0
+/* Also update SONAME in the Makefile whenever you change these. */
+#define HTTP_PARSER_VERSION_MAJOR 2
+#define HTTP_PARSER_VERSION_MINOR 2
+#define HTTP_PARSER_VERSION_PATCH 0
#include <sys/types.h>
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
#include <BaseTsd.h>
+#include <stddef.h>
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
@@ -38,8 +41,6 @@ typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
-typedef SIZE_T size_t;
-typedef SSIZE_T ssize_t;
#else
#include <stdint.h>
#endif
@@ -51,14 +52,6 @@ typedef SSIZE_T ssize_t;
# define HTTP_PARSER_STRICT 1
#endif
-/* Compile with -DHTTP_PARSER_DEBUG=1 to add extra debugging information to
- * the error reporting facility.
- */
-#ifndef HTTP_PARSER_DEBUG
-# define HTTP_PARSER_DEBUG 0
-#endif
-
-
/* Maximium header size allowed */
#define HTTP_MAX_HEADER_SIZE (80*1024)
@@ -77,7 +70,7 @@ typedef struct http_parser_settings http_parser_settings;
* chunked' headers that indicate the presence of a body.
*
* 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"
+ * many times for each string. E.G. you might get 10 callbacks for "on_url"
* each providing just a few characters more data.
*/
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
@@ -156,6 +149,7 @@ enum flags
XX(CB_headers_complete, "the on_headers_complete callback failed") \
XX(CB_body, "the on_body callback failed") \
XX(CB_message_complete, "the on_message_complete callback failed") \
+ XX(CB_status, "the on_status callback failed") \
\
/* Parsing-related errors */ \
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
@@ -196,21 +190,14 @@ enum http_errno {
/* Get an http_errno value from an http_parser */
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
-/* Get the line number that generated the current error */
-#if HTTP_PARSER_DEBUG
-#define HTTP_PARSER_ERRNO_LINE(p) ((p)->error_lineno)
-#else
-#define HTTP_PARSER_ERRNO_LINE(p) 0
-#endif
-
struct http_parser {
/** PRIVATE **/
- unsigned char type : 2; /* enum http_parser_type */
- unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
- unsigned char state; /* enum state from http_parser.c */
- unsigned char header_state; /* enum header_state from http_parser.c */
- unsigned char index; /* index into current matcher */
+ unsigned int type : 2; /* enum http_parser_type */
+ unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
+ unsigned int state : 8; /* enum state from http_parser.c */
+ unsigned int header_state : 8; /* enum header_state from http_parser.c */
+ unsigned int index : 8; /* index into current matcher */
uint32_t nread; /* # bytes read in various scenarios */
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
@@ -218,20 +205,16 @@ struct http_parser {
/** READ-ONLY **/
unsigned short http_major;
unsigned short http_minor;
- unsigned short status_code; /* responses only */
- unsigned char method; /* requests only */
- unsigned char http_errno : 7;
+ unsigned int status_code : 16; /* responses only */
+ unsigned int method : 8; /* requests only */
+ unsigned int http_errno : 7;
/* 1 = Upgrade header was present and the parser has exited because of that.
* 0 = No upgrade header present.
* Should be checked when http_parser_execute() returns in addition to
* error checking.
*/
- unsigned char upgrade : 1;
-
-#if HTTP_PARSER_DEBUG
- uint32_t error_lineno;
-#endif
+ unsigned int upgrade : 1;
/** PUBLIC **/
void *data; /* A pointer to get hook to the "connection" or "socket" object */
@@ -241,6 +224,7 @@ struct http_parser {
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
+ http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;
@@ -279,6 +263,18 @@ struct http_parser_url {
};
+/* Returns the library version. Bits 16-23 contain the major version number,
+ * bits 8-15 the minor version number and bits 0-7 the patch level.
+ * Usage example:
+ *
+ * unsigned long version = http_parser_version();
+ * unsigned major = (version >> 16) & 255;
+ * unsigned minor = (version >> 8) & 255;
+ * unsigned patch = version & 255;
+ * printf("http_parser v%u.%u.%u\n", major, minor, version);
+ */
+unsigned long http_parser_version(void);
+
void http_parser_init(http_parser *parser, enum http_parser_type type);
@@ -313,6 +309,9 @@ int http_parser_parse_url(const char *buf, size_t buflen,
/* Pause or un-pause the parser; a nonzero value pauses */
void http_parser_pause(http_parser *parser, int paused);
+/* Checks if this is the final chunk of the body. */
+int http_body_is_final(const http_parser *parser);
+
#ifdef __cplusplus
}
#endif
diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c
index 46d817bb38..6a05b0d3a4 100644
--- a/deps/http_parser/test.c
+++ b/deps/http_parser/test.c
@@ -26,13 +26,19 @@
#include <string.h>
#include <stdarg.h>
+#if defined(__APPLE__)
+# undef strlcat
+# undef strlncpy
+# undef strlcpy
+#endif /* defined(__APPLE__) */
+
#undef TRUE
#define TRUE 1
#undef FALSE
#define FALSE 0
#define MAX_HEADERS 13
-#define MAX_ELEMENT_SIZE 500
+#define MAX_ELEMENT_SIZE 2048
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -44,6 +50,7 @@ struct message {
enum http_parser_type type;
enum http_method method;
int status_code;
+ char response_status[MAX_ELEMENT_SIZE];
char request_path[MAX_ELEMENT_SIZE];
char request_url[MAX_ELEMENT_SIZE];
char fragment[MAX_ELEMENT_SIZE];
@@ -67,6 +74,7 @@ struct message {
int headers_complete_cb_called;
int message_complete_cb_called;
int message_complete_on_eof;
+ int body_is_final;
};
static int currently_parsing_eof;
@@ -926,6 +934,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 301
+ ,.response_status= "Moved Permanently"
,.num_headers= 8
,.headers=
{ { "Location", "http://www.google.com/" }
@@ -974,6 +983,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 5
,.headers=
{ { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
@@ -1002,6 +1012,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 404
+ ,.response_status= "Not Found"
,.num_headers= 0
,.headers= {}
,.body_size= 0
@@ -1017,6 +1028,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 301
+ ,.response_status= ""
,.num_headers= 0
,.headers= {}
,.body= ""
@@ -1042,6 +1054,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 2
,.headers=
{ {"Content-Type", "text/plain" }
@@ -1067,6 +1080,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 2
,.headers=
{ {"Content-Type", "text/html; charset=utf-8" }
@@ -1090,6 +1104,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 4
,.headers=
{ {"Content-Type", "text/html; charset=UTF-8" }
@@ -1115,6 +1130,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 4
,.headers=
{ {"Server", "DCLK-AdSvr" }
@@ -1147,6 +1163,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 301
+ ,.response_status= "Moved Permanently"
,.num_headers= 9
,.headers=
{ { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
@@ -1185,6 +1202,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 11
,.headers=
{ { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
@@ -1216,6 +1234,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 500
+ ,.response_status= "Oriëntatieprobleem"
,.num_headers= 3
,.headers=
{ { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
@@ -1236,6 +1255,7 @@ const struct message responses[] =
,.http_major= 0
,.http_minor= 9
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 0
,.headers=
{}
@@ -1258,6 +1278,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Content-Type", "text/plain" }
@@ -1276,6 +1297,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Connection", "keep-alive" }
@@ -1295,6 +1317,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 204
+ ,.response_status= "No content"
,.num_headers= 1
,.headers=
{ { "Connection", "keep-alive" }
@@ -1313,6 +1336,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 0
,.headers={}
,.body_size= 0
@@ -1329,6 +1353,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 204
+ ,.response_status= "No content"
,.num_headers= 0
,.headers={}
,.body_size= 0
@@ -1346,6 +1371,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 204
+ ,.response_status= "No content"
,.num_headers= 1
,.headers=
{ { "Connection", "close" }
@@ -1367,6 +1393,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Transfer-Encoding", "chunked" }
@@ -1395,6 +1422,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 7
,.headers=
{ { "Server", "Microsoft-IIS/6.0" }
@@ -1409,14 +1437,138 @@ const struct message responses[] =
}
#endif /* !HTTP_PARSER_STRICT */
+#define AMAZON_COM 20
+, {.name= "amazon.com"
+ ,.type= HTTP_RESPONSE
+ ,.raw= "HTTP/1.1 301 MovedPermanently\r\n"
+ "Date: Wed, 15 May 2013 17:06:33 GMT\r\n"
+ "Server: Server\r\n"
+ "x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n"
+ "p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n"
+ "x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n"
+ "Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n"
+ "Vary: Accept-Encoding,User-Agent\r\n"
+ "Content-Type: text/html; charset=ISO-8859-1\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n"
+ ,.should_keep_alive= TRUE
+ ,.message_complete_on_eof= FALSE
+ ,.http_major= 1
+ ,.http_minor= 1
+ ,.status_code= 301
+ ,.response_status= "MovedPermanently"
+ ,.num_headers= 9
+ ,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" }
+ , { "Server", "Server" }
+ , { "x-amz-id-1", "0GPHKXSJQ826RK7GZEB2" }
+ , { "p3p", "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" }
+ , { "x-amz-id-2", "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" }
+ , { "Location", "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" }
+ , { "Vary", "Accept-Encoding,User-Agent" }
+ , { "Content-Type", "text/html; charset=ISO-8859-1" }
+ , { "Transfer-Encoding", "chunked" }
+ }
+ ,.body= "\n"
+ }
+
+#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
+, {.name= "empty reason phrase after space"
+ ,.type= HTTP_RESPONSE
+ ,.raw= "HTTP/1.1 200 \r\n"
+ "\r\n"
+ ,.should_keep_alive= FALSE
+ ,.message_complete_on_eof= TRUE
+ ,.http_major= 1
+ ,.http_minor= 1
+ ,.status_code= 200
+ ,.response_status= ""
+ ,.num_headers= 0
+ ,.headers= {}
+ ,.body= ""
+ }
+
, {.name= NULL } /* sentinel */
};
+/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
+ * define it ourselves.
+ */
+size_t
+strnlen(const char *s, size_t maxlen)
+{
+ const char *p;
+
+ p = memchr(s, '\0', maxlen);
+ if (p == NULL)
+ return maxlen;
+
+ return p - s;
+}
+
+size_t
+strlncat(char *dst, size_t len, const char *src, size_t n)
+{
+ size_t slen;
+ size_t dlen;
+ size_t rlen;
+ size_t ncpy;
+
+ slen = strnlen(src, n);
+ dlen = strnlen(dst, len);
+
+ if (dlen < len) {
+ rlen = len - dlen;
+ ncpy = slen < rlen ? slen : (rlen - 1);
+ memcpy(dst + dlen, src, ncpy);
+ dst[dlen + ncpy] = '\0';
+ }
+
+ assert(len > slen + dlen);
+ return slen + dlen;
+}
+
+size_t
+strlcat(char *dst, const char *src, size_t len)
+{
+ return strlncat(dst, len, src, (size_t) -1);
+}
+
+size_t
+strlncpy(char *dst, size_t len, const char *src, size_t n)
+{
+ size_t slen;
+ size_t ncpy;
+
+ slen = strnlen(src, n);
+
+ if (len > 0) {
+ ncpy = slen < len ? slen : (len - 1);
+ memcpy(dst, src, ncpy);
+ dst[ncpy] = '\0';
+ }
+
+ assert(len > slen);
+ return slen;
+}
+
+size_t
+strlcpy(char *dst, const char *src, size_t len)
+{
+ return strlncpy(dst, len, src, (size_t) -1);
+}
+
int
request_url_cb (http_parser *p, const char *buf, size_t len)
{
assert(p == parser);
- strncat(messages[num_messages].request_url, buf, len);
+ strlncat(messages[num_messages].request_url,
+ sizeof(messages[num_messages].request_url),
+ buf,
+ len);
return 0;
}
@@ -1429,7 +1581,10 @@ header_field_cb (http_parser *p, const char *buf, size_t len)
if (m->last_header_element != FIELD)
m->num_headers++;
- strncat(m->headers[m->num_headers-1][0], buf, len);
+ strlncat(m->headers[m->num_headers-1][0],
+ sizeof(m->headers[m->num_headers-1][0]),
+ buf,
+ len);
m->last_header_element = FIELD;
@@ -1442,19 +1597,39 @@ header_value_cb (http_parser *p, const char *buf, size_t len)
assert(p == parser);
struct message *m = &messages[num_messages];
- strncat(m->headers[m->num_headers-1][1], buf, len);
+ strlncat(m->headers[m->num_headers-1][1],
+ sizeof(m->headers[m->num_headers-1][1]),
+ buf,
+ len);
m->last_header_element = VALUE;
return 0;
}
+void
+check_body_is_final (const http_parser *p)
+{
+ if (messages[num_messages].body_is_final) {
+ fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
+ "on last on_body callback call "
+ "but it doesn't! ***\n\n");
+ assert(0);
+ abort();
+ }
+ messages[num_messages].body_is_final = http_body_is_final(p);
+}
+
int
body_cb (http_parser *p, const char *buf, size_t len)
{
assert(p == parser);
- strncat(messages[num_messages].body, buf, len);
+ strlncat(messages[num_messages].body,
+ sizeof(messages[num_messages].body),
+ buf,
+ len);
messages[num_messages].body_size += len;
+ check_body_is_final(p);
// printf("body_cb: '%s'\n", requests[num_messages].body);
return 0;
}
@@ -1465,6 +1640,7 @@ count_body_cb (http_parser *p, const char *buf, size_t len)
assert(p == parser);
assert(buf);
messages[num_messages].body_size += len;
+ check_body_is_final(p);
return 0;
}
@@ -1501,6 +1677,18 @@ message_complete_cb (http_parser *p)
assert(0);
abort();
}
+
+ if (messages[num_messages].body_size &&
+ http_body_is_final(p) &&
+ !messages[num_messages].body_is_final)
+ {
+ fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
+ "on last on_body callback call "
+ "but it doesn't! ***\n\n");
+ assert(0);
+ abort();
+ }
+
messages[num_messages].message_complete_cb_called = TRUE;
messages[num_messages].message_complete_on_eof = currently_parsing_eof;
@@ -1509,6 +1697,17 @@ message_complete_cb (http_parser *p)
return 0;
}
+int
+response_status_cb (http_parser *p, const char *buf, size_t len)
+{
+ assert(p == parser);
+ strlncat(messages[num_messages].response_status,
+ sizeof(messages[num_messages].response_status),
+ buf,
+ len);
+ return 0;
+}
+
/* These dontcall_* callbacks exist so that we can verify that when we're
* paused, no additional callbacks are invoked */
int
@@ -1569,11 +1768,20 @@ dontcall_message_complete_cb (http_parser *p)
abort();
}
+int
+dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
+{
+ if (p || buf || len) { } // gcc
+ fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n");
+ abort();
+}
+
static http_parser_settings settings_dontcall =
{.on_message_begin = dontcall_message_begin_cb
,.on_header_field = dontcall_header_field_cb
,.on_header_value = dontcall_header_value_cb
,.on_url = dontcall_request_url_cb
+ ,.on_status = dontcall_response_status_cb
,.on_body = dontcall_body_cb
,.on_headers_complete = dontcall_headers_complete_cb
,.on_message_complete = dontcall_message_complete_cb
@@ -1639,11 +1847,20 @@ pause_message_complete_cb (http_parser *p)
return message_complete_cb(p);
}
+int
+pause_response_status_cb (http_parser *p, const char *buf, size_t len)
+{
+ http_parser_pause(p, 1);
+ *current_pause_parser = settings_dontcall;
+ return response_status_cb(p, buf, len);
+}
+
static http_parser_settings settings_pause =
{.on_message_begin = pause_message_begin_cb
,.on_header_field = pause_header_field_cb
,.on_header_value = pause_header_value_cb
,.on_url = pause_request_url_cb
+ ,.on_status = pause_response_status_cb
,.on_body = pause_body_cb
,.on_headers_complete = pause_headers_complete_cb
,.on_message_complete = pause_message_complete_cb
@@ -1654,6 +1871,7 @@ static http_parser_settings settings =
,.on_header_field = header_field_cb
,.on_header_value = header_value_cb
,.on_url = request_url_cb
+ ,.on_status = response_status_cb
,.on_body = body_cb
,.on_headers_complete = headers_complete_cb
,.on_message_complete = message_complete_cb
@@ -1664,6 +1882,7 @@ static http_parser_settings settings_count_body =
,.on_header_field = header_field_cb
,.on_header_value = header_value_cb
,.on_url = request_url_cb
+ ,.on_status = response_status_cb
,.on_body = count_body_cb
,.on_headers_complete = headers_complete_cb
,.on_message_complete = message_complete_cb
@@ -1674,6 +1893,7 @@ static http_parser_settings settings_null =
,.on_header_field = 0
,.on_header_value = 0
,.on_url = 0
+ ,.on_status = 0
,.on_body = 0
,.on_headers_complete = 0
,.on_message_complete = 0
@@ -1797,6 +2017,7 @@ message_eq (int index, const struct message *expected)
MESSAGE_CHECK_NUM_EQ(expected, m, method);
} else {
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
+ MESSAGE_CHECK_STR_EQ(expected, m, response_status);
}
MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
@@ -1926,8 +2147,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
static void
print_error (const char *raw, size_t error_location)
{
- fprintf(stderr, "\n*** %s:%d -- %s ***\n\n",
- "http_parser.c", HTTP_PARSER_ERRNO_LINE(parser),
+ fprintf(stderr, "\n*** %s ***\n\n",
http_errno_description(HTTP_PARSER_ERRNO(parser)));
int this_line = 0, char_len = 0;
@@ -2108,6 +2328,25 @@ const struct url_test url_tests[] =
,.rv=0
}
+, {.name="ipv4 in ipv6 address"
+ ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/"
+ ,.is_connect=0
+ ,.u=
+ {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
+ ,.port=0
+ ,.field_data=
+ {{ 0, 4 } /* UF_SCHEMA */
+ ,{ 8, 37 } /* UF_HOST */
+ ,{ 0, 0 } /* UF_PORT */
+ ,{ 46, 1 } /* UF_PATH */
+ ,{ 0, 0 } /* UF_QUERY */
+ ,{ 0, 0 } /* UF_FRAGMENT */
+ ,{ 0, 0 } /* UF_USERINFO */
+ }
+ }
+ ,.rv=0
+ }
+
, {.name="extra ? in query string"
,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,"
"fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,"
@@ -2462,7 +2701,7 @@ dump_url (const char *url, const struct http_parser_url *u)
continue;
}
- printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n",
+ printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",
i,
u->field_data[i].off,
u->field_data[i].len,
@@ -2852,15 +3091,15 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
parser_init(type_both ? HTTP_BOTH : r1->type);
buf1_len = i;
- strncpy(buf1, total, buf1_len);
+ strlncpy(buf1, sizeof(buf1), total, buf1_len);
buf1[buf1_len] = 0;
buf2_len = j - i;
- strncpy(buf2, total+i, buf2_len);
+ strlncpy(buf2, sizeof(buf1), total+i, buf2_len);
buf2[buf2_len] = 0;
buf3_len = total_len - j;
- strncpy(buf3, total+j, buf3_len);
+ strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
buf3[buf3_len] = 0;
read = parse(buf1, buf1_len);
@@ -3024,6 +3263,16 @@ main (void)
int i, j, k;
int request_count;
int response_count;
+ unsigned long version;
+ unsigned major;
+ unsigned minor;
+ unsigned patch;
+
+ version = http_parser_version();
+ major = (version >> 16) & 255;
+ minor = (version >> 8) & 255;
+ patch = version & 255;
+ printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version);
printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
@@ -3087,6 +3336,7 @@ main (void)
,.http_major= 1
,.http_minor= 0
,.status_code= 200
+ ,.response_status= "OK"
,.num_headers= 2
,.headers=
{ { "Transfer-Encoding", "chunked" }