Update http-parser
This commit is contained in:
parent
adec2c06bf
commit
3e333f49fe
|
@ -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
|
||||||
|
|
|
@ -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,6 +959,8 @@ 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;
|
||||||
|
@ -968,10 +972,10 @@ reexecute:
|
||||||
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 */ break;
|
||||||
default:
|
default:
|
||||||
SET_ERRNO(HPE_INVALID_METHOD);
|
SET_ERRNO(HPE_INVALID_METHOD);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1027,6 +1031,13 @@ reexecute:
|
||||||
SET_ERRNO(HPE_INVALID_METHOD);
|
SET_ERRNO(HPE_INVALID_METHOD);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
} else if (parser->method == HTTP_REPORT) {
|
||||||
|
if (parser->index == 2 && ch == 'B') {
|
||||||
|
parser->method = HTTP_REBIND;
|
||||||
|
} else {
|
||||||
|
SET_ERRNO(HPE_INVALID_METHOD);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
} else if (parser->index == 1 && parser->method == HTTP_POST) {
|
} else if (parser->index == 1 && parser->method == HTTP_POST) {
|
||||||
if (ch == 'R') {
|
if (ch == 'R') {
|
||||||
parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
|
parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
|
||||||
|
@ -1049,6 +1060,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;
|
||||||
|
@ -1828,11 +1841,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)) {
|
||||||
|
@ -2152,15 +2166,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2213,6 +2225,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:
|
||||||
|
@ -2263,6 +2292,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 +2326,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:
|
||||||
|
|
|
@ -30,7 +30,8 @@ extern "C" {
|
||||||
#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,25 @@ 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) \
|
||||||
|
|
||||||
enum http_method
|
enum http_method
|
||||||
{
|
{
|
||||||
|
|
|
@ -2918,6 +2918,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 +3743,12 @@ main (void)
|
||||||
"MOVE",
|
"MOVE",
|
||||||
"PROPFIND",
|
"PROPFIND",
|
||||||
"PROPPATCH",
|
"PROPPATCH",
|
||||||
|
"SEARCH",
|
||||||
"UNLOCK",
|
"UNLOCK",
|
||||||
|
"BIND",
|
||||||
|
"REBIND",
|
||||||
|
"UNBIND",
|
||||||
|
"ACL",
|
||||||
"REPORT",
|
"REPORT",
|
||||||
"MKACTIVITY",
|
"MKACTIVITY",
|
||||||
"CHECKOUT",
|
"CHECKOUT",
|
||||||
|
@ -3700,6 +3758,8 @@ main (void)
|
||||||
"SUBSCRIBE",
|
"SUBSCRIBE",
|
||||||
"UNSUBSCRIBE",
|
"UNSUBSCRIBE",
|
||||||
"PATCH",
|
"PATCH",
|
||||||
|
"PURGE",
|
||||||
|
"MKCALENDAR",
|
||||||
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…
Reference in New Issue