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 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 /* Also update SONAME in the Makefile whenever you change these. */ 28 #define HTTP_PARSER_VERSION_MAJOR 2 29 #define HTTP_PARSER_VERSION_MINOR 7 30 #define HTTP_PARSER_VERSION_PATCH 0 31 32 #include <sys/types.h> 33 #if defined(_WIN32) && !defined(__MINGW32__) && \ 34 (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) 35 #include <BaseTsd.h> 36 #include <stddef.h> 37 typedef __int8 int8_t; 38 typedef unsigned __int8 uint8_t; 39 typedef __int16 int16_t; 40 typedef unsigned __int16 uint16_t; 41 typedef __int32 int32_t; 42 typedef unsigned __int32 uint32_t; 43 typedef __int64 int64_t; 44 typedef unsigned __int64 uint64_t; 45 #else 46 #include <stdint.h> 47 #endif 48 49 /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run 50 * faster 51 */ 52 #ifndef HTTP_PARSER_STRICT 53 # define HTTP_PARSER_STRICT 1 54 #endif 55 56 /* Maximium header size allowed. If the macro is not defined 57 * before including this header then the default is used. To 58 * change the maximum header size, define the macro in the build 59 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove 60 * the effective limit on the size of the header, define the macro 61 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) 62 */ 63 #ifndef HTTP_MAX_HEADER_SIZE 64 # define HTTP_MAX_HEADER_SIZE (80*1024) 65 #endif 66 67 typedef struct http_parser http_parser; 68 typedef struct http_parser_settings http_parser_settings; 69 70 71 /* Callbacks should return non-zero to indicate an error. The parser will 72 * then halt execution. 73 * 74 * The one exception is on_headers_complete. In a HTTP_RESPONSE parser 75 * returning '1' from on_headers_complete will tell the parser that it 76 * should not expect a body. This is used when receiving a response to a 77 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: 78 * chunked' headers that indicate the presence of a body. 79 * 80 * Returning `2` from on_headers_complete will tell parser that it should not 81 * expect neither a body nor any futher responses on this connection. This is 82 * useful for handling responses to a CONNECT request which may not contain 83 * `Upgrade` or `Connection: upgrade` headers. 84 * 85 * http_data_cb does not return data chunks. It will be called arbitrarily 86 * many times for each string. E.G. you might get 10 callbacks for "on_url" 87 * each providing just a few characters more data. 88 */ 89 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); 90 typedef int (*http_cb) (http_parser*); 91 92 93 /* Request Methods */ 94 #define HTTP_METHOD_MAP(XX) \ 95 XX(0, DELETE, DELETE) \ 96 XX(1, GET, GET) \ 97 XX(2, HEAD, HEAD) \ 98 XX(3, POST, POST) \ 99 XX(4, PUT, PUT) \ 100 /* pathological */ \ 101 XX(5, CONNECT, CONNECT) \ 102 XX(6, OPTIONS, OPTIONS) \ 103 XX(7, TRACE, TRACE) \ 104 /* WebDAV */ \ 105 XX(8, COPY, COPY) \ 106 XX(9, LOCK, LOCK) \ 107 XX(10, MKCOL, MKCOL) \ 108 XX(11, MOVE, MOVE) \ 109 XX(12, PROPFIND, PROPFIND) \ 110 XX(13, PROPPATCH, PROPPATCH) \ 111 XX(14, SEARCH, SEARCH) \ 112 XX(15, UNLOCK, UNLOCK) \ 113 XX(16, BIND, BIND) \ 114 XX(17, REBIND, REBIND) \ 115 XX(18, UNBIND, UNBIND) \ 116 XX(19, ACL, ACL) \ 117 /* subversion */ \ 118 XX(20, REPORT, REPORT) \ 119 XX(21, MKACTIVITY, MKACTIVITY) \ 120 XX(22, CHECKOUT, CHECKOUT) \ 121 XX(23, MERGE, MERGE) \ 122 /* upnp */ \ 123 XX(24, MSEARCH, M-SEARCH) \ 124 XX(25, NOTIFY, NOTIFY) \ 125 XX(26, SUBSCRIBE, SUBSCRIBE) \ 126 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 127 /* RFC-5789 */ \ 128 XX(28, PATCH, PATCH) \ 129 XX(29, PURGE, PURGE) \ 130 /* CalDAV */ \ 131 XX(30, MKCALENDAR, MKCALENDAR) \ 132 /* RFC-2068, section 19.6.1.2 */ \ 133 XX(31, LINK, LINK) \ 134 XX(32, UNLINK, UNLINK) \ 135 136 enum http_method 137 { 138 #define XX(num, name, string) HTTP_##name = num, 139 HTTP_METHOD_MAP(XX) 140 #undef XX 141 }; 142 143 144 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; 145 146 147 /* Flag values for http_parser.flags field */ 148 enum flags 149 { F_CHUNKED = 1 << 0 150 , F_CONNECTION_KEEP_ALIVE = 1 << 1 151 , F_CONNECTION_CLOSE = 1 << 2 152 , F_CONNECTION_UPGRADE = 1 << 3 153 , F_TRAILING = 1 << 4 154 , F_UPGRADE = 1 << 5 155 , F_SKIPBODY = 1 << 6 156 , F_CONTENTLENGTH = 1 << 7 157 }; 158 159 160 /* Map for errno-related constants 161 * 162 * The provided argument should be a macro that takes 2 arguments. 163 */ 164 #define HTTP_ERRNO_MAP(XX) \ 165 /* No error */ \ 166 XX(OK, "success") \ 167 \ 168 /* Callback-related errors */ \ 169 XX(CB_message_begin, "the on_message_begin callback failed") \ 170 XX(CB_url, "the on_url callback failed") \ 171 XX(CB_header_field, "the on_header_field callback failed") \ 172 XX(CB_header_value, "the on_header_value callback failed") \ 173 XX(CB_headers_complete, "the on_headers_complete callback failed") \ 174 XX(CB_body, "the on_body callback failed") \ 175 XX(CB_message_complete, "the on_message_complete callback failed") \ 176 XX(CB_status, "the on_status callback failed") \ 177 XX(CB_chunk_header, "the on_chunk_header callback failed") \ 178 XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ 179 \ 180 /* Parsing-related errors */ \ 181 XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ 182 XX(HEADER_OVERFLOW, \ 183 "too many header bytes seen; overflow detected") \ 184 XX(CLOSED_CONNECTION, \ 185 "data received after completed connection: close message") \ 186 XX(INVALID_VERSION, "invalid HTTP version") \ 187 XX(INVALID_STATUS, "invalid HTTP status code") \ 188 XX(INVALID_METHOD, "invalid HTTP method") \ 189 XX(INVALID_URL, "invalid URL") \ 190 XX(INVALID_HOST, "invalid host") \ 191 XX(INVALID_PORT, "invalid port") \ 192 XX(INVALID_PATH, "invalid path") \ 193 XX(INVALID_QUERY_STRING, "invalid query string") \ 194 XX(INVALID_FRAGMENT, "invalid fragment") \ 195 XX(LF_EXPECTED, "LF character expected") \ 196 XX(INVALID_HEADER_TOKEN, "invalid character in header") \ 197 XX(INVALID_CONTENT_LENGTH, \ 198 "invalid character in content-length header") \ 199 XX(UNEXPECTED_CONTENT_LENGTH, \ 200 "unexpected content-length header") \ 201 XX(INVALID_CHUNK_SIZE, \ 202 "invalid character in chunk size header") \ 203 XX(INVALID_CONSTANT, "invalid constant string") \ 204 XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ 205 XX(STRICT, "strict mode assertion failed") \ 206 XX(PAUSED, "parser is paused") \ 207 XX(UNKNOWN, "an unknown error occurred") 208 209 210 /* Define HPE_* values for each errno value above */ 211 #define HTTP_ERRNO_GEN(n, s) HPE_##n, 212 enum http_errno { 213 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) 214 }; 215 #undef HTTP_ERRNO_GEN 216 217 218 /* Get an http_errno value from an http_parser */ 219 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) 220 221 222 struct http_parser { 223 /** PRIVATE **/ 224 unsigned int type : 2; /* enum http_parser_type */ 225 unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ 226 unsigned int state : 7; /* enum state from http_parser.c */ 227 unsigned int header_state : 7; /* enum header_state from http_parser.c */ 228 unsigned int index : 7; /* index into current matcher */ 229 unsigned int lenient_http_headers : 1; 230 231 uint32_t nread; /* # bytes read in various scenarios */ 232 uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ 233 234 /** READ-ONLY **/ 235 unsigned short http_major; 236 unsigned short http_minor; 237 unsigned int status_code : 16; /* responses only */ 238 unsigned int method : 8; /* requests only */ 239 unsigned int http_errno : 7; 240 241 /* 1 = Upgrade header was present and the parser has exited because of that. 242 * 0 = No upgrade header present. 243 * Should be checked when http_parser_execute() returns in addition to 244 * error checking. 245 */ 246 unsigned int upgrade : 1; 247 248 /** PUBLIC **/ 249 void *data; /* A pointer to get hook to the "connection" or "socket" object */ 250 }; 251 252 253 struct http_parser_settings { 254 http_cb on_message_begin; 255 http_data_cb on_url; 256 http_data_cb on_status; 257 http_data_cb on_header_field; 258 http_data_cb on_header_value; 259 http_cb on_headers_complete; 260 http_data_cb on_body; 261 http_cb on_message_complete; 262 /* When on_chunk_header is called, the current chunk length is stored 263 * in parser->content_length. 264 */ 265 http_cb on_chunk_header; 266 http_cb on_chunk_complete; 267 }; 268 269 270 enum http_parser_url_fields 271 { UF_SCHEMA = 0 272 , UF_HOST = 1 273 , UF_PORT = 2 274 , UF_PATH = 3 275 , UF_QUERY = 4 276 , UF_FRAGMENT = 5 277 , UF_USERINFO = 6 278 , UF_MAX = 7 279 }; 280 281 282 /* Result structure for http_parser_parse_url(). 283 * 284 * Callers should index into field_data[] with UF_* values iff field_set 285 * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and 286 * because we probably have padding left over), we convert any port to 287 * a uint16_t. 288 */ 289 struct http_parser_url { 290 uint16_t field_set; /* Bitmask of (1 << UF_*) values */ 291 uint16_t port; /* Converted UF_PORT string */ 292 293 struct { 294 uint16_t off; /* Offset into buffer in which field starts */ 295 uint16_t len; /* Length of run in buffer */ 296 } field_data[UF_MAX]; 297 }; 298 299 300 /* Returns the library version. Bits 16-23 contain the major version number, 301 * bits 8-15 the minor version number and bits 0-7 the patch level. 302 * Usage example: 303 * 304 * unsigned long version = http_parser_version(); 305 * unsigned major = (version >> 16) & 255; 306 * unsigned minor = (version >> 8) & 255; 307 * unsigned patch = version & 255; 308 * printf("http_parser v%u.%u.%u\n", major, minor, patch); 309 */ 310 unsigned long http_parser_version(void); 311 312 void http_parser_init(http_parser *parser, enum http_parser_type type); 313 314 315 /* Initialize http_parser_settings members to 0 316 */ 317 void http_parser_settings_init(http_parser_settings *settings); 318 319 320 /* Executes the parser. Returns number of parsed bytes. Sets 321 * `parser->http_errno` on error. */ 322 size_t http_parser_execute(http_parser *parser, 323 const http_parser_settings *settings, 324 const char *data, 325 size_t len); 326 327 328 /* If http_should_keep_alive() in the on_headers_complete or 329 * on_message_complete callback returns 0, then this should be 330 * the last message on the connection. 331 * If you are the server, respond with the "Connection: close" header. 332 * If you are the client, close the connection. 333 */ 334 int http_should_keep_alive(const http_parser *parser); 335 336 /* Returns a string version of the HTTP method. */ 337 const char *http_method_str(enum http_method m); 338 339 /* Return a string name of the given error */ 340 const char *http_errno_name(enum http_errno err); 341 342 /* Return a string description of the given error */ 343 const char *http_errno_description(enum http_errno err); 344 345 /* Initialize all http_parser_url members to 0 */ 346 void http_parser_url_init(struct http_parser_url *u); 347 348 /* Parse a URL; return nonzero on failure */ 349 int http_parser_parse_url(const char *buf, size_t buflen, 350 int is_connect, 351 struct http_parser_url *u); 352 353 /* Pause or un-pause the parser; a nonzero value pauses */ 354 void http_parser_pause(http_parser *parser, int paused); 355 356 /* Checks if this is the final chunk of the body. */ 357 int http_body_is_final(const http_parser *parser); 358 359 #ifdef __cplusplus 360 } 361 #endif 362 #endif 363