1 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
3 * Additional changes are licensed under the same terms as NGINX and
4 * copyright Joyent, Inc. and other Node contributors. All rights reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "http_parser.h"
33 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
37 # define MIN(a,b) ((a) < (b) ? (a) : (b))
41 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
45 # define BIT_AT(a, i) \
46 (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
47 (1 << ((unsigned int) (i) & 7))))
51 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
54 #define SET_ERRNO(e) \
56 parser->http_errno = (e); \
59 #define CURRENT_STATE() p_state
60 #define UPDATE_STATE(V) p_state = (V);
63 parser->state = CURRENT_STATE(); \
72 # define LIKELY(X) __builtin_expect(!!(X), 1)
73 # define UNLIKELY(X) __builtin_expect(!!(X), 0)
75 # define LIKELY(X) (X)
76 # define UNLIKELY(X) (X)
80 /* Run the notify callback FOR, returning ER if it fails */
81 #define CALLBACK_NOTIFY_(FOR, ER) \
83 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
85 if (LIKELY(settings->on_##FOR)) { \
86 parser->state = CURRENT_STATE(); \
87 if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
88 SET_ERRNO(HPE_CB_##FOR); \
90 UPDATE_STATE(parser->state); \
92 /* We either errored above or got paused; get out */ \
93 if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
99 /* Run the notify callback FOR and consume the current byte */
100 #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
102 /* Run the notify callback FOR and don't consume the current byte */
103 #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
105 /* Run data callback FOR with LEN bytes, returning ER if it fails */
106 #define CALLBACK_DATA_(FOR, LEN, ER) \
108 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
111 if (LIKELY(settings->on_##FOR)) { \
112 parser->state = CURRENT_STATE(); \
114 settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
115 SET_ERRNO(HPE_CB_##FOR); \
117 UPDATE_STATE(parser->state); \
119 /* We either errored above or got paused; get out */ \
120 if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
128 /* Run the data callback FOR and consume the current byte */
129 #define CALLBACK_DATA(FOR) \
130 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
132 /* Run the data callback FOR and don't consume the current byte */
133 #define CALLBACK_DATA_NOADVANCE(FOR) \
134 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
136 /* Set the mark FOR; non-destructive if mark is already set */
144 /* Don't allow the total size of the HTTP headers (including the status
145 * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect
146 * embedders against denial-of-service attacks where the attacker feeds
147 * us a never-ending header that the embedder keeps buffering.
149 * This check is arguably the responsibility of embedders but we're doing
150 * it on the embedder's behalf because most won't bother and this way we
151 * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger
152 * than any reasonable request or response so this should never affect
153 * day-to-day operation.
155 #define COUNT_HEADER_SIZE(V) \
157 parser->nread += (V); \
158 if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
159 SET_ERRNO(HPE_HEADER_OVERFLOW); \
165 #define PROXY_CONNECTION "proxy-connection"
166 #define CONNECTION "connection"
167 #define CONTENT_LENGTH "content-length"
168 #define TRANSFER_ENCODING "transfer-encoding"
169 #define UPGRADE "upgrade"
170 #define CHUNKED "chunked"
171 #define KEEP_ALIVE "keep-alive"
172 #define CLOSE "close"
175 static const char *method_strings[] =
177 #define XX(num, name, string) #string,
183 /* Tokens as defined by rfc 2616. Also lowercases them.
184 * token = 1*<any CHAR except CTLs or separators>
185 * separators = "(" | ")" | "<" | ">" | "@"
186 * | "," | ";" | ":" | "\" | <">
187 * | "/" | "[" | "]" | "?" | "="
188 * | "{" | "}" | SP | HT
190 static const char tokens[256] = {
191 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
192 0, 0, 0, 0, 0, 0, 0, 0,
193 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
194 0, 0, 0, 0, 0, 0, 0, 0,
195 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
196 0, 0, 0, 0, 0, 0, 0, 0,
197 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
198 0, 0, 0, 0, 0, 0, 0, 0,
199 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
200 0, '!', 0, '#', '$', '%', '&', '\'',
201 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
202 0, 0, '*', '+', 0, '-', '.', 0,
203 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
204 '0', '1', '2', '3', '4', '5', '6', '7',
205 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
206 '8', '9', 0, 0, 0, 0, 0, 0,
207 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
208 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
209 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
210 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
211 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
212 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
213 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
214 'x', 'y', 'z', 0, 0, 0, '^', '_',
215 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
216 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
217 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
218 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
219 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
220 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
221 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
222 'x', 'y', 'z', 0, '|', 0, '~', 0 };
225 static const int8_t unhex[256] =
226 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
227 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
228 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
229 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
230 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
231 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
232 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
233 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
237 #if HTTP_PARSER_STRICT
244 static const uint8_t normal_url_char[32] = {
245 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
246 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
247 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
248 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
249 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
250 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
251 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
252 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
253 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
254 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
255 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
256 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
257 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
258 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
259 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
260 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
261 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
262 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
263 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
264 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
265 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
266 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
267 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
268 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
269 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
270 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
271 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
272 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
273 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
274 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
275 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
276 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
281 { s_dead = 1 /* important that this is > 0 */
290 , s_res_first_http_major
292 , s_res_first_http_minor
294 , s_res_first_status_code
298 , s_res_line_almost_done
303 , s_req_spaces_before_url
306 , s_req_schema_slash_slash
309 , s_req_server_with_at
311 , s_req_query_string_start
313 , s_req_fragment_start
320 , s_req_first_http_major
322 , s_req_first_http_minor
324 , s_req_line_almost_done
326 , s_header_field_start
328 , s_header_value_discard_ws
329 , s_header_value_discard_ws_almost_done
330 , s_header_value_discard_lws
331 , s_header_value_start
335 , s_header_almost_done
340 , s_chunk_size_almost_done
342 , s_headers_almost_done
345 /* Important: 's_headers_done' must be the last 'header' state. All
346 * states beyond this must be 'body' states. It is used for overflow
347 * checking. See the PARSING_HEADER() macro.
351 , s_chunk_data_almost_done
355 , s_body_identity_eof
361 #define PARSING_HEADER(state) (state <= s_headers_done)
370 , h_matching_connection
371 , h_matching_proxy_connection
372 , h_matching_content_length
373 , h_matching_transfer_encoding
378 , h_transfer_encoding
381 , h_matching_transfer_encoding_chunked
382 , h_matching_connection_token_start
383 , h_matching_connection_keep_alive
384 , h_matching_connection_close
385 , h_matching_connection_upgrade
386 , h_matching_connection_token
388 , h_transfer_encoding_chunked
389 , h_connection_keep_alive
391 , h_connection_upgrade
397 , s_http_userinfo_start
400 , s_http_host_v6_start
404 , s_http_host_port_start
408 /* Macros for character classes; depends on strict-mode */
411 #define LOWER(c) (unsigned char)(c | 0x20)
412 #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
413 #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
414 #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
415 #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
416 #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
417 (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
419 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
420 (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
421 (c) == '$' || (c) == ',')
423 #define STRICT_TOKEN(c) (tokens[(unsigned char)c])
425 #if HTTP_PARSER_STRICT
426 #define TOKEN(c) (tokens[(unsigned char)c])
427 #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
428 #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
430 #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
431 #define IS_URL_CHAR(c) \
432 (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
433 #define IS_HOST_CHAR(c) \
434 (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
438 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
441 #if HTTP_PARSER_STRICT
442 # define STRICT_CHECK(cond) \
445 SET_ERRNO(HPE_STRICT); \
449 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
451 # define STRICT_CHECK(cond)
452 # define NEW_MESSAGE() start_state
456 /* Map errno values to strings for human-readable output */
457 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
460 const char *description;
461 } http_strerror_tab[] = {
462 HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
464 #undef HTTP_STRERROR_GEN
466 int http_message_needs_eof(const http_parser *parser);
470 * This is designed to be shared by http_parser_execute() for URL validation,
471 * hence it has a state transition + byte-for-byte interface. In addition, it
472 * is meant to be embedded in http_parser_parse_url(), which does the dirty
473 * work of turning state transitions URL components for its API.
475 * This function should only be invoked with non-space characters. It is
476 * assumed that the caller cares about (and can detect) the transition between
477 * URL and non-URL states by looking for these.
480 parse_url_char(enum state s, const char ch)
482 if (ch == ' ' || ch == '\r' || ch == '\n') {
486 #if HTTP_PARSER_STRICT
487 if (ch == '\t' || ch == '\f') {
493 case s_req_spaces_before_url:
494 /* Proxied requests are followed by scheme of an absolute URI (alpha).
495 * All methods except CONNECT are followed by '/' or '*'.
498 if (ch == '/' || ch == '*') {
514 return s_req_schema_slash;
519 case s_req_schema_slash:
521 return s_req_schema_slash_slash;
526 case s_req_schema_slash_slash:
528 return s_req_server_start;
533 case s_req_server_with_at:
539 case s_req_server_start:
546 return s_req_query_string_start;
550 return s_req_server_with_at;
553 if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
560 if (IS_URL_CHAR(ch)) {
566 return s_req_query_string_start;
569 return s_req_fragment_start;
574 case s_req_query_string_start:
575 case s_req_query_string:
576 if (IS_URL_CHAR(ch)) {
577 return s_req_query_string;
582 /* allow extra '?' in query string */
583 return s_req_query_string;
586 return s_req_fragment_start;
591 case s_req_fragment_start:
592 if (IS_URL_CHAR(ch)) {
593 return s_req_fragment;
598 return s_req_fragment;
607 if (IS_URL_CHAR(ch)) {
623 /* We should never fall out of the switch above unless there's an error */
627 size_t http_parser_execute (http_parser *parser,
628 const http_parser_settings *settings,
634 const char *p = data;
635 const char *header_field_mark = 0;
636 const char *header_value_mark = 0;
637 const char *url_mark = 0;
638 const char *body_mark = 0;
639 const char *status_mark = 0;
640 enum state p_state = parser->state;
642 /* We're in an error state. Don't bother doing anything. */
643 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
648 switch (CURRENT_STATE()) {
649 case s_body_identity_eof:
650 /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
653 CALLBACK_NOTIFY_NOADVANCE(message_complete);
657 case s_start_req_or_res:
663 SET_ERRNO(HPE_INVALID_EOF_STATE);
669 if (CURRENT_STATE() == s_header_field)
670 header_field_mark = data;
671 if (CURRENT_STATE() == s_header_value)
672 header_value_mark = data;
673 switch (CURRENT_STATE()) {
676 case s_req_schema_slash:
677 case s_req_schema_slash_slash:
678 case s_req_server_start:
680 case s_req_server_with_at:
681 case s_req_query_string_start:
682 case s_req_query_string:
683 case s_req_fragment_start:
694 for (p=data; p != data + len; p++) {
697 if (PARSING_HEADER(CURRENT_STATE()))
698 COUNT_HEADER_SIZE(1);
700 switch (CURRENT_STATE()) {
703 /* this state is used after a 'Connection: close' message
704 * the parser will error out if it reads another message
706 if (LIKELY(ch == CR || ch == LF))
709 SET_ERRNO(HPE_CLOSED_CONNECTION);
712 case s_start_req_or_res:
714 if (ch == CR || ch == LF)
717 parser->content_length = ULLONG_MAX;
720 UPDATE_STATE(s_res_or_resp_H);
722 CALLBACK_NOTIFY(message_begin);
724 parser->type = HTTP_REQUEST;
725 UPDATE_STATE(s_start_req);
732 case s_res_or_resp_H:
734 parser->type = HTTP_RESPONSE;
735 UPDATE_STATE(s_res_HT);
737 if (UNLIKELY(ch != 'E')) {
738 SET_ERRNO(HPE_INVALID_CONSTANT);
742 parser->type = HTTP_REQUEST;
743 parser->method = HTTP_HEAD;
745 UPDATE_STATE(s_req_method);
752 parser->content_length = ULLONG_MAX;
756 UPDATE_STATE(s_res_H);
764 SET_ERRNO(HPE_INVALID_CONSTANT);
768 CALLBACK_NOTIFY(message_begin);
773 STRICT_CHECK(ch != 'T');
774 UPDATE_STATE(s_res_HT);
778 STRICT_CHECK(ch != 'T');
779 UPDATE_STATE(s_res_HTT);
783 STRICT_CHECK(ch != 'P');
784 UPDATE_STATE(s_res_HTTP);
788 STRICT_CHECK(ch != '/');
789 UPDATE_STATE(s_res_first_http_major);
792 case s_res_first_http_major:
793 if (UNLIKELY(ch < '0' || ch > '9')) {
794 SET_ERRNO(HPE_INVALID_VERSION);
798 parser->http_major = ch - '0';
799 UPDATE_STATE(s_res_http_major);
802 /* major HTTP version or dot */
803 case s_res_http_major:
806 UPDATE_STATE(s_res_first_http_minor);
811 SET_ERRNO(HPE_INVALID_VERSION);
815 parser->http_major *= 10;
816 parser->http_major += ch - '0';
818 if (UNLIKELY(parser->http_major > 999)) {
819 SET_ERRNO(HPE_INVALID_VERSION);
826 /* first digit of minor HTTP version */
827 case s_res_first_http_minor:
828 if (UNLIKELY(!IS_NUM(ch))) {
829 SET_ERRNO(HPE_INVALID_VERSION);
833 parser->http_minor = ch - '0';
834 UPDATE_STATE(s_res_http_minor);
837 /* minor HTTP version or end of request line */
838 case s_res_http_minor:
841 UPDATE_STATE(s_res_first_status_code);
845 if (UNLIKELY(!IS_NUM(ch))) {
846 SET_ERRNO(HPE_INVALID_VERSION);
850 parser->http_minor *= 10;
851 parser->http_minor += ch - '0';
853 if (UNLIKELY(parser->http_minor > 999)) {
854 SET_ERRNO(HPE_INVALID_VERSION);
861 case s_res_first_status_code:
868 SET_ERRNO(HPE_INVALID_STATUS);
871 parser->status_code = ch - '0';
872 UPDATE_STATE(s_res_status_code);
876 case s_res_status_code:
881 UPDATE_STATE(s_res_status_start);
884 UPDATE_STATE(s_res_line_almost_done);
887 UPDATE_STATE(s_header_field_start);
890 SET_ERRNO(HPE_INVALID_STATUS);
896 parser->status_code *= 10;
897 parser->status_code += ch - '0';
899 if (UNLIKELY(parser->status_code > 999)) {
900 SET_ERRNO(HPE_INVALID_STATUS);
907 case s_res_status_start:
910 UPDATE_STATE(s_res_line_almost_done);
915 UPDATE_STATE(s_header_field_start);
920 UPDATE_STATE(s_res_status);
927 UPDATE_STATE(s_res_line_almost_done);
928 CALLBACK_DATA(status);
933 UPDATE_STATE(s_header_field_start);
934 CALLBACK_DATA(status);
940 case s_res_line_almost_done:
941 STRICT_CHECK(ch != LF);
942 UPDATE_STATE(s_header_field_start);
947 if (ch == CR || ch == LF)
950 parser->content_length = ULLONG_MAX;
952 if (UNLIKELY(!IS_ALPHA(ch))) {
953 SET_ERRNO(HPE_INVALID_METHOD);
957 parser->method = (enum http_method) 0;
960 case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
961 case 'D': parser->method = HTTP_DELETE; break;
962 case 'G': parser->method = HTTP_GET; break;
963 case 'H': parser->method = HTTP_HEAD; break;
964 case 'L': parser->method = HTTP_LOCK; break;
965 case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
966 case 'N': parser->method = HTTP_NOTIFY; break;
967 case 'O': parser->method = HTTP_OPTIONS; break;
968 case 'P': parser->method = HTTP_POST;
969 /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
971 case 'R': parser->method = HTTP_REPORT; break;
972 case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
973 case 'T': parser->method = HTTP_TRACE; break;
974 case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
976 SET_ERRNO(HPE_INVALID_METHOD);
979 UPDATE_STATE(s_req_method);
981 CALLBACK_NOTIFY(message_begin);
989 if (UNLIKELY(ch == '\0')) {
990 SET_ERRNO(HPE_INVALID_METHOD);
994 matcher = method_strings[parser->method];
995 if (ch == ' ' && matcher[parser->index] == '\0') {
996 UPDATE_STATE(s_req_spaces_before_url);
997 } else if (ch == matcher[parser->index]) {
999 } else if (parser->method == HTTP_CONNECT) {
1000 if (parser->index == 1 && ch == 'H') {
1001 parser->method = HTTP_CHECKOUT;
1002 } else if (parser->index == 2 && ch == 'P') {
1003 parser->method = HTTP_COPY;
1005 SET_ERRNO(HPE_INVALID_METHOD);
1008 } else if (parser->method == HTTP_MKCOL) {
1009 if (parser->index == 1 && ch == 'O') {
1010 parser->method = HTTP_MOVE;
1011 } else if (parser->index == 1 && ch == 'E') {
1012 parser->method = HTTP_MERGE;
1013 } else if (parser->index == 1 && ch == '-') {
1014 parser->method = HTTP_MSEARCH;
1015 } else if (parser->index == 2 && ch == 'A') {
1016 parser->method = HTTP_MKACTIVITY;
1017 } else if (parser->index == 3 && ch == 'A') {
1018 parser->method = HTTP_MKCALENDAR;
1020 SET_ERRNO(HPE_INVALID_METHOD);
1023 } else if (parser->method == HTTP_SUBSCRIBE) {
1024 if (parser->index == 1 && ch == 'E') {
1025 parser->method = HTTP_SEARCH;
1027 SET_ERRNO(HPE_INVALID_METHOD);
1030 } else if (parser->index == 1 && parser->method == HTTP_POST) {
1032 parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
1033 } else if (ch == 'U') {
1034 parser->method = HTTP_PUT; /* or HTTP_PURGE */
1035 } else if (ch == 'A') {
1036 parser->method = HTTP_PATCH;
1038 SET_ERRNO(HPE_INVALID_METHOD);
1041 } else if (parser->index == 2) {
1042 if (parser->method == HTTP_PUT) {
1044 parser->method = HTTP_PURGE;
1046 SET_ERRNO(HPE_INVALID_METHOD);
1049 } else if (parser->method == HTTP_UNLOCK) {
1051 parser->method = HTTP_UNSUBSCRIBE;
1053 SET_ERRNO(HPE_INVALID_METHOD);
1057 SET_ERRNO(HPE_INVALID_METHOD);
1060 } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
1061 parser->method = HTTP_PROPPATCH;
1063 SET_ERRNO(HPE_INVALID_METHOD);
1071 case s_req_spaces_before_url:
1073 if (ch == ' ') break;
1076 if (parser->method == HTTP_CONNECT) {
1077 UPDATE_STATE(s_req_server_start);
1080 UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1081 if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1082 SET_ERRNO(HPE_INVALID_URL);
1090 case s_req_schema_slash:
1091 case s_req_schema_slash_slash:
1092 case s_req_server_start:
1095 /* No whitespace allowed here */
1099 SET_ERRNO(HPE_INVALID_URL);
1102 UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1103 if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1104 SET_ERRNO(HPE_INVALID_URL);
1113 case s_req_server_with_at:
1115 case s_req_query_string_start:
1116 case s_req_query_string:
1117 case s_req_fragment_start:
1118 case s_req_fragment:
1122 UPDATE_STATE(s_req_http_start);
1127 parser->http_major = 0;
1128 parser->http_minor = 9;
1129 UPDATE_STATE((ch == CR) ?
1130 s_req_line_almost_done :
1131 s_header_field_start);
1135 UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1136 if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1137 SET_ERRNO(HPE_INVALID_URL);
1144 case s_req_http_start:
1147 UPDATE_STATE(s_req_http_H);
1152 SET_ERRNO(HPE_INVALID_CONSTANT);
1158 STRICT_CHECK(ch != 'T');
1159 UPDATE_STATE(s_req_http_HT);
1163 STRICT_CHECK(ch != 'T');
1164 UPDATE_STATE(s_req_http_HTT);
1167 case s_req_http_HTT:
1168 STRICT_CHECK(ch != 'P');
1169 UPDATE_STATE(s_req_http_HTTP);
1172 case s_req_http_HTTP:
1173 STRICT_CHECK(ch != '/');
1174 UPDATE_STATE(s_req_first_http_major);
1177 /* first digit of major HTTP version */
1178 case s_req_first_http_major:
1179 if (UNLIKELY(ch < '1' || ch > '9')) {
1180 SET_ERRNO(HPE_INVALID_VERSION);
1184 parser->http_major = ch - '0';
1185 UPDATE_STATE(s_req_http_major);
1188 /* major HTTP version or dot */
1189 case s_req_http_major:
1192 UPDATE_STATE(s_req_first_http_minor);
1196 if (UNLIKELY(!IS_NUM(ch))) {
1197 SET_ERRNO(HPE_INVALID_VERSION);
1201 parser->http_major *= 10;
1202 parser->http_major += ch - '0';
1204 if (UNLIKELY(parser->http_major > 999)) {
1205 SET_ERRNO(HPE_INVALID_VERSION);
1212 /* first digit of minor HTTP version */
1213 case s_req_first_http_minor:
1214 if (UNLIKELY(!IS_NUM(ch))) {
1215 SET_ERRNO(HPE_INVALID_VERSION);
1219 parser->http_minor = ch - '0';
1220 UPDATE_STATE(s_req_http_minor);
1223 /* minor HTTP version or end of request line */
1224 case s_req_http_minor:
1227 UPDATE_STATE(s_req_line_almost_done);
1232 UPDATE_STATE(s_header_field_start);
1236 /* XXX allow spaces after digit? */
1238 if (UNLIKELY(!IS_NUM(ch))) {
1239 SET_ERRNO(HPE_INVALID_VERSION);
1243 parser->http_minor *= 10;
1244 parser->http_minor += ch - '0';
1246 if (UNLIKELY(parser->http_minor > 999)) {
1247 SET_ERRNO(HPE_INVALID_VERSION);
1254 /* end of request line */
1255 case s_req_line_almost_done:
1257 if (UNLIKELY(ch != LF)) {
1258 SET_ERRNO(HPE_LF_EXPECTED);
1262 UPDATE_STATE(s_header_field_start);
1266 case s_header_field_start:
1269 UPDATE_STATE(s_headers_almost_done);
1274 /* they might be just sending \n instead of \r\n so this would be
1275 * the second \n to denote the end of headers*/
1276 UPDATE_STATE(s_headers_almost_done);
1283 SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1290 UPDATE_STATE(s_header_field);
1294 parser->header_state = h_C;
1298 parser->header_state = h_matching_proxy_connection;
1302 parser->header_state = h_matching_transfer_encoding;
1306 parser->header_state = h_matching_upgrade;
1310 parser->header_state = h_general;
1316 case s_header_field:
1318 const char* start = p;
1319 for (; p != data + len; p++) {
1326 switch (parser->header_state) {
1332 parser->header_state = (c == 'o' ? h_CO : h_general);
1337 parser->header_state = (c == 'n' ? h_CON : h_general);
1344 parser->header_state = h_matching_connection;
1347 parser->header_state = h_matching_content_length;
1350 parser->header_state = h_general;
1357 case h_matching_connection:
1359 if (parser->index > sizeof(CONNECTION)-1
1360 || c != CONNECTION[parser->index]) {
1361 parser->header_state = h_general;
1362 } else if (parser->index == sizeof(CONNECTION)-2) {
1363 parser->header_state = h_connection;
1367 /* proxy-connection */
1369 case h_matching_proxy_connection:
1371 if (parser->index > sizeof(PROXY_CONNECTION)-1
1372 || c != PROXY_CONNECTION[parser->index]) {
1373 parser->header_state = h_general;
1374 } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
1375 parser->header_state = h_connection;
1379 /* content-length */
1381 case h_matching_content_length:
1383 if (parser->index > sizeof(CONTENT_LENGTH)-1
1384 || c != CONTENT_LENGTH[parser->index]) {
1385 parser->header_state = h_general;
1386 } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
1387 parser->header_state = h_content_length;
1391 /* transfer-encoding */
1393 case h_matching_transfer_encoding:
1395 if (parser->index > sizeof(TRANSFER_ENCODING)-1
1396 || c != TRANSFER_ENCODING[parser->index]) {
1397 parser->header_state = h_general;
1398 } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
1399 parser->header_state = h_transfer_encoding;
1405 case h_matching_upgrade:
1407 if (parser->index > sizeof(UPGRADE)-1
1408 || c != UPGRADE[parser->index]) {
1409 parser->header_state = h_general;
1410 } else if (parser->index == sizeof(UPGRADE)-2) {
1411 parser->header_state = h_upgrade;
1416 case h_content_length:
1417 case h_transfer_encoding:
1419 if (ch != ' ') parser->header_state = h_general;
1423 assert(0 && "Unknown header_state");
1428 COUNT_HEADER_SIZE(p - start);
1430 if (p == data + len) {
1436 UPDATE_STATE(s_header_value_discard_ws);
1437 CALLBACK_DATA(header_field);
1441 SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1445 case s_header_value_discard_ws:
1446 if (ch == ' ' || ch == '\t') break;
1449 UPDATE_STATE(s_header_value_discard_ws_almost_done);
1454 UPDATE_STATE(s_header_value_discard_lws);
1460 case s_header_value_start:
1464 UPDATE_STATE(s_header_value);
1469 switch (parser->header_state) {
1471 parser->flags |= F_UPGRADE;
1472 parser->header_state = h_general;
1475 case h_transfer_encoding:
1476 /* looking for 'Transfer-Encoding: chunked' */
1478 parser->header_state = h_matching_transfer_encoding_chunked;
1480 parser->header_state = h_general;
1484 case h_content_length:
1485 if (UNLIKELY(!IS_NUM(ch))) {
1486 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1490 parser->content_length = ch - '0';
1494 /* looking for 'Connection: keep-alive' */
1496 parser->header_state = h_matching_connection_keep_alive;
1497 /* looking for 'Connection: close' */
1498 } else if (c == 'c') {
1499 parser->header_state = h_matching_connection_close;
1500 } else if (c == 'u') {
1501 parser->header_state = h_matching_connection_upgrade;
1503 parser->header_state = h_matching_connection_token;
1507 /* Multi-value `Connection` header */
1508 case h_matching_connection_token_start:
1512 parser->header_state = h_general;
1518 case s_header_value:
1520 const char* start = p;
1521 enum header_states h_state = parser->header_state;
1522 for (; p != data + len; p++) {
1525 UPDATE_STATE(s_header_almost_done);
1526 parser->header_state = h_state;
1527 CALLBACK_DATA(header_value);
1532 UPDATE_STATE(s_header_almost_done);
1533 COUNT_HEADER_SIZE(p - start);
1534 parser->header_state = h_state;
1535 CALLBACK_DATA_NOADVANCE(header_value);
1546 size_t limit = data + len - p;
1548 limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
1550 p_cr = memchr(p, CR, limit);
1551 p_lf = memchr(p, LF, limit);
1553 if (p_lf != NULL && p_cr >= p_lf)
1557 } else if (UNLIKELY(p_lf != NULL)) {
1568 case h_transfer_encoding:
1569 assert(0 && "Shouldn't get here.");
1572 case h_content_length:
1576 if (ch == ' ') break;
1578 if (UNLIKELY(!IS_NUM(ch))) {
1579 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1580 parser->header_state = h_state;
1584 t = parser->content_length;
1588 /* Overflow? Test against a conservative limit for simplicity. */
1589 if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
1590 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1591 parser->header_state = h_state;
1595 parser->content_length = t;
1599 /* Transfer-Encoding: chunked */
1600 case h_matching_transfer_encoding_chunked:
1602 if (parser->index > sizeof(CHUNKED)-1
1603 || c != CHUNKED[parser->index]) {
1604 h_state = h_general;
1605 } else if (parser->index == sizeof(CHUNKED)-2) {
1606 h_state = h_transfer_encoding_chunked;
1610 case h_matching_connection_token_start:
1611 /* looking for 'Connection: keep-alive' */
1613 h_state = h_matching_connection_keep_alive;
1614 /* looking for 'Connection: close' */
1615 } else if (c == 'c') {
1616 h_state = h_matching_connection_close;
1617 } else if (c == 'u') {
1618 h_state = h_matching_connection_upgrade;
1619 } else if (STRICT_TOKEN(c)) {
1620 h_state = h_matching_connection_token;
1622 h_state = h_general;
1626 /* looking for 'Connection: keep-alive' */
1627 case h_matching_connection_keep_alive:
1629 if (parser->index > sizeof(KEEP_ALIVE)-1
1630 || c != KEEP_ALIVE[parser->index]) {
1631 h_state = h_matching_connection_token;
1632 } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
1633 h_state = h_connection_keep_alive;
1637 /* looking for 'Connection: close' */
1638 case h_matching_connection_close:
1640 if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
1641 h_state = h_matching_connection_token;
1642 } else if (parser->index == sizeof(CLOSE)-2) {
1643 h_state = h_connection_close;
1647 /* looking for 'Connection: upgrade' */
1648 case h_matching_connection_upgrade:
1650 if (parser->index > sizeof(UPGRADE) - 1 ||
1651 c != UPGRADE[parser->index]) {
1652 h_state = h_matching_connection_token;
1653 } else if (parser->index == sizeof(UPGRADE)-2) {
1654 h_state = h_connection_upgrade;
1658 case h_matching_connection_token:
1660 h_state = h_matching_connection_token_start;
1665 case h_transfer_encoding_chunked:
1666 if (ch != ' ') h_state = h_general;
1669 case h_connection_keep_alive:
1670 case h_connection_close:
1671 case h_connection_upgrade:
1673 if (h_state == h_connection_keep_alive) {
1674 parser->flags |= F_CONNECTION_KEEP_ALIVE;
1675 } else if (h_state == h_connection_close) {
1676 parser->flags |= F_CONNECTION_CLOSE;
1677 } else if (h_state == h_connection_upgrade) {
1678 parser->flags |= F_CONNECTION_UPGRADE;
1680 h_state = h_matching_connection_token_start;
1682 } else if (ch != ' ') {
1683 h_state = h_matching_connection_token;
1688 UPDATE_STATE(s_header_value);
1689 h_state = h_general;
1693 parser->header_state = h_state;
1695 COUNT_HEADER_SIZE(p - start);
1697 if (p == data + len)
1702 case s_header_almost_done:
1704 STRICT_CHECK(ch != LF);
1706 UPDATE_STATE(s_header_value_lws);
1710 case s_header_value_lws:
1712 if (ch == ' ' || ch == '\t') {
1713 UPDATE_STATE(s_header_value_start);
1717 /* finished the header */
1718 switch (parser->header_state) {
1719 case h_connection_keep_alive:
1720 parser->flags |= F_CONNECTION_KEEP_ALIVE;
1722 case h_connection_close:
1723 parser->flags |= F_CONNECTION_CLOSE;
1725 case h_transfer_encoding_chunked:
1726 parser->flags |= F_CHUNKED;
1728 case h_connection_upgrade:
1729 parser->flags |= F_CONNECTION_UPGRADE;
1735 UPDATE_STATE(s_header_field_start);
1739 case s_header_value_discard_ws_almost_done:
1741 STRICT_CHECK(ch != LF);
1742 UPDATE_STATE(s_header_value_discard_lws);
1746 case s_header_value_discard_lws:
1748 if (ch == ' ' || ch == '\t') {
1749 UPDATE_STATE(s_header_value_discard_ws);
1752 switch (parser->header_state) {
1753 case h_connection_keep_alive:
1754 parser->flags |= F_CONNECTION_KEEP_ALIVE;
1756 case h_connection_close:
1757 parser->flags |= F_CONNECTION_CLOSE;
1759 case h_connection_upgrade:
1760 parser->flags |= F_CONNECTION_UPGRADE;
1762 case h_transfer_encoding_chunked:
1763 parser->flags |= F_CHUNKED;
1769 /* header value was empty */
1771 UPDATE_STATE(s_header_field_start);
1772 CALLBACK_DATA_NOADVANCE(header_value);
1777 case s_headers_almost_done:
1779 STRICT_CHECK(ch != LF);
1781 if (parser->flags & F_TRAILING) {
1782 /* End of a chunked request */
1783 UPDATE_STATE(NEW_MESSAGE());
1784 CALLBACK_NOTIFY(message_complete);
1788 UPDATE_STATE(s_headers_done);
1790 /* Set this here so that on_headers_complete() callbacks can see it */
1792 ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==
1793 (F_UPGRADE | F_CONNECTION_UPGRADE) ||
1794 parser->method == HTTP_CONNECT);
1796 /* Here we call the headers_complete callback. This is somewhat
1797 * different than other callbacks because if the user returns 1, we
1798 * will interpret that as saying that this message has no body. This
1799 * is needed for the annoying case of recieving a response to a HEAD
1802 * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1803 * we have to simulate it by handling a change in errno below.
1805 if (settings->on_headers_complete) {
1806 switch (settings->on_headers_complete(parser)) {
1811 parser->flags |= F_SKIPBODY;
1815 SET_ERRNO(HPE_CB_headers_complete);
1816 RETURN(p - data); /* Error */
1820 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1827 case s_headers_done:
1829 STRICT_CHECK(ch != LF);
1833 /* Exit, the rest of the connect is in a different protocol. */
1834 if (parser->upgrade) {
1835 UPDATE_STATE(NEW_MESSAGE());
1836 CALLBACK_NOTIFY(message_complete);
1837 RETURN((p - data) + 1);
1840 if (parser->flags & F_SKIPBODY) {
1841 UPDATE_STATE(NEW_MESSAGE());
1842 CALLBACK_NOTIFY(message_complete);
1843 } else if (parser->flags & F_CHUNKED) {
1844 /* chunked encoding - ignore Content-Length header */
1845 UPDATE_STATE(s_chunk_size_start);
1847 if (parser->content_length == 0) {
1848 /* Content-Length header given but zero: Content-Length: 0\r\n */
1849 UPDATE_STATE(NEW_MESSAGE());
1850 CALLBACK_NOTIFY(message_complete);
1851 } else if (parser->content_length != ULLONG_MAX) {
1852 /* Content-Length header given and non-zero */
1853 UPDATE_STATE(s_body_identity);
1855 if (parser->type == HTTP_REQUEST ||
1856 !http_message_needs_eof(parser)) {
1857 /* Assume content-length 0 - read the next */
1858 UPDATE_STATE(NEW_MESSAGE());
1859 CALLBACK_NOTIFY(message_complete);
1861 /* Read body until EOF */
1862 UPDATE_STATE(s_body_identity_eof);
1870 case s_body_identity:
1872 uint64_t to_read = MIN(parser->content_length,
1873 (uint64_t) ((data + len) - p));
1875 assert(parser->content_length != 0
1876 && parser->content_length != ULLONG_MAX);
1878 /* The difference between advancing content_length and p is because
1879 * the latter will automaticaly advance on the next loop iteration.
1880 * Further, if content_length ends up at 0, we want to see the last
1881 * byte again for our message complete callback.
1884 parser->content_length -= to_read;
1887 if (parser->content_length == 0) {
1888 UPDATE_STATE(s_message_done);
1890 /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1892 * The alternative to doing this is to wait for the next byte to
1893 * trigger the data callback, just as in every other case. The
1894 * problem with this is that this makes it difficult for the test
1895 * harness to distinguish between complete-on-EOF and
1896 * complete-on-length. It's not clear that this distinction is
1897 * important for applications, but let's keep it for now.
1899 CALLBACK_DATA_(body, p - body_mark + 1, p - data);
1906 /* read until EOF */
1907 case s_body_identity_eof:
1913 case s_message_done:
1914 UPDATE_STATE(NEW_MESSAGE());
1915 CALLBACK_NOTIFY(message_complete);
1918 case s_chunk_size_start:
1920 assert(parser->nread == 1);
1921 assert(parser->flags & F_CHUNKED);
1923 unhex_val = unhex[(unsigned char)ch];
1924 if (UNLIKELY(unhex_val == -1)) {
1925 SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1929 parser->content_length = unhex_val;
1930 UPDATE_STATE(s_chunk_size);
1938 assert(parser->flags & F_CHUNKED);
1941 UPDATE_STATE(s_chunk_size_almost_done);
1945 unhex_val = unhex[(unsigned char)ch];
1947 if (unhex_val == -1) {
1948 if (ch == ';' || ch == ' ') {
1949 UPDATE_STATE(s_chunk_parameters);
1953 SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1957 t = parser->content_length;
1961 /* Overflow? Test against a conservative limit for simplicity. */
1962 if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
1963 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1967 parser->content_length = t;
1971 case s_chunk_parameters:
1973 assert(parser->flags & F_CHUNKED);
1974 /* just ignore this shit. TODO check for overflow */
1976 UPDATE_STATE(s_chunk_size_almost_done);
1982 case s_chunk_size_almost_done:
1984 assert(parser->flags & F_CHUNKED);
1985 STRICT_CHECK(ch != LF);
1989 if (parser->content_length == 0) {
1990 parser->flags |= F_TRAILING;
1991 UPDATE_STATE(s_header_field_start);
1993 UPDATE_STATE(s_chunk_data);
2000 uint64_t to_read = MIN(parser->content_length,
2001 (uint64_t) ((data + len) - p));
2003 assert(parser->flags & F_CHUNKED);
2004 assert(parser->content_length != 0
2005 && parser->content_length != ULLONG_MAX);
2007 /* See the explanation in s_body_identity for why the content
2008 * length and data pointers are managed this way.
2011 parser->content_length -= to_read;
2014 if (parser->content_length == 0) {
2015 UPDATE_STATE(s_chunk_data_almost_done);
2021 case s_chunk_data_almost_done:
2022 assert(parser->flags & F_CHUNKED);
2023 assert(parser->content_length == 0);
2024 STRICT_CHECK(ch != CR);
2025 UPDATE_STATE(s_chunk_data_done);
2026 CALLBACK_DATA(body);
2029 case s_chunk_data_done:
2030 assert(parser->flags & F_CHUNKED);
2031 STRICT_CHECK(ch != LF);
2033 UPDATE_STATE(s_chunk_size_start);
2037 assert(0 && "unhandled state");
2038 SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2043 /* Run callbacks for any marks that we have leftover after we ran our of
2044 * bytes. There should be at most one of these set, so it's OK to invoke
2045 * them in series (unset marks will not result in callbacks).
2047 * We use the NOADVANCE() variety of callbacks here because 'p' has already
2048 * overflowed 'data' and this allows us to correct for the off-by-one that
2049 * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
2050 * value that's in-bounds).
2053 assert(((header_field_mark ? 1 : 0) +
2054 (header_value_mark ? 1 : 0) +
2055 (url_mark ? 1 : 0) +
2056 (body_mark ? 1 : 0) +
2057 (status_mark ? 1 : 0)) <= 1);
2059 CALLBACK_DATA_NOADVANCE(header_field);
2060 CALLBACK_DATA_NOADVANCE(header_value);
2061 CALLBACK_DATA_NOADVANCE(url);
2062 CALLBACK_DATA_NOADVANCE(body);
2063 CALLBACK_DATA_NOADVANCE(status);
2068 if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2069 SET_ERRNO(HPE_UNKNOWN);
2076 /* Does the parser need to see an EOF to find the end of the message? */
2078 http_message_needs_eof (const http_parser *parser)
2080 if (parser->type == HTTP_REQUEST) {
2084 /* See RFC 2616 section 4.4 */
2085 if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2086 parser->status_code == 204 || /* No Content */
2087 parser->status_code == 304 || /* Not Modified */
2088 parser->flags & F_SKIPBODY) { /* response to a HEAD request */
2092 if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
2101 http_should_keep_alive (const http_parser *parser)
2103 if (parser->http_major > 0 && parser->http_minor > 0) {
2105 if (parser->flags & F_CONNECTION_CLOSE) {
2109 /* HTTP/1.0 or earlier */
2110 if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2115 return !http_message_needs_eof(parser);
2120 http_method_str (enum http_method m)
2122 return ELEM_AT(method_strings, m, "<unknown>");
2127 http_parser_init (http_parser *parser, enum http_parser_type t)
2129 void *data = parser->data; /* preserve application data */
2130 memset(parser, 0, sizeof(*parser));
2131 parser->data = data;
2133 parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
2134 parser->http_errno = HPE_OK;
2138 http_errno_name(enum http_errno err) {
2139 assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
2140 return http_strerror_tab[err].name;
2144 http_errno_description(enum http_errno err) {
2145 assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
2146 return http_strerror_tab[err].description;
2149 static enum http_host_state
2150 http_parse_host_char(enum http_host_state s, const char ch) {
2152 case s_http_userinfo:
2153 case s_http_userinfo_start:
2155 return s_http_host_start;
2158 if (IS_USERINFO_CHAR(ch)) {
2159 return s_http_userinfo;
2163 case s_http_host_start:
2165 return s_http_host_v6_start;
2168 if (IS_HOST_CHAR(ch)) {
2175 if (IS_HOST_CHAR(ch)) {
2180 case s_http_host_v6_end:
2182 return s_http_host_port_start;
2187 case s_http_host_v6:
2189 return s_http_host_v6_end;
2193 case s_http_host_v6_start:
2194 if (IS_HEX(ch) || ch == ':' || ch == '.') {
2195 return s_http_host_v6;
2200 case s_http_host_port:
2201 case s_http_host_port_start:
2203 return s_http_host_port;
2211 return s_http_host_dead;
2215 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2216 enum http_host_state s;
2219 size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2221 u->field_data[UF_HOST].len = 0;
2223 s = found_at ? s_http_userinfo_start : s_http_host_start;
2225 for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2226 enum http_host_state new_s = http_parse_host_char(s, *p);
2228 if (new_s == s_http_host_dead) {
2234 if (s != s_http_host) {
2235 u->field_data[UF_HOST].off = p - buf;
2237 u->field_data[UF_HOST].len++;
2240 case s_http_host_v6:
2241 if (s != s_http_host_v6) {
2242 u->field_data[UF_HOST].off = p - buf;
2244 u->field_data[UF_HOST].len++;
2247 case s_http_host_port:
2248 if (s != s_http_host_port) {
2249 u->field_data[UF_PORT].off = p - buf;
2250 u->field_data[UF_PORT].len = 0;
2251 u->field_set |= (1 << UF_PORT);
2253 u->field_data[UF_PORT].len++;
2256 case s_http_userinfo:
2257 if (s != s_http_userinfo) {
2258 u->field_data[UF_USERINFO].off = p - buf ;
2259 u->field_data[UF_USERINFO].len = 0;
2260 u->field_set |= (1 << UF_USERINFO);
2262 u->field_data[UF_USERINFO].len++;
2271 /* Make sure we don't end somewhere unexpected */
2273 case s_http_host_start:
2274 case s_http_host_v6_start:
2275 case s_http_host_v6:
2276 case s_http_host_port_start:
2277 case s_http_userinfo:
2278 case s_http_userinfo_start:
2288 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2289 struct http_parser_url *u)
2293 enum http_parser_url_fields uf, old_uf;
2296 u->port = u->field_set = 0;
2297 s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2300 for (p = buf; p < buf + buflen; p++) {
2301 s = parse_url_char(s, *p);
2303 /* Figure out the next field that we're operating on */
2308 /* Skip delimeters */
2309 case s_req_schema_slash:
2310 case s_req_schema_slash_slash:
2311 case s_req_server_start:
2312 case s_req_query_string_start:
2313 case s_req_fragment_start:
2320 case s_req_server_with_at:
2332 case s_req_query_string:
2336 case s_req_fragment:
2341 assert(!"Unexpected state");
2345 /* Nothing's changed; soldier on */
2347 u->field_data[uf].len++;
2351 u->field_data[uf].off = p - buf;
2352 u->field_data[uf].len = 1;
2354 u->field_set |= (1 << uf);
2358 /* host must be present if there is a schema */
2359 /* parsing http:///toto will fail */
2360 if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) {
2361 if (http_parse_host(buf, u, found_at) != 0) {
2366 /* CONNECT requests can only contain "hostname:port" */
2367 if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2371 if (u->field_set & (1 << UF_PORT)) {
2372 /* Don't bother with endp; we've already validated the string */
2373 unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
2375 /* Ports have a max value of 2^16 */
2380 u->port = (uint16_t) v;
2387 http_parser_pause(http_parser *parser, int paused) {
2388 /* Users should only be pausing/unpausing a parser that is not in an error
2389 * state. In non-debug builds, there's not much that we can do about this
2390 * other than ignore it.
2392 if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2393 HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2394 SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2396 assert(0 && "Attempting to pause parser in error state");
2401 http_body_is_final(const struct http_parser *parser) {
2402 return parser->state == s_message_done;
2406 http_parser_version(void) {
2407 return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2408 HTTP_PARSER_VERSION_MINOR * 0x00100 |
2409 HTTP_PARSER_VERSION_PATCH * 0x00001;