proxygen
http_parser.h
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 #ifndef http_parser_h
22 #define http_parser_h
23 
24 #define HTTP_PARSER_VERSION_MAJOR 1
25 #define HTTP_PARSER_VERSION_MINOR 0
26 
27 #include <sys/types.h>
28 #if defined(_WIN32) && !defined(__MINGW32__) && \
29  (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
30 #include <BaseTsd.h>
31 #include <stddef.h>
32 typedef __int8 int8_t;
33 typedef unsigned __int8 uint8_t;
34 typedef __int16 int16_t;
35 typedef unsigned __int16 uint16_t;
36 typedef __int32 int32_t;
37 typedef unsigned __int32 uint32_t;
38 typedef __int64 int64_t;
39 typedef unsigned __int64 uint64_t;
40 #else
41 #include <stdint.h>
42 #endif
43 
44 #if __cplusplus
45 namespace proxygen {
46 #endif /* __cplusplus */
47 
48 /* Compile with -DHTTP_PARSER_STRICT=1 to parse URLs and hostnames
49  * strictly according to the RFCs
50  */
51 #ifndef HTTP_PARSER_STRICT
52 # define HTTP_PARSER_STRICT 0
53 #endif
54 
55 /* Compile with -DHTTP_PARSER_DEBUG=1 to add extra debugging information to
56  * the error reporting facility.
57  */
58 #ifndef HTTP_PARSER_DEBUG
59 # define HTTP_PARSER_DEBUG 0
60 #endif
61 
62 
63 /* Maximium header size allowed */
64 #define HTTP_MAX_HEADER_SIZE (80*1024)
65 
66 
67 typedef struct http_parser http_parser;
70 
71 
72 /* Callbacks should return non-zero to indicate an error. The parser will
73  * then halt execution.
74  *
75  * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
76  * returning '1' from on_headers_complete will tell the parser that it
77  * should not expect a body. This is used when receiving a response to a
78  * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
79  * chunked' headers that indicate the presence of a body.
80  *
81  * http_data_cb does not return data chunks. It will be call arbitrarally
82  * many times for each string. E.G. you might get 10 callbacks for "on_path"
83  * each providing just a few characters more data.
84  */
85 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
86 typedef int (*http_cb) (http_parser*);
87 
88 
89 /* Request Methods */
96  /* pathological */
100  /* webdav */
108  /* subversion */
113  /* upnp */
118  /* RFC-5789 */
120  };
121 
122 
124 
125 
126 /* Flag values for http_parser.flags field */
127 enum flags
128  { F_CHUNKED = 1 << 0
129  , F_TRAILING = 1 << 3
130  , F_UPGRADE = 1 << 4
131  , F_SKIPBODY = 1 << 5
132  };
133 
134 
135 /* Map for errno-related constants
136  *
137  * The provided argument should be a macro that takes 2 arguments.
138  */
139 #define HTTP_ERRNO_MAP(XX) \
140  /* No error */ \
141  XX(OK, "success") \
142  \
143  /* Callback-related errors */ \
144  XX(CB_message_begin, "the on_message_begin callback failed") \
145  XX(CB_path, "the on_path callback failed") \
146  XX(CB_query_string, "the on_query_string callback failed") \
147  XX(CB_url, "the on_url callback failed") \
148  XX(CB_fragment, "the on_fragment callback failed") \
149  XX(CB_header_field, "the on_header_field callback failed") \
150  XX(CB_header_value, "the on_header_value callback failed") \
151  XX(CB_headers_complete, "the on_headers_complete callback failed") \
152  XX(CB_body, "the on_body callback failed") \
153  XX(CB_message_complete, "the on_message_complete callback failed") \
154  XX(CB_reason, "the on_reason callback failed") \
155  XX(CB_chunk_header, "the on_chunk_header callback failed") \
156  XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
157  \
158  /* Parsing-related errors */ \
159  XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
160  XX(HEADER_OVERFLOW, \
161  "too many header bytes seen; overflow detected") \
162  XX(CLOSED_CONNECTION, \
163  "data received after completed connection: close message") \
164  XX(INVALID_VERSION, "invalid HTTP version") \
165  XX(INVALID_STATUS, "invalid HTTP status code") \
166  XX(INVALID_METHOD, "invalid HTTP method") \
167  XX(INVALID_URL, "invalid URL") \
168  XX(INVALID_HOST, "invalid host") \
169  XX(INVALID_PORT, "invalid port") \
170  XX(INVALID_PATH, "invalid path") \
171  XX(INVALID_QUERY_STRING, "invalid query string") \
172  XX(INVALID_FRAGMENT, "invalid fragment") \
173  XX(LF_EXPECTED, "LF character expected") \
174  XX(INVALID_HEADER_TOKEN, "invalid character in header") \
175  XX(INVALID_CONTENT_LENGTH, \
176  "invalid character in content-length header") \
177  XX(HUGE_CONTENT_LENGTH, \
178  "content-length header too large") \
179  XX(INVALID_CHUNK_SIZE, \
180  "invalid character in chunk size header") \
181  XX(HUGE_CHUNK_SIZE, \
182  "chunk header size too large") \
183  XX(INVALID_TRANSFER_ENCODING, \
184  "invalid character in transfer-encoding header") \
185  XX(INVALID_UPGRADE, \
186  "invalid character in upgrade header") \
187  XX(INVALID_CONSTANT, "invalid constant string") \
188  XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
189  XX(STRICT, "strict mode assertion failed") \
190  XX(PAUSED, "parser is paused") \
191  XX(UNKNOWN, "an unknown error occurred")
192 
193 
194 /* Define HPE_* values for each errno value above */
195 #define HTTP_ERRNO_GEN(n, s) HPE_##n,
198 };
199 #undef HTTP_ERRNO_GEN
200 
201 
202 /* Get an http_errno value from an http_parser */
203 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
204 
205 /* Get the line number that generated the current error */
206 #if HTTP_PARSER_DEBUG
207 #define HTTP_PARSER_ERRNO_LINE(p) ((p)->error_lineno)
208 #else
209 #define HTTP_PARSER_ERRNO_LINE(p) 0
210 #endif
211 
213 struct http_parser {
215  unsigned char type : 2; /* enum http_parser_type */
216  unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
217  unsigned char state; /* enum state from http_parser.c */
218  unsigned char header_state; /* enum header_state from http_parser.c */
219  unsigned char index; /* index into current matcher */
221  uint32_t nread; /* # bytes read in various scenarios */
222  int64_t content_length; /* # bytes in body (0 if no Content-Length header) */
223 
225  unsigned short http_major;
226  unsigned short http_minor;
227  unsigned short status_code; /* responses only */
228  unsigned char method; /* requests only */
229  unsigned char http_errno : 7;
230 
231  /* 1 = Upgrade header was present and the parser has exited because of that.
232  * 0 = No upgrade header present.
233  * Should be checked when http_parser_execute() returns in addition to
234  * error checking.
235  */
236  char upgrade : 1;
237 
238 #if HTTP_PARSER_DEBUG
239  uint32_t error_lineno;
240 #endif
241 
243  void *data; /* A pointer to get hook to the "connection" or "socket" object */
244 };
245 
248  http_cb on_message_begin;
249  http_data_cb on_url;
250  http_data_cb on_header_field;
251  http_data_cb on_header_value;
252  http_data_cb on_headers_complete;
253  http_data_cb on_body;
254  http_cb on_message_complete;
255  http_data_cb on_reason;
256  /* When on_chunk_header is called, the current chunk length is stored
257  * in parser->content_length.
258  */
259  http_cb on_chunk_header;
260  http_cb on_chunk_complete;
261 };
262 
265  { UF_SCHEMA = 0
266  , UF_HOST = 1
267  , UF_PORT = 2
268  , UF_PATH = 3
269  , UF_QUERY = 4
272  , UF_MAX = 7
273 };
274 
275 
276 /* Result structure for http_parser_parse_url().
277  *
278  * Callers should index into field_data[] with UF_* values iff field_set
279  * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
280  * because we probably have padding left over), we convert any port to
281  * a uint16_t.
282  */
284  uint16_t field_set; /* Bitmask of (1 << UF_*) values */
285  uint16_t port; /* Converted UF_PORT string */
286 
287  struct {
288  uint16_t off; /* Offset into buffer in which field starts */
289  uint16_t len; /* Length of run in buffer */
290  } field_data[UF_MAX];
291 };
292 
293 
294 void http_parser_init(http_parser *parser, enum http_parser_type type);
295 
296 
297 size_t http_parser_execute(http_parser *parser,
299  const char *data,
300  size_t len);
301 
302 /* Returns a string version of the HTTP method. */
303 const char *http_method_str(enum http_method m);
304 
305 /* Return a string name of the given error */
306 const char *http_errno_name(enum http_errno err);
307 
308 /* Return a string description of the given error */
309 const char *http_errno_description(enum http_errno err);
310 
311 /* Parse a URL; return nonzero on failure */
312 int http_parser_parse_url(const char *buf, size_t buflen,
313  int is_connect,
314  struct http_parser_url *u);
315 
316 /* Pause or un-pause the parser; a nonzero value pauses */
317 void http_parser_pause(http_parser *parser, int paused);
318 
319 #if __cplusplus
320 }
321 #endif /* __cplusplus */
322 
323 #endif
int(* http_cb)(http_parser *)
Definition: http_parser.h:86
#define HTTP_ERRNO_MAP(XX)
Definition: http_parser.h:139
flags
Definition: http_parser.h:127
struct http_parser_result http_parser_result
Definition: http_parser.h:69
const char * http_method_str(enum http_method m)
Definition: http_parser.c:2159
PskType type
void http_parser_pause(http_parser *parser, int paused)
Definition: http_parser.c:2431
static http_parser_settings settings
Definition: test.c:1529
static http_parser * parser
Definition: test.c:40
size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
Definition: http_parser.c:602
static map< string, int > m
int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u)
Definition: http_parser.c:2332
http_method
Definition: http_parser.h:90
http_parser_type
Definition: http_parser.h:123
#define HTTP_ERRNO_GEN(n, s)
Definition: http_parser.h:195
http_errno
Definition: http_parser.h:196
int(* http_data_cb)(http_parser *, const char *at, size_t length)
Definition: http_parser.h:85
const char * http_errno_name(enum http_errno err)
Definition: http_parser.c:2180
const char * http_errno_description(enum http_errno err)
Definition: http_parser.c:2186
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
http_parser_url_fields
Definition: http_parser.h:263
state
Definition: http_parser.c:272
void http_parser_init(http_parser *parser, enum http_parser_type type)
Definition: http_parser.c:2166