Browse Source

deps: update http-parser to 2.6.0

significant updates:

* [[`777ba4eded`](https://github.com/nodejs/node/commit/777ba4eded)] - **src**: introduce `http_parser_url_init` (Fedor Indutny) [nodejs/http-parser#225](https://github.com/nodejs/http-parser/pull/225)
* [[`e557b62744`](https://github.com/nodejs/node/commit/e557b62744)] - **src**: support LINK/UNLINK (RFC 2068, draft-snell-link-method) (Olivier Mengué) [nodejs/http-parser#267](https://github.com/nodejs/http-parser/pull/267)
* [[`eb5e9928b4`](https://github.com/nodejs/node/commit/eb5e9928b4)] - **src**: support ACL (WebDAV, RFC3744, Section 8.1). (Ivan Enderlin) [joyent/http-parser#260](https://github.com/joyent/http-parser/pull/260)
* [[`8b1d652322`](https://github.com/nodejs/node/commit/8b1d652322)] - **src**: support BIND/REBIND/UNBIND (WebDAV, RFC5842) (Ivan Enderlin) [joyent/http-parser#242](https://github.com/joyent/http-parser/pull/242)
* [[`7d75dd7325`](https://github.com/nodejs/node/commit/7d75dd7325)] - **src**: support IPv6 Zone ID as per RFC 6874 (Tatsuhiro Tsujikawa) [joyent/http-parser#253](https://github.com/joyent/http-parser/pull/253)

PR-URL: https://github.com/nodejs/node/pull/3569
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Johan Bergström <bugs@bergstroem.nu>
process-exit-stdio-flushing
James M Snell 9 years ago
parent
commit
d006d6aa46
  1. 1
      deps/http_parser/AUTHORS
  2. 31
      deps/http_parser/Makefile
  3. 69
      deps/http_parser/README.md
  4. 3
      deps/http_parser/contrib/url_parser.c
  5. 99
      deps/http_parser/http_parser.c
  6. 41
      deps/http_parser/http_parser.h
  7. 114
      deps/http_parser/test.c

1
deps/http_parser/AUTHORS

@ -65,3 +65,4 @@ Romain Giraud <giraud.romain@gmail.com>
Jay Satiro <raysatiro@yahoo.com> Jay Satiro <raysatiro@yahoo.com>
Arne Steen <Arne.Steen@gmx.de> Arne Steen <Arne.Steen@gmx.de>
Kjell Schubert <kjell.schubert@gmail.com> Kjell Schubert <kjell.schubert@gmail.com>
Olivier Mengué <dolmen@cpan.org>

31
deps/http_parser/Makefile

@ -19,7 +19,19 @@
# IN THE SOFTWARE. # IN THE SOFTWARE.
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
SONAME ?= libhttp_parser.so.2.5.0 HELPER ?=
BINEXT ?=
ifeq (darwin,$(PLATFORM))
SONAME ?= libhttp_parser.2.6.0.dylib
SOEXT ?= dylib
else ifeq (wine,$(PLATFORM))
CC = winegcc
BINEXT = .exe.so
HELPER = wine
else
SONAME ?= libhttp_parser.so.2.6.0
SOEXT ?= so
endif
CC?=gcc CC?=gcc
AR?=ar AR?=ar
@ -53,8 +65,8 @@ LDFLAGS_LIB += -Wl,-soname=$(SONAME)
endif endif
test: test_g test_fast test: test_g test_fast
./test_g $(HELPER) ./test_g$(BINEXT)
./test_fast $(HELPER) ./test_fast$(BINEXT)
test_g: http_parser_g.o test_g.o test_g: http_parser_g.o test_g.o
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@ $(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
@ -81,7 +93,7 @@ http_parser.o: http_parser.c http_parser.h Makefile
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
test-run-timed: test_fast test-run-timed: test_fast
while(true) do time ./test_fast > /dev/null; done while(true) do time $(HELPER) ./test_fast$(BINEXT) > /dev/null; done
test-valgrind: test_g test-valgrind: test_g
valgrind ./test_g valgrind ./test_g
@ -102,10 +114,10 @@ url_parser_g: http_parser_g.o contrib/url_parser.c
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@ $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
parsertrace: http_parser.o contrib/parsertrace.c parsertrace: http_parser.o contrib/parsertrace.c
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace$(BINEXT)
parsertrace_g: http_parser_g.o contrib/parsertrace.c parsertrace_g: http_parser_g.o contrib/parsertrace.c
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g$(BINEXT)
tags: http_parser.c http_parser.h test.c tags: http_parser.c http_parser.h test.c
ctags $^ ctags $^
@ -113,12 +125,12 @@ tags: http_parser.c http_parser.h test.c
install: library install: library
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h $(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
$(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME) $(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME)
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.so ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
install-strip: library install-strip: library
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h $(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
$(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME) $(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME)
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.so ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
uninstall: uninstall:
rm $(INCLUDEDIR)/http_parser.h rm $(INCLUDEDIR)/http_parser.h
@ -128,7 +140,8 @@ uninstall:
clean: clean:
rm -f *.o *.a tags test test_fast test_g \ rm -f *.o *.a tags test test_fast test_g \
http_parser.tar libhttp_parser.so.* \ http_parser.tar libhttp_parser.so.* \
url_parser url_parser_g parsertrace parsertrace_g url_parser url_parser_g parsertrace parsertrace_g \
*.exe *.exe.so
contrib/url_parser.c: http_parser.h contrib/url_parser.c: http_parser.h
contrib/parsertrace.c: http_parser.h contrib/parsertrace.c: http_parser.h

69
deps/http_parser/README.md

@ -94,7 +94,7 @@ The Special Problem of Upgrade
------------------------------ ------------------------------
HTTP supports upgrading the connection to a different protocol. An HTTP supports upgrading the connection to a different protocol. An
increasingly common example of this is the Web Socket protocol which sends increasingly common example of this is the WebSocket protocol which sends
a request like a request like
GET /demo HTTP/1.1 GET /demo HTTP/1.1
@ -106,8 +106,8 @@ a request like
followed by non-HTTP data. followed by non-HTTP data.
(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more (See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the
information the Web Socket protocol.) WebSocket protocol.)
To support this, the parser will treat this as a normal HTTP message without a To support this, the parser will treat this as a normal HTTP message without a
body, issuing both on_headers_complete and on_message_complete callbacks. However body, issuing both on_headers_complete and on_message_complete callbacks. However
@ -137,6 +137,69 @@ There are two types of callbacks:
Callbacks must return 0 on success. Returning a non-zero value indicates Callbacks must return 0 on success. Returning a non-zero value indicates
error to the parser, making it exit immediately. error to the parser, making it exit immediately.
For cases where it is necessary to pass local information to/from a callback,
the `http_parser` object's `data` field can be used.
An example of such a case is when using threads to handle a socket connection,
parse a request, and then give a response over that socket. By instantiation
of a thread-local struct containing relevant data (e.g. accepted socket,
allocated memory for callbacks to write into, etc), a parser's callbacks are
able to communicate data between the scope of the thread and the scope of the
callback in a threadsafe manner. This allows http-parser to be used in
multi-threaded contexts.
Example:
```
typedef struct {
socket_t sock;
void* buffer;
int buf_len;
} custom_data_t;
int my_url_callback(http_parser* parser, const char *at, size_t length) {
/* access to thread local custom_data_t struct.
Use this access save parsed data for later use into thread local
buffer, or communicate over socket
*/
parser->data;
...
return 0;
}
...
void http_parser_thread(socket_t sock) {
int nparsed = 0;
/* allocate memory for user data */
custom_data_t *my_data = malloc(sizeof(custom_data_t));
/* some information for use by callbacks.
* achieves thread -> callback information flow */
my_data->sock = sock;
/* instantiate a thread-local parser */
http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST); /* initialise parser */
/* this custom data reference is accessible through the reference to the
parser supplied to callback functions */
parser->data = my_data;
http_parser_settings settings; / * set up callbacks */
settings.on_url = my_url_callback;
/* execute parser */
nparsed = http_parser_execute(parser, &settings, buf, recved);
...
/* parsed information copied from callback.
can now perform action on data copied into thread-local memory from callbacks.
achieves callback -> thread information flow */
my_data->buffer;
...
}
```
In case you parse HTTP message in chunks (i.e. `read()` request line In case you parse HTTP message in chunks (i.e. `read()` request line
from socket, parse, read half headers, parse, etc) your data callbacks from socket, parse, read half headers, parse, etc) your data callbacks
may be called more than once. Http-parser guarantees that data pointer is only may be called more than once. Http-parser guarantees that data pointer is only

3
deps/http_parser/contrib/url_parser.c

@ -35,6 +35,7 @@ int main(int argc, char ** argv) {
connect = strcmp("connect", argv[1]) == 0 ? 1 : 0; connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
printf("Parsing %s, connect %d\n", argv[2], connect); printf("Parsing %s, connect %d\n", argv[2], connect);
http_parser_url_init(&u);
result = http_parser_parse_url(argv[2], len, connect, &u); result = http_parser_parse_url(argv[2], len, connect, &u);
if (result != 0) { if (result != 0) {
printf("Parse error : %d\n", result); printf("Parse error : %d\n", result);
@ -43,4 +44,4 @@ int main(int argc, char ** argv) {
printf("Parse ok, result : \n"); printf("Parse ok, result : \n");
dump_url(argv[2], &u); dump_url(argv[2], &u);
return 0; return 0;
} }

99
deps/http_parser/http_parser.c

@ -400,6 +400,8 @@ enum http_host_state
, s_http_host , s_http_host
, s_http_host_v6 , s_http_host_v6
, s_http_host_v6_end , s_http_host_v6_end
, s_http_host_v6_zone_start
, s_http_host_v6_zone
, s_http_host_port_start , s_http_host_port_start
, s_http_host_port , s_http_host_port
}; };
@ -957,21 +959,23 @@ reexecute:
parser->method = (enum http_method) 0; parser->method = (enum http_method) 0;
parser->index = 1; parser->index = 1;
switch (ch) { switch (ch) {
case 'A': parser->method = HTTP_ACL; break;
case 'B': parser->method = HTTP_BIND; break;
case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
case 'D': parser->method = HTTP_DELETE; break; case 'D': parser->method = HTTP_DELETE; break;
case 'G': parser->method = HTTP_GET; break; case 'G': parser->method = HTTP_GET; break;
case 'H': parser->method = HTTP_HEAD; break; case 'H': parser->method = HTTP_HEAD; break;
case 'L': parser->method = HTTP_LOCK; break; case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
case 'N': parser->method = HTTP_NOTIFY; break; case 'N': parser->method = HTTP_NOTIFY; break;
case 'O': parser->method = HTTP_OPTIONS; break; case 'O': parser->method = HTTP_OPTIONS; break;
case 'P': parser->method = HTTP_POST; case 'P': parser->method = HTTP_POST;
/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
break; break;
case 'R': parser->method = HTTP_REPORT; break; case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
case 'T': parser->method = HTTP_TRACE; break; case 'T': parser->method = HTTP_TRACE; break;
case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break; case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
default: default:
SET_ERRNO(HPE_INVALID_METHOD); SET_ERRNO(HPE_INVALID_METHOD);
goto error; goto error;
@ -1027,16 +1031,32 @@ reexecute:
SET_ERRNO(HPE_INVALID_METHOD); SET_ERRNO(HPE_INVALID_METHOD);
goto error; goto error;
} }
} else if (parser->index == 1 && parser->method == HTTP_POST) { } else if (parser->method == HTTP_REPORT) {
if (ch == 'R') { if (parser->index == 2 && ch == 'B') {
parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ parser->method = HTTP_REBIND;
} else if (ch == 'U') { } else {
parser->method = HTTP_PUT; /* or HTTP_PURGE */ SET_ERRNO(HPE_INVALID_METHOD);
} else if (ch == 'A') { goto error;
parser->method = HTTP_PATCH; }
} else { } else if (parser->index == 1) {
SET_ERRNO(HPE_INVALID_METHOD); if (parser->method == HTTP_POST) {
goto error; 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) { } else if (parser->index == 2) {
if (parser->method == HTTP_PUT) { if (parser->method == HTTP_PUT) {
@ -1049,6 +1069,8 @@ reexecute:
} else if (parser->method == HTTP_UNLOCK) { } else if (parser->method == HTTP_UNLOCK) {
if (ch == 'S') { if (ch == 'S') {
parser->method = HTTP_UNSUBSCRIBE; parser->method = HTTP_UNSUBSCRIBE;
} else if(ch == 'B') {
parser->method = HTTP_UNBIND;
} else { } else {
SET_ERRNO(HPE_INVALID_METHOD); SET_ERRNO(HPE_INVALID_METHOD);
goto error; goto error;
@ -1059,6 +1081,8 @@ reexecute:
} }
} else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
parser->method = HTTP_PROPPATCH; parser->method = HTTP_PROPPATCH;
} else if (parser->index == 3 && parser->method == HTTP_UNLOCK && ch == 'I') {
parser->method = HTTP_UNLINK;
} else { } else {
SET_ERRNO(HPE_INVALID_METHOD); SET_ERRNO(HPE_INVALID_METHOD);
goto error; goto error;
@ -1828,11 +1852,12 @@ reexecute:
case s_headers_done: case s_headers_done:
{ {
int hasBody;
STRICT_CHECK(ch != LF); STRICT_CHECK(ch != LF);
parser->nread = 0; parser->nread = 0;
int hasBody = parser->flags & F_CHUNKED || hasBody = parser->flags & F_CHUNKED ||
(parser->content_length > 0 && parser->content_length != ULLONG_MAX); (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
if (parser->upgrade && (parser->method == HTTP_CONNECT || if (parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) { (parser->flags & F_SKIPBODY) || !hasBody)) {
@ -1857,8 +1882,7 @@ reexecute:
/* Content-Length header given and non-zero */ /* Content-Length header given and non-zero */
UPDATE_STATE(s_body_identity); UPDATE_STATE(s_body_identity);
} else { } else {
if (parser->type == HTTP_REQUEST || if (!http_message_needs_eof(parser)) {
!http_message_needs_eof(parser)) {
/* Assume content-length 0 - read the next */ /* Assume content-length 0 - read the next */
UPDATE_STATE(NEW_MESSAGE()); UPDATE_STATE(NEW_MESSAGE());
CALLBACK_NOTIFY(message_complete); CALLBACK_NOTIFY(message_complete);
@ -2153,15 +2177,13 @@ http_parser_settings_init(http_parser_settings *settings)
const char * const char *
http_errno_name(enum http_errno err) { http_errno_name(enum http_errno err) {
assert(((size_t) err) < assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
(sizeof(http_strerror_tab) / sizeof(http_strerror_tab[0])));
return http_strerror_tab[err].name; return http_strerror_tab[err].name;
} }
const char * const char *
http_errno_description(enum http_errno err) { http_errno_description(enum http_errno err) {
assert(((size_t) err) < assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
(sizeof(http_strerror_tab) / sizeof(http_strerror_tab[0])));
return http_strerror_tab[err].description; return http_strerror_tab[err].description;
} }
@ -2214,6 +2236,23 @@ http_parse_host_char(enum http_host_state s, const char ch) {
return s_http_host_v6; return s_http_host_v6;
} }
if (s == s_http_host_v6 && ch == '%') {
return s_http_host_v6_zone_start;
}
break;
case s_http_host_v6_zone:
if (ch == ']') {
return s_http_host_v6_end;
}
/* FALLTHROUGH */
case s_http_host_v6_zone_start:
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
ch == '~') {
return s_http_host_v6_zone;
}
break; break;
case s_http_host_port: case s_http_host_port:
@ -2232,6 +2271,7 @@ http_parse_host_char(enum http_host_state s, const char ch) {
static int static int
http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
assert(u->field_set & (1 << UF_HOST));
enum http_host_state s; enum http_host_state s;
const char *p; const char *p;
@ -2263,6 +2303,11 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
u->field_data[UF_HOST].len++; u->field_data[UF_HOST].len++;
break; break;
case s_http_host_v6_zone_start:
case s_http_host_v6_zone:
u->field_data[UF_HOST].len++;
break;
case s_http_host_port: case s_http_host_port:
if (s != s_http_host_port) { if (s != s_http_host_port) {
u->field_data[UF_PORT].off = p - buf; u->field_data[UF_PORT].off = p - buf;
@ -2292,6 +2337,8 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
case s_http_host_start: case s_http_host_start:
case s_http_host_v6_start: case s_http_host_v6_start:
case s_http_host_v6: case s_http_host_v6:
case s_http_host_v6_zone_start:
case s_http_host_v6_zone:
case s_http_host_port_start: case s_http_host_port_start:
case s_http_userinfo: case s_http_userinfo:
case s_http_userinfo_start: case s_http_userinfo_start:
@ -2303,6 +2350,11 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
return 0; return 0;
} }
void
http_parser_url_init(struct http_parser_url *u) {
memset(u, 0, sizeof(*u));
}
int int
http_parser_parse_url(const char *buf, size_t buflen, int is_connect, http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
struct http_parser_url *u) struct http_parser_url *u)
@ -2376,7 +2428,12 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
/* host must be present if there is a schema */ /* host must be present if there is a schema */
/* parsing http:///toto will fail */ /* parsing http:///toto will fail */
if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) { if ((u->field_set & (1 << UF_SCHEMA)) &&
(u->field_set & (1 << UF_HOST)) == 0) {
return 1;
}
if (u->field_set & (1 << UF_HOST)) {
if (http_parse_host(buf, u, found_at) != 0) { if (http_parse_host(buf, u, found_at) != 0) {
return 1; return 1;
} }

41
deps/http_parser/http_parser.h

@ -26,11 +26,12 @@ extern "C" {
/* Also update SONAME in the Makefile whenever you change these. */ /* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 5 #define HTTP_PARSER_VERSION_MINOR 6
#define HTTP_PARSER_VERSION_PATCH 0 #define HTTP_PARSER_VERSION_PATCH 0
#include <sys/types.h> #include <sys/types.h>
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600) #if defined(_WIN32) && !defined(__MINGW32__) && \
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
#include <BaseTsd.h> #include <BaseTsd.h>
#include <stddef.h> #include <stddef.h>
typedef __int8 int8_t; typedef __int8 int8_t;
@ -95,7 +96,7 @@ typedef int (*http_cb) (http_parser*);
XX(5, CONNECT, CONNECT) \ XX(5, CONNECT, CONNECT) \
XX(6, OPTIONS, OPTIONS) \ XX(6, OPTIONS, OPTIONS) \
XX(7, TRACE, TRACE) \ XX(7, TRACE, TRACE) \
/* webdav */ \ /* WebDAV */ \
XX(8, COPY, COPY) \ XX(8, COPY, COPY) \
XX(9, LOCK, LOCK) \ XX(9, LOCK, LOCK) \
XX(10, MKCOL, MKCOL) \ XX(10, MKCOL, MKCOL) \
@ -104,21 +105,28 @@ typedef int (*http_cb) (http_parser*);
XX(13, PROPPATCH, PROPPATCH) \ XX(13, PROPPATCH, PROPPATCH) \
XX(14, SEARCH, SEARCH) \ XX(14, SEARCH, SEARCH) \
XX(15, UNLOCK, UNLOCK) \ XX(15, UNLOCK, UNLOCK) \
XX(16, BIND, BIND) \
XX(17, REBIND, REBIND) \
XX(18, UNBIND, UNBIND) \
XX(19, ACL, ACL) \
/* subversion */ \ /* subversion */ \
XX(16, REPORT, REPORT) \ XX(20, REPORT, REPORT) \
XX(17, MKACTIVITY, MKACTIVITY) \ XX(21, MKACTIVITY, MKACTIVITY) \
XX(18, CHECKOUT, CHECKOUT) \ XX(22, CHECKOUT, CHECKOUT) \
XX(19, MERGE, MERGE) \ XX(23, MERGE, MERGE) \
/* upnp */ \ /* upnp */ \
XX(20, MSEARCH, M-SEARCH) \ XX(24, MSEARCH, M-SEARCH) \
XX(21, NOTIFY, NOTIFY) \ XX(25, NOTIFY, NOTIFY) \
XX(22, SUBSCRIBE, SUBSCRIBE) \ XX(26, SUBSCRIBE, SUBSCRIBE) \
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
/* RFC-5789 */ \ /* RFC-5789 */ \
XX(24, PATCH, PATCH) \ XX(28, PATCH, PATCH) \
XX(25, PURGE, PURGE) \ XX(29, PURGE, PURGE) \
/* CalDAV */ \ /* CalDAV */ \
XX(26, MKCALENDAR, MKCALENDAR) \ XX(30, MKCALENDAR, MKCALENDAR) \
/* RFC-2068, section 19.6.1.2 */ \
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
enum http_method enum http_method
{ {
@ -144,7 +152,7 @@ enum flags
/* Map for errno-related constants /* Map for errno-related constants
* *
* The provided argument should be a macro that takes 2 arguments. * The provided argument should be a macro that takes 2 arguments.
*/ */
#define HTTP_ERRNO_MAP(XX) \ #define HTTP_ERRNO_MAP(XX) \
@ -325,6 +333,9 @@ const char *http_errno_name(enum http_errno err);
/* Return a string description of the given error */ /* Return a string description of the given error */
const char *http_errno_description(enum http_errno err); const char *http_errno_description(enum http_errno err);
/* Initialize all http_parser_url members to 0 */
void http_parser_url_init(struct http_parser_url *u);
/* Parse a URL; return nonzero on failure */ /* Parse a URL; return nonzero on failure */
int http_parser_parse_url(const char *buf, size_t buflen, int http_parser_parse_url(const char *buf, size_t buflen,
int is_connect, int is_connect,

114
deps/http_parser/test.c

@ -1101,6 +1101,58 @@ const struct message requests[] =
,.body= "" ,.body= ""
} }
/* Examples from the Internet draft for LINK/UNLINK methods:
* https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5
*/
#define LINK_REQUEST 40
, {.name = "link request"
,.type= HTTP_REQUEST
,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n"
"Host: example.com\r\n"
"Link: <http://example.com/profiles/joe>; rel=\"tag\"\r\n"
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
"\r\n"
,.should_keep_alive= TRUE
,.message_complete_on_eof= FALSE
,.http_major= 1
,.http_minor= 1
,.method= HTTP_LINK
,.request_path= "/images/my_dog.jpg"
,.request_url= "/images/my_dog.jpg"
,.query_string= ""
,.fragment= ""
,.num_headers= 3
,.headers= { { "Host", "example.com" }
, { "Link", "<http://example.com/profiles/joe>; rel=\"tag\"" }
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
}
,.body= ""
}
#define UNLINK_REQUEST 41
, {.name = "link request"
,.type= HTTP_REQUEST
,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
"Host: example.com\r\n"
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
"\r\n"
,.should_keep_alive= TRUE
,.message_complete_on_eof= FALSE
,.http_major= 1
,.http_minor= 1
,.method= HTTP_UNLINK
,.request_path= "/images/my_dog.jpg"
,.request_url= "/images/my_dog.jpg"
,.query_string= ""
,.fragment= ""
,.num_headers= 2
,.headers= { { "Host", "example.com" }
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
}
,.body= ""
}
, {.name= NULL } /* sentinel */ , {.name= NULL } /* sentinel */
}; };
@ -2918,6 +2970,59 @@ const struct url_test url_tests[] =
,.rv=1 /* s_dead */ ,.rv=1 /* s_dead */
} }
, {.name="ipv6 address with Zone ID"
,.url="http://[fe80::a%25eth0]/"
,.is_connect=0
,.u=
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
,.port=0
,.field_data=
{{ 0, 4 } /* UF_SCHEMA */
,{ 8, 14 } /* UF_HOST */
,{ 0, 0 } /* UF_PORT */
,{ 23, 1 } /* UF_PATH */
,{ 0, 0 } /* UF_QUERY */
,{ 0, 0 } /* UF_FRAGMENT */
,{ 0, 0 } /* UF_USERINFO */
}
}
,.rv=0
}
, {.name="ipv6 address with Zone ID, but '%' is not percent-encoded"
,.url="http://[fe80::a%eth0]/"
,.is_connect=0
,.u=
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
,.port=0
,.field_data=
{{ 0, 4 } /* UF_SCHEMA */
,{ 8, 12 } /* UF_HOST */
,{ 0, 0 } /* UF_PORT */
,{ 21, 1 } /* UF_PATH */
,{ 0, 0 } /* UF_QUERY */
,{ 0, 0 } /* UF_FRAGMENT */
,{ 0, 0 } /* UF_USERINFO */
}
}
,.rv=0
}
, {.name="ipv6 address ending with '%'"
,.url="http://[fe80::a%]/"
,.rv=1 /* s_dead */
}
, {.name="ipv6 address with Zone ID including bad character"
,.url="http://[fe80::a%$HOME]/"
,.rv=1 /* s_dead */
}
, {.name="just ipv6 Zone ID"
,.url="http://[%eth0]/"
,.rv=1 /* s_dead */
}
#if HTTP_PARSER_STRICT #if HTTP_PARSER_STRICT
, {.name="tab in URL" , {.name="tab in URL"
@ -3690,7 +3795,12 @@ main (void)
"MOVE", "MOVE",
"PROPFIND", "PROPFIND",
"PROPPATCH", "PROPPATCH",
"SEARCH",
"UNLOCK", "UNLOCK",
"BIND",
"REBIND",
"UNBIND",
"ACL",
"REPORT", "REPORT",
"MKACTIVITY", "MKACTIVITY",
"CHECKOUT", "CHECKOUT",
@ -3700,6 +3810,10 @@ main (void)
"SUBSCRIBE", "SUBSCRIBE",
"UNSUBSCRIBE", "UNSUBSCRIBE",
"PATCH", "PATCH",
"PURGE",
"MKCALENDAR",
"LINK",
"UNLINK",
0 }; 0 };
const char **this_method; const char **this_method;
for (this_method = all_methods; *this_method; this_method++) { for (this_method = all_methods; *this_method; this_method++) {

Loading…
Cancel
Save