deps: upgrade http-parser to v2.8.0
PR-URL: https://github.com/nodejs-private/http-parser-private/pull/1 Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rod Vagg <rod@vagg.org>
This commit is contained in:
parent
80310e916a
commit
32050065f1
2
deps/http_parser/.gitignore
vendored
2
deps/http_parser/.gitignore
vendored
@ -12,6 +12,8 @@ parsertrace_g
|
|||||||
*.mk
|
*.mk
|
||||||
*.Makefile
|
*.Makefile
|
||||||
*.so.*
|
*.so.*
|
||||||
|
*.exe.*
|
||||||
|
*.exe
|
||||||
*.a
|
*.a
|
||||||
|
|
||||||
|
|
||||||
|
6
deps/http_parser/LICENSE-MIT
vendored
6
deps/http_parser/LICENSE-MIT
vendored
@ -1,8 +1,4 @@
|
|||||||
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
Copyright Joyent, Inc. and other Node contributors.
|
||||||
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to
|
of this software and associated documentation files (the "Software"), to
|
||||||
|
39
deps/http_parser/Makefile
vendored
39
deps/http_parser/Makefile
vendored
@ -21,16 +21,22 @@
|
|||||||
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
||||||
HELPER ?=
|
HELPER ?=
|
||||||
BINEXT ?=
|
BINEXT ?=
|
||||||
|
SOLIBNAME = libhttp_parser
|
||||||
|
SOMAJOR = 2
|
||||||
|
SOMINOR = 8
|
||||||
|
SOREV = 0
|
||||||
ifeq (darwin,$(PLATFORM))
|
ifeq (darwin,$(PLATFORM))
|
||||||
SONAME ?= libhttp_parser.2.7.0.dylib
|
|
||||||
SOEXT ?= dylib
|
SOEXT ?= dylib
|
||||||
|
SONAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOEXT)
|
||||||
|
LIBNAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOREV).$(SOEXT)
|
||||||
else ifeq (wine,$(PLATFORM))
|
else ifeq (wine,$(PLATFORM))
|
||||||
CC = winegcc
|
CC = winegcc
|
||||||
BINEXT = .exe.so
|
BINEXT = .exe.so
|
||||||
HELPER = wine
|
HELPER = wine
|
||||||
else
|
else
|
||||||
SONAME ?= libhttp_parser.so.2.7.0
|
|
||||||
SOEXT ?= so
|
SOEXT ?= so
|
||||||
|
SONAME ?= $(SOLIBNAME).$(SOEXT).$(SOMAJOR).$(SOMINOR)
|
||||||
|
LIBNAME ?= $(SOLIBNAME).$(SOEXT).$(SOMAJOR).$(SOMINOR).$(SOREV)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CC?=gcc
|
CC?=gcc
|
||||||
@ -55,11 +61,13 @@ CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
|||||||
LDFLAGS_LIB = $(LDFLAGS) -shared
|
LDFLAGS_LIB = $(LDFLAGS) -shared
|
||||||
|
|
||||||
INSTALL ?= install
|
INSTALL ?= install
|
||||||
PREFIX ?= $(DESTDIR)/usr/local
|
PREFIX ?= /usr/local
|
||||||
LIBDIR = $(PREFIX)/lib
|
LIBDIR = $(PREFIX)/lib
|
||||||
INCLUDEDIR = $(PREFIX)/include
|
INCLUDEDIR = $(PREFIX)/include
|
||||||
|
|
||||||
ifneq (darwin,$(PLATFORM))
|
ifeq (darwin,$(PLATFORM))
|
||||||
|
LDFLAGS_LIB += -Wl,-install_name,$(LIBDIR)/$(SONAME)
|
||||||
|
else
|
||||||
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
||||||
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
||||||
endif
|
endif
|
||||||
@ -102,7 +110,7 @@ libhttp_parser.o: http_parser.c http_parser.h Makefile
|
|||||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
|
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
|
||||||
|
|
||||||
library: libhttp_parser.o
|
library: libhttp_parser.o
|
||||||
$(CC) $(LDFLAGS_LIB) -o $(SONAME) $<
|
$(CC) $(LDFLAGS_LIB) -o $(LIBNAME) $<
|
||||||
|
|
||||||
package: http_parser.o
|
package: http_parser.o
|
||||||
$(AR) rcs libhttp_parser.a http_parser.o
|
$(AR) rcs libhttp_parser.a http_parser.o
|
||||||
@ -123,19 +131,22 @@ tags: http_parser.c http_parser.h test.c
|
|||||||
ctags $^
|
ctags $^
|
||||||
|
|
||||||
install: library
|
install: library
|
||||||
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
$(INSTALL) -D http_parser.h $(DESTDIR)$(INCLUDEDIR)/http_parser.h
|
||||||
$(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME)
|
$(INSTALL) -D $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME)
|
||||||
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
ln -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME)
|
||||||
|
ln -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT)
|
||||||
|
|
||||||
install-strip: library
|
install-strip: library
|
||||||
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
$(INSTALL) -D http_parser.h $(DESTDIR)$(INCLUDEDIR)/http_parser.h
|
||||||
$(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME)
|
$(INSTALL) -D -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME)
|
||||||
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
ln -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME)
|
||||||
|
ln -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT)
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm $(INCLUDEDIR)/http_parser.h
|
rm $(DESTDIR)$(INCLUDEDIR)/http_parser.h
|
||||||
rm $(LIBDIR)/$(SONAME)
|
rm $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT)
|
||||||
rm $(LIBDIR)/libhttp_parser.so
|
rm $(DESTDIR)$(LIBDIR)/$(SONAME)
|
||||||
|
rm $(DESTDIR)$(LIBDIR)/$(LIBNAME)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a tags test test_fast test_g \
|
rm -f *.o *.a tags test test_fast test_g \
|
||||||
|
10
deps/http_parser/README.md
vendored
10
deps/http_parser/README.md
vendored
@ -72,9 +72,9 @@ if (parser->upgrade) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
HTTP needs to know where the end of the stream is. For example, sometimes
|
`http_parser` needs to know where the end of the stream is. For example, sometimes
|
||||||
servers send responses without Content-Length and expect the client to
|
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
|
consume input (for the body) until EOF. To tell `http_parser` about EOF, give
|
||||||
`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors
|
`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors
|
||||||
can still be encountered during an EOF, so one must still be prepared
|
can still be encountered during an EOF, so one must still be prepared
|
||||||
to receive them.
|
to receive them.
|
||||||
@ -93,7 +93,7 @@ the on_body callback.
|
|||||||
The Special Problem of Upgrade
|
The Special Problem of Upgrade
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
HTTP supports upgrading the connection to a different protocol. An
|
`http_parser` supports upgrading the connection to a different protocol. An
|
||||||
increasingly common example of this is the WebSocket protocol which sends
|
increasingly common example of this is the WebSocket protocol which sends
|
||||||
a request like
|
a request like
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ 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,
|
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
|
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
|
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
|
callback in a threadsafe manner. This allows `http_parser` to be used in
|
||||||
multi-threaded contexts.
|
multi-threaded contexts.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -202,7 +202,7 @@ void http_parser_thread(socket_t sock) {
|
|||||||
|
|
||||||
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
|
||||||
valid for the lifetime of callback. You can also `read()` into a heap allocated
|
valid for the lifetime of callback. You can also `read()` into a heap allocated
|
||||||
buffer to avoid copying memory around if this fits your application.
|
buffer to avoid copying memory around if this fits your application.
|
||||||
|
|
||||||
|
5
deps/http_parser/contrib/parsertrace.c
vendored
5
deps/http_parser/contrib/parsertrace.c
vendored
@ -1,7 +1,4 @@
|
|||||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
/* Copyright Joyent, Inc. and other Node contributors.
|
||||||
*
|
|
||||||
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
200
deps/http_parser/http_parser.c
vendored
200
deps/http_parser/http_parser.c
vendored
@ -1,7 +1,4 @@
|
|||||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
/* Copyright Joyent, Inc. and other Node contributors.
|
||||||
*
|
|
||||||
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to
|
* of this software and associated documentation files (the "Software"), to
|
||||||
@ -25,7 +22,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
@ -286,10 +282,10 @@ enum state
|
|||||||
, s_res_HT
|
, s_res_HT
|
||||||
, s_res_HTT
|
, s_res_HTT
|
||||||
, s_res_HTTP
|
, s_res_HTTP
|
||||||
, s_res_first_http_major
|
|
||||||
, s_res_http_major
|
, s_res_http_major
|
||||||
, s_res_first_http_minor
|
, s_res_http_dot
|
||||||
, s_res_http_minor
|
, s_res_http_minor
|
||||||
|
, s_res_http_end
|
||||||
, s_res_first_status_code
|
, s_res_first_status_code
|
||||||
, s_res_status_code
|
, s_res_status_code
|
||||||
, s_res_status_start
|
, s_res_status_start
|
||||||
@ -316,10 +312,10 @@ enum state
|
|||||||
, s_req_http_HT
|
, s_req_http_HT
|
||||||
, s_req_http_HTT
|
, s_req_http_HTT
|
||||||
, s_req_http_HTTP
|
, s_req_http_HTTP
|
||||||
, s_req_first_http_major
|
|
||||||
, s_req_http_major
|
, s_req_http_major
|
||||||
, s_req_first_http_minor
|
, s_req_http_dot
|
||||||
, s_req_http_minor
|
, s_req_http_minor
|
||||||
|
, s_req_http_end
|
||||||
, s_req_line_almost_done
|
, s_req_line_almost_done
|
||||||
|
|
||||||
, s_header_field_start
|
, s_header_field_start
|
||||||
@ -795,78 +791,51 @@ reexecute:
|
|||||||
|
|
||||||
case s_res_HTTP:
|
case s_res_HTTP:
|
||||||
STRICT_CHECK(ch != '/');
|
STRICT_CHECK(ch != '/');
|
||||||
UPDATE_STATE(s_res_first_http_major);
|
UPDATE_STATE(s_res_http_major);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case s_res_first_http_major:
|
case s_res_http_major:
|
||||||
if (UNLIKELY(ch < '0' || ch > '9')) {
|
if (UNLIKELY(!IS_NUM(ch))) {
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->http_major = ch - '0';
|
parser->http_major = ch - '0';
|
||||||
UPDATE_STATE(s_res_http_major);
|
UPDATE_STATE(s_res_http_dot);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* major HTTP version or dot */
|
case s_res_http_dot:
|
||||||
case s_res_http_major:
|
|
||||||
{
|
{
|
||||||
if (ch == '.') {
|
if (UNLIKELY(ch != '.')) {
|
||||||
UPDATE_STATE(s_res_first_http_minor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_NUM(ch)) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->http_major *= 10;
|
|
||||||
parser->http_major += ch - '0';
|
|
||||||
|
|
||||||
if (UNLIKELY(parser->http_major > 999)) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UPDATE_STATE(s_res_http_minor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first digit of minor HTTP version */
|
case s_res_http_minor:
|
||||||
case s_res_first_http_minor:
|
|
||||||
if (UNLIKELY(!IS_NUM(ch))) {
|
if (UNLIKELY(!IS_NUM(ch))) {
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->http_minor = ch - '0';
|
parser->http_minor = ch - '0';
|
||||||
UPDATE_STATE(s_res_http_minor);
|
UPDATE_STATE(s_res_http_end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* minor HTTP version or end of request line */
|
case s_res_http_end:
|
||||||
case s_res_http_minor:
|
|
||||||
{
|
{
|
||||||
if (ch == ' ') {
|
if (UNLIKELY(ch != ' ')) {
|
||||||
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
UPDATE_STATE(s_res_first_status_code);
|
UPDATE_STATE(s_res_first_status_code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(!IS_NUM(ch))) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->http_minor *= 10;
|
|
||||||
parser->http_minor += ch - '0';
|
|
||||||
|
|
||||||
if (UNLIKELY(parser->http_minor > 999)) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case s_res_first_status_code:
|
case s_res_first_status_code:
|
||||||
{
|
{
|
||||||
if (!IS_NUM(ch)) {
|
if (!IS_NUM(ch)) {
|
||||||
@ -890,10 +859,9 @@ reexecute:
|
|||||||
UPDATE_STATE(s_res_status_start);
|
UPDATE_STATE(s_res_status_start);
|
||||||
break;
|
break;
|
||||||
case CR:
|
case CR:
|
||||||
UPDATE_STATE(s_res_line_almost_done);
|
|
||||||
break;
|
|
||||||
case LF:
|
case LF:
|
||||||
UPDATE_STATE(s_header_field_start);
|
UPDATE_STATE(s_res_status_start);
|
||||||
|
REEXECUTE();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SET_ERRNO(HPE_INVALID_STATUS);
|
SET_ERRNO(HPE_INVALID_STATUS);
|
||||||
@ -915,19 +883,13 @@ reexecute:
|
|||||||
|
|
||||||
case s_res_status_start:
|
case s_res_status_start:
|
||||||
{
|
{
|
||||||
if (ch == CR) {
|
|
||||||
UPDATE_STATE(s_res_line_almost_done);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch == LF) {
|
|
||||||
UPDATE_STATE(s_header_field_start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MARK(status);
|
MARK(status);
|
||||||
UPDATE_STATE(s_res_status);
|
UPDATE_STATE(s_res_status);
|
||||||
parser->index = 0;
|
parser->index = 0;
|
||||||
|
|
||||||
|
if (ch == CR || ch == LF)
|
||||||
|
REEXECUTE();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,7 +942,7 @@ reexecute:
|
|||||||
/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
|
/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
|
||||||
break;
|
break;
|
||||||
case 'R': parser->method = HTTP_REPORT; /* or REBIND */ 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, SOURCE */ break;
|
||||||
case 'T': parser->method = HTTP_TRACE; break;
|
case 'T': parser->method = HTTP_TRACE; break;
|
||||||
case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
|
case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
|
||||||
default:
|
default:
|
||||||
@ -1007,7 +969,7 @@ reexecute:
|
|||||||
UPDATE_STATE(s_req_spaces_before_url);
|
UPDATE_STATE(s_req_spaces_before_url);
|
||||||
} else if (ch == matcher[parser->index]) {
|
} else if (ch == matcher[parser->index]) {
|
||||||
; /* nada */
|
; /* nada */
|
||||||
} else if (IS_ALPHA(ch)) {
|
} else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
|
||||||
|
|
||||||
switch (parser->method << 16 | parser->index << 8 | ch) {
|
switch (parser->method << 16 | parser->index << 8 | ch) {
|
||||||
#define XX(meth, pos, ch, new_meth) \
|
#define XX(meth, pos, ch, new_meth) \
|
||||||
@ -1016,31 +978,28 @@ reexecute:
|
|||||||
|
|
||||||
XX(POST, 1, 'U', PUT)
|
XX(POST, 1, 'U', PUT)
|
||||||
XX(POST, 1, 'A', PATCH)
|
XX(POST, 1, 'A', PATCH)
|
||||||
|
XX(POST, 1, 'R', PROPFIND)
|
||||||
|
XX(PUT, 2, 'R', PURGE)
|
||||||
XX(CONNECT, 1, 'H', CHECKOUT)
|
XX(CONNECT, 1, 'H', CHECKOUT)
|
||||||
XX(CONNECT, 2, 'P', COPY)
|
XX(CONNECT, 2, 'P', COPY)
|
||||||
XX(MKCOL, 1, 'O', MOVE)
|
XX(MKCOL, 1, 'O', MOVE)
|
||||||
XX(MKCOL, 1, 'E', MERGE)
|
XX(MKCOL, 1, 'E', MERGE)
|
||||||
|
XX(MKCOL, 1, '-', MSEARCH)
|
||||||
XX(MKCOL, 2, 'A', MKACTIVITY)
|
XX(MKCOL, 2, 'A', MKACTIVITY)
|
||||||
XX(MKCOL, 3, 'A', MKCALENDAR)
|
XX(MKCOL, 3, 'A', MKCALENDAR)
|
||||||
XX(SUBSCRIBE, 1, 'E', SEARCH)
|
XX(SUBSCRIBE, 1, 'E', SEARCH)
|
||||||
|
XX(SUBSCRIBE, 1, 'O', SOURCE)
|
||||||
XX(REPORT, 2, 'B', REBIND)
|
XX(REPORT, 2, 'B', REBIND)
|
||||||
XX(POST, 1, 'R', PROPFIND)
|
|
||||||
XX(PROPFIND, 4, 'P', PROPPATCH)
|
XX(PROPFIND, 4, 'P', PROPPATCH)
|
||||||
XX(PUT, 2, 'R', PURGE)
|
|
||||||
XX(LOCK, 1, 'I', LINK)
|
XX(LOCK, 1, 'I', LINK)
|
||||||
XX(UNLOCK, 2, 'S', UNSUBSCRIBE)
|
XX(UNLOCK, 2, 'S', UNSUBSCRIBE)
|
||||||
XX(UNLOCK, 2, 'B', UNBIND)
|
XX(UNLOCK, 2, 'B', UNBIND)
|
||||||
XX(UNLOCK, 3, 'I', UNLINK)
|
XX(UNLOCK, 3, 'I', UNLINK)
|
||||||
#undef XX
|
#undef XX
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SET_ERRNO(HPE_INVALID_METHOD);
|
SET_ERRNO(HPE_INVALID_METHOD);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (ch == '-' &&
|
|
||||||
parser->index == 1 &&
|
|
||||||
parser->method == HTTP_MKCOL) {
|
|
||||||
parser->method = HTTP_MSEARCH;
|
|
||||||
} else {
|
} else {
|
||||||
SET_ERRNO(HPE_INVALID_METHOD);
|
SET_ERRNO(HPE_INVALID_METHOD);
|
||||||
goto error;
|
goto error;
|
||||||
@ -1153,57 +1112,41 @@ reexecute:
|
|||||||
|
|
||||||
case s_req_http_HTTP:
|
case s_req_http_HTTP:
|
||||||
STRICT_CHECK(ch != '/');
|
STRICT_CHECK(ch != '/');
|
||||||
UPDATE_STATE(s_req_first_http_major);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* first digit of major HTTP version */
|
|
||||||
case s_req_first_http_major:
|
|
||||||
if (UNLIKELY(ch < '1' || ch > '9')) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->http_major = ch - '0';
|
|
||||||
UPDATE_STATE(s_req_http_major);
|
UPDATE_STATE(s_req_http_major);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* major HTTP version or dot */
|
|
||||||
case s_req_http_major:
|
case s_req_http_major:
|
||||||
{
|
|
||||||
if (ch == '.') {
|
|
||||||
UPDATE_STATE(s_req_first_http_minor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UNLIKELY(!IS_NUM(ch))) {
|
if (UNLIKELY(!IS_NUM(ch))) {
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->http_major *= 10;
|
parser->http_major = ch - '0';
|
||||||
parser->http_major += ch - '0';
|
UPDATE_STATE(s_req_http_dot);
|
||||||
|
break;
|
||||||
|
|
||||||
if (UNLIKELY(parser->http_major > 999)) {
|
case s_req_http_dot:
|
||||||
|
{
|
||||||
|
if (UNLIKELY(ch != '.')) {
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UPDATE_STATE(s_req_http_minor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first digit of minor HTTP version */
|
case s_req_http_minor:
|
||||||
case s_req_first_http_minor:
|
|
||||||
if (UNLIKELY(!IS_NUM(ch))) {
|
if (UNLIKELY(!IS_NUM(ch))) {
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->http_minor = ch - '0';
|
parser->http_minor = ch - '0';
|
||||||
UPDATE_STATE(s_req_http_minor);
|
UPDATE_STATE(s_req_http_end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* minor HTTP version or end of request line */
|
case s_req_http_end:
|
||||||
case s_req_http_minor:
|
|
||||||
{
|
{
|
||||||
if (ch == CR) {
|
if (ch == CR) {
|
||||||
UPDATE_STATE(s_req_line_almost_done);
|
UPDATE_STATE(s_req_line_almost_done);
|
||||||
@ -1215,21 +1158,8 @@ reexecute:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX allow spaces after digit? */
|
|
||||||
|
|
||||||
if (UNLIKELY(!IS_NUM(ch))) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
SET_ERRNO(HPE_INVALID_VERSION);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
parser->http_minor *= 10;
|
|
||||||
parser->http_minor += ch - '0';
|
|
||||||
|
|
||||||
if (UNLIKELY(parser->http_minor > 999)) {
|
|
||||||
SET_ERRNO(HPE_INVALID_VERSION);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1366,12 +1296,7 @@ reexecute:
|
|||||||
|| c != CONTENT_LENGTH[parser->index]) {
|
|| c != CONTENT_LENGTH[parser->index]) {
|
||||||
parser->header_state = h_general;
|
parser->header_state = h_general;
|
||||||
} else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
|
} else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
|
||||||
if (parser->flags & F_CONTENTLENGTH) {
|
|
||||||
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
parser->header_state = h_content_length;
|
parser->header_state = h_content_length;
|
||||||
parser->flags |= F_CONTENTLENGTH;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1474,6 +1399,12 @@ reexecute:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser->flags & F_CONTENTLENGTH) {
|
||||||
|
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser->flags |= F_CONTENTLENGTH;
|
||||||
parser->content_length = ch - '0';
|
parser->content_length = ch - '0';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1793,10 +1724,17 @@ reexecute:
|
|||||||
UPDATE_STATE(s_headers_done);
|
UPDATE_STATE(s_headers_done);
|
||||||
|
|
||||||
/* Set this here so that on_headers_complete() callbacks can see it */
|
/* Set this here so that on_headers_complete() callbacks can see it */
|
||||||
|
if ((parser->flags & F_UPGRADE) &&
|
||||||
|
(parser->flags & F_CONNECTION_UPGRADE)) {
|
||||||
|
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
|
||||||
|
* mandatory only when it is a 101 Switching Protocols response,
|
||||||
|
* otherwise it is purely informational, to announce support.
|
||||||
|
*/
|
||||||
parser->upgrade =
|
parser->upgrade =
|
||||||
((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==
|
(parser->type == HTTP_REQUEST || parser->status_code == 101);
|
||||||
(F_UPGRADE | F_CONNECTION_UPGRADE) ||
|
} else {
|
||||||
parser->method == HTTP_CONNECT);
|
parser->upgrade = (parser->method == HTTP_CONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Here we call the headers_complete callback. This is somewhat
|
/* Here we call the headers_complete callback. This is somewhat
|
||||||
* different than other callbacks because if the user returns 1, we
|
* different than other callbacks because if the user returns 1, we
|
||||||
@ -1815,6 +1753,7 @@ reexecute:
|
|||||||
case 2:
|
case 2:
|
||||||
parser->upgrade = 1;
|
parser->upgrade = 1;
|
||||||
|
|
||||||
|
/* FALLTHROUGH */
|
||||||
case 1:
|
case 1:
|
||||||
parser->flags |= F_SKIPBODY;
|
parser->flags |= F_SKIPBODY;
|
||||||
break;
|
break;
|
||||||
@ -2373,7 +2312,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
|||||||
case s_req_server_with_at:
|
case s_req_server_with_at:
|
||||||
found_at = 1;
|
found_at = 1;
|
||||||
|
|
||||||
/* FALLTROUGH */
|
/* FALLTHROUGH */
|
||||||
case s_req_server:
|
case s_req_server:
|
||||||
uf = UF_HOST;
|
uf = UF_HOST;
|
||||||
break;
|
break;
|
||||||
@ -2427,13 +2366,28 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (u->field_set & (1 << UF_PORT)) {
|
if (u->field_set & (1 << UF_PORT)) {
|
||||||
/* Don't bother with endp; we've already validated the string */
|
uint16_t off;
|
||||||
unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
|
uint16_t len;
|
||||||
|
const char* p;
|
||||||
|
const char* end;
|
||||||
|
unsigned long v;
|
||||||
|
|
||||||
|
off = u->field_data[UF_PORT].off;
|
||||||
|
len = u->field_data[UF_PORT].len;
|
||||||
|
end = buf + off + len;
|
||||||
|
|
||||||
|
/* NOTE: The characters are already validated and are in the [0-9] range */
|
||||||
|
assert(off + len <= buflen && "Port number overflow");
|
||||||
|
v = 0;
|
||||||
|
for (p = buf + off; p < end; p++) {
|
||||||
|
v *= 10;
|
||||||
|
v += *p - '0';
|
||||||
|
|
||||||
/* Ports have a max value of 2^16 */
|
/* Ports have a max value of 2^16 */
|
||||||
if (v > 0xffff) {
|
if (v > 0xffff) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u->port = (uint16_t) v;
|
u->port = (uint16_t) v;
|
||||||
}
|
}
|
||||||
|
77
deps/http_parser/http_parser.h
vendored
77
deps/http_parser/http_parser.h
vendored
@ -26,14 +26,13 @@ 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 7
|
#define HTTP_PARSER_VERSION_MINOR 8
|
||||||
#define HTTP_PARSER_VERSION_PATCH 0
|
#define HTTP_PARSER_VERSION_PATCH 0
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <stddef.h>
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||||
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
||||||
#include <BaseTsd.h>
|
#include <BaseTsd.h>
|
||||||
#include <stddef.h>
|
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
typedef unsigned __int8 uint8_t;
|
typedef unsigned __int8 uint8_t;
|
||||||
typedef __int16 int16_t;
|
typedef __int16 int16_t;
|
||||||
@ -90,6 +89,76 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
|||||||
typedef int (*http_cb) (http_parser*);
|
typedef int (*http_cb) (http_parser*);
|
||||||
|
|
||||||
|
|
||||||
|
/* Status Codes */
|
||||||
|
#define HTTP_STATUS_MAP(XX) \
|
||||||
|
XX(100, CONTINUE, Continue) \
|
||||||
|
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
||||||
|
XX(102, PROCESSING, Processing) \
|
||||||
|
XX(200, OK, OK) \
|
||||||
|
XX(201, CREATED, Created) \
|
||||||
|
XX(202, ACCEPTED, Accepted) \
|
||||||
|
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
|
||||||
|
XX(204, NO_CONTENT, No Content) \
|
||||||
|
XX(205, RESET_CONTENT, Reset Content) \
|
||||||
|
XX(206, PARTIAL_CONTENT, Partial Content) \
|
||||||
|
XX(207, MULTI_STATUS, Multi-Status) \
|
||||||
|
XX(208, ALREADY_REPORTED, Already Reported) \
|
||||||
|
XX(226, IM_USED, IM Used) \
|
||||||
|
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
|
||||||
|
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
|
||||||
|
XX(302, FOUND, Found) \
|
||||||
|
XX(303, SEE_OTHER, See Other) \
|
||||||
|
XX(304, NOT_MODIFIED, Not Modified) \
|
||||||
|
XX(305, USE_PROXY, Use Proxy) \
|
||||||
|
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
|
||||||
|
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
|
||||||
|
XX(400, BAD_REQUEST, Bad Request) \
|
||||||
|
XX(401, UNAUTHORIZED, Unauthorized) \
|
||||||
|
XX(402, PAYMENT_REQUIRED, Payment Required) \
|
||||||
|
XX(403, FORBIDDEN, Forbidden) \
|
||||||
|
XX(404, NOT_FOUND, Not Found) \
|
||||||
|
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
|
||||||
|
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
|
||||||
|
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
|
||||||
|
XX(408, REQUEST_TIMEOUT, Request Timeout) \
|
||||||
|
XX(409, CONFLICT, Conflict) \
|
||||||
|
XX(410, GONE, Gone) \
|
||||||
|
XX(411, LENGTH_REQUIRED, Length Required) \
|
||||||
|
XX(412, PRECONDITION_FAILED, Precondition Failed) \
|
||||||
|
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
|
||||||
|
XX(414, URI_TOO_LONG, URI Too Long) \
|
||||||
|
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
|
||||||
|
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
|
||||||
|
XX(417, EXPECTATION_FAILED, Expectation Failed) \
|
||||||
|
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
|
||||||
|
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
|
||||||
|
XX(423, LOCKED, Locked) \
|
||||||
|
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
|
||||||
|
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
|
||||||
|
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
|
||||||
|
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
|
||||||
|
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
|
||||||
|
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
|
||||||
|
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
|
||||||
|
XX(501, NOT_IMPLEMENTED, Not Implemented) \
|
||||||
|
XX(502, BAD_GATEWAY, Bad Gateway) \
|
||||||
|
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
|
||||||
|
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
|
||||||
|
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
|
||||||
|
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
|
||||||
|
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
||||||
|
XX(508, LOOP_DETECTED, Loop Detected) \
|
||||||
|
XX(510, NOT_EXTENDED, Not Extended) \
|
||||||
|
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
|
||||||
|
|
||||||
|
enum http_status
|
||||||
|
{
|
||||||
|
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
||||||
|
HTTP_STATUS_MAP(XX)
|
||||||
|
#undef XX
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Request Methods */
|
/* Request Methods */
|
||||||
#define HTTP_METHOD_MAP(XX) \
|
#define HTTP_METHOD_MAP(XX) \
|
||||||
XX(0, DELETE, DELETE) \
|
XX(0, DELETE, DELETE) \
|
||||||
@ -132,6 +201,8 @@ typedef int (*http_cb) (http_parser*);
|
|||||||
/* RFC-2068, section 19.6.1.2 */ \
|
/* RFC-2068, section 19.6.1.2 */ \
|
||||||
XX(31, LINK, LINK) \
|
XX(31, LINK, LINK) \
|
||||||
XX(32, UNLINK, UNLINK) \
|
XX(32, UNLINK, UNLINK) \
|
||||||
|
/* icecast */ \
|
||||||
|
XX(33, SOURCE, SOURCE) \
|
||||||
|
|
||||||
enum http_method
|
enum http_method
|
||||||
{
|
{
|
||||||
|
265
deps/http_parser/test.c
vendored
265
deps/http_parser/test.c
vendored
@ -78,6 +78,7 @@ struct message {
|
|||||||
int message_begin_cb_called;
|
int message_begin_cb_called;
|
||||||
int headers_complete_cb_called;
|
int headers_complete_cb_called;
|
||||||
int message_complete_cb_called;
|
int message_complete_cb_called;
|
||||||
|
int status_cb_called;
|
||||||
int message_complete_on_eof;
|
int message_complete_on_eof;
|
||||||
int body_is_final;
|
int body_is_final;
|
||||||
};
|
};
|
||||||
@ -1131,7 +1132,7 @@ const struct message requests[] =
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define UNLINK_REQUEST 41
|
#define UNLINK_REQUEST 41
|
||||||
, {.name = "link request"
|
, {.name = "unlink request"
|
||||||
,.type= HTTP_REQUEST
|
,.type= HTTP_REQUEST
|
||||||
,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
|
,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
|
||||||
"Host: example.com\r\n"
|
"Host: example.com\r\n"
|
||||||
@ -1153,6 +1154,26 @@ const struct message requests[] =
|
|||||||
,.body= ""
|
,.body= ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SOURCE_REQUEST 42
|
||||||
|
, {.name = "source request"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "SOURCE /music/sweet/music HTTP/1.1\r\n"
|
||||||
|
"Host: example.com\r\n"
|
||||||
|
"\r\n"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_SOURCE
|
||||||
|
,.request_path= "/music/sweet/music"
|
||||||
|
,.request_url= "/music/sweet/music"
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.num_headers= 1
|
||||||
|
,.headers= { { "Host", "example.com" } }
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
, {.name= NULL } /* sentinel */
|
, {.name= NULL } /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1745,6 +1766,193 @@ const struct message responses[] =
|
|||||||
,.body= ""
|
,.body= ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CONTENT_LENGTH_X 21
|
||||||
|
, {.name= "Content-Length-X"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Length-X: 0\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"2\r\n"
|
||||||
|
"OK\r\n"
|
||||||
|
"0\r\n"
|
||||||
|
"\r\n"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 200
|
||||||
|
,.response_status= "OK"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.headers= { { "Content-Length-X", "0" }
|
||||||
|
, { "Transfer-Encoding", "chunked" }
|
||||||
|
}
|
||||||
|
,.body= "OK"
|
||||||
|
,.num_chunks_complete= 2
|
||||||
|
,.chunk_lengths= { 2 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER 22
|
||||||
|
, {.name= "HTTP 101 response with Upgrade header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"proto"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 101
|
||||||
|
,.response_status= "Switching Protocols"
|
||||||
|
,.upgrade= "proto"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 23
|
||||||
|
, {.name= "HTTP 101 response with Upgrade and Content-Length header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"Content-Length: 4\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"body"
|
||||||
|
"proto"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 101
|
||||||
|
,.response_status= "Switching Protocols"
|
||||||
|
,.body= "body"
|
||||||
|
,.upgrade= "proto"
|
||||||
|
,.num_headers= 3
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
, { "Content-Length", "4" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 24
|
||||||
|
, {.name= "HTTP 101 response with Upgrade and Transfer-Encoding header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"2\r\n"
|
||||||
|
"bo\r\n"
|
||||||
|
"2\r\n"
|
||||||
|
"dy\r\n"
|
||||||
|
"0\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"proto"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 101
|
||||||
|
,.response_status= "Switching Protocols"
|
||||||
|
,.body= "body"
|
||||||
|
,.upgrade= "proto"
|
||||||
|
,.num_headers= 3
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
, { "Transfer-Encoding", "chunked" }
|
||||||
|
}
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 2, 2 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER 25
|
||||||
|
, {.name= "HTTP 200 response with Upgrade header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"body"
|
||||||
|
,.should_keep_alive= FALSE
|
||||||
|
,.message_complete_on_eof= TRUE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 200
|
||||||
|
,.response_status= "OK"
|
||||||
|
,.body= "body"
|
||||||
|
,.upgrade= NULL
|
||||||
|
,.num_headers= 2
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 26
|
||||||
|
, {.name= "HTTP 200 response with Upgrade and Content-Length header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"Content-Length: 4\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"body"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 200
|
||||||
|
,.response_status= "OK"
|
||||||
|
,.num_headers= 3
|
||||||
|
,.body= "body"
|
||||||
|
,.upgrade= NULL
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
, { "Content-Length", "4" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 27
|
||||||
|
, {.name= "HTTP 200 response with Upgrade and Transfer-Encoding header"
|
||||||
|
,.type= HTTP_RESPONSE
|
||||||
|
,.raw= "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Upgrade: h2c\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"2\r\n"
|
||||||
|
"bo\r\n"
|
||||||
|
"2\r\n"
|
||||||
|
"dy\r\n"
|
||||||
|
"0\r\n"
|
||||||
|
"\r\n"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.status_code= 200
|
||||||
|
,.response_status= "OK"
|
||||||
|
,.num_headers= 3
|
||||||
|
,.body= "body"
|
||||||
|
,.upgrade= NULL
|
||||||
|
,.headers=
|
||||||
|
{ { "Connection", "upgrade" }
|
||||||
|
, { "Upgrade", "h2c" }
|
||||||
|
, { "Transfer-Encoding", "chunked" }
|
||||||
|
}
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 2, 2 }
|
||||||
|
}
|
||||||
|
|
||||||
, {.name= NULL } /* sentinel */
|
, {.name= NULL } /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1955,6 +2163,9 @@ int
|
|||||||
response_status_cb (http_parser *p, const char *buf, size_t len)
|
response_status_cb (http_parser *p, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
assert(p == parser);
|
assert(p == parser);
|
||||||
|
|
||||||
|
messages[num_messages].status_cb_called = TRUE;
|
||||||
|
|
||||||
strlncat(messages[num_messages].response_status,
|
strlncat(messages[num_messages].response_status,
|
||||||
sizeof(messages[num_messages].response_status),
|
sizeof(messages[num_messages].response_status),
|
||||||
buf,
|
buf,
|
||||||
@ -2379,6 +2590,7 @@ message_eq (int index, int connect, const struct message *expected)
|
|||||||
} else {
|
} else {
|
||||||
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
|
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
|
||||||
MESSAGE_CHECK_STR_EQ(expected, m, response_status);
|
MESSAGE_CHECK_STR_EQ(expected, m, response_status);
|
||||||
|
assert(m->status_cb_called);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connect) {
|
if (!connect) {
|
||||||
@ -2450,7 +2662,9 @@ message_eq (int index, int connect, const struct message *expected)
|
|||||||
if (!r) return 0;
|
if (!r) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!connect) {
|
||||||
MESSAGE_CHECK_STR_EQ(expected, m, upgrade);
|
MESSAGE_CHECK_STR_EQ(expected, m, upgrade);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -3287,9 +3501,11 @@ test_message_count_body (const struct message *message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_simple (const char *buf, enum http_errno err_expected)
|
test_simple_type (const char *buf,
|
||||||
|
enum http_errno err_expected,
|
||||||
|
enum http_parser_type type)
|
||||||
{
|
{
|
||||||
parser_init(HTTP_REQUEST);
|
parser_init(type);
|
||||||
|
|
||||||
enum http_errno err;
|
enum http_errno err;
|
||||||
|
|
||||||
@ -3313,6 +3529,12 @@ test_simple (const char *buf, enum http_errno err_expected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_simple (const char *buf, enum http_errno err_expected)
|
||||||
|
{
|
||||||
|
test_simple_type(buf, err_expected, HTTP_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_invalid_header_content (int req, const char* str)
|
test_invalid_header_content (int req, const char* str)
|
||||||
{
|
{
|
||||||
@ -3462,6 +3684,30 @@ test_header_cr_no_lf_error (int req)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_no_overflow_parse_url (void)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
struct http_parser_url u;
|
||||||
|
|
||||||
|
http_parser_url_init(&u);
|
||||||
|
rv = http_parser_parse_url("http://example.com:8001", 22, 0, &u);
|
||||||
|
|
||||||
|
if (rv != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** test_no_overflow_parse_url invalid return value=%d\n",
|
||||||
|
rv);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.port != 800) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** test_no_overflow_parse_url invalid port number=%d\n",
|
||||||
|
u.port);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_header_overflow_error (int req)
|
test_header_overflow_error (int req)
|
||||||
{
|
{
|
||||||
@ -3850,11 +4096,10 @@ test_message_connect (const struct message *msg)
|
|||||||
{
|
{
|
||||||
char *buf = (char*) msg->raw;
|
char *buf = (char*) msg->raw;
|
||||||
size_t buflen = strlen(msg->raw);
|
size_t buflen = strlen(msg->raw);
|
||||||
size_t nread;
|
|
||||||
|
|
||||||
parser_init(msg->type);
|
parser_init(msg->type);
|
||||||
|
|
||||||
nread = parse_connect(buf, buflen);
|
parse_connect(buf, buflen);
|
||||||
|
|
||||||
if (num_messages != 1) {
|
if (num_messages != 1) {
|
||||||
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
|
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
|
||||||
@ -3898,6 +4143,7 @@ main (void)
|
|||||||
test_header_nread_value();
|
test_header_nread_value();
|
||||||
|
|
||||||
//// OVERFLOW CONDITIONS
|
//// OVERFLOW CONDITIONS
|
||||||
|
test_no_overflow_parse_url();
|
||||||
|
|
||||||
test_header_overflow_error(HTTP_REQUEST);
|
test_header_overflow_error(HTTP_REQUEST);
|
||||||
test_no_overflow_long_body(HTTP_REQUEST, 1000);
|
test_no_overflow_long_body(HTTP_REQUEST, 1000);
|
||||||
@ -3924,6 +4170,12 @@ main (void)
|
|||||||
|
|
||||||
//// RESPONSES
|
//// RESPONSES
|
||||||
|
|
||||||
|
test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
||||||
|
test_simple_type("HTTP/01.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
||||||
|
test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
||||||
|
test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
||||||
|
test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
||||||
|
|
||||||
for (i = 0; i < response_count; i++) {
|
for (i = 0; i < response_count; i++) {
|
||||||
test_message(&responses[i]);
|
test_message(&responses[i]);
|
||||||
}
|
}
|
||||||
@ -4001,6 +4253,9 @@ main (void)
|
|||||||
/// REQUESTS
|
/// REQUESTS
|
||||||
|
|
||||||
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
||||||
|
test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION);
|
||||||
|
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
|
||||||
|
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);
|
||||||
|
|
||||||
// Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js
|
// Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js
|
||||||
test_simple("GET / HTTP/1.1\r\n"
|
test_simple("GET / HTTP/1.1\r\n"
|
||||||
|
@ -60,7 +60,8 @@ const methods = [
|
|||||||
'PURGE',
|
'PURGE',
|
||||||
'MKCALENDAR',
|
'MKCALENDAR',
|
||||||
'LINK',
|
'LINK',
|
||||||
'UNLINK'
|
'UNLINK',
|
||||||
|
'SOURCE',
|
||||||
];
|
];
|
||||||
|
|
||||||
assert.deepStrictEqual(http.METHODS, methods.sort());
|
assert.deepStrictEqual(http.METHODS, methods.sort());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user