midori_http_parser 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitmodules +6 -0
  4. data/.travis.yml +33 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE-MIT +20 -0
  7. data/README.md +90 -0
  8. data/Rakefile +6 -0
  9. data/bench/standalone.rb +23 -0
  10. data/bench/thin.rb +58 -0
  11. data/ext/ruby_http_parser/.gitignore +1 -0
  12. data/ext/ruby_http_parser/RubyHttpParserService.java +18 -0
  13. data/ext/ruby_http_parser/ext_help.h +18 -0
  14. data/ext/ruby_http_parser/extconf.rb +24 -0
  15. data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +495 -0
  16. data/ext/ruby_http_parser/ruby_http_parser.c +516 -0
  17. data/ext/ruby_http_parser/vendor/.gitkeep +0 -0
  18. data/ext/ruby_http_parser/vendor/http-parser-java/AUTHORS +32 -0
  19. data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +48 -0
  20. data/ext/ruby_http_parser/vendor/http-parser-java/README.md +183 -0
  21. data/ext/ruby_http_parser/vendor/http-parser-java/TODO +28 -0
  22. data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
  23. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +2175 -0
  24. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
  25. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +304 -0
  26. data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
  27. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
  28. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
  29. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
  30. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
  31. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +9 -0
  32. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +113 -0
  33. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +36 -0
  34. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
  35. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +256 -0
  36. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java +13 -0
  37. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java +111 -0
  38. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java +5 -0
  39. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java +25 -0
  40. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java +7 -0
  41. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +2171 -0
  42. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +83 -0
  43. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +374 -0
  44. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/ParseUrl.java +51 -0
  45. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
  46. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +52 -0
  47. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +16 -0
  48. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +48 -0
  49. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +212 -0
  50. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +62 -0
  51. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +117 -0
  52. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +27 -0
  53. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Url.java +127 -0
  54. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +236 -0
  55. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +59 -0
  56. data/ext/ruby_http_parser/vendor/http-parser-java/test.c +3425 -0
  57. data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +845 -0
  58. data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
  59. data/ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb +6 -0
  60. data/ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb +13 -0
  61. data/ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb +15 -0
  62. data/ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb +33 -0
  63. data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +68 -0
  64. data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +23 -0
  65. data/ext/ruby_http_parser/vendor/http-parser/README.md +246 -0
  66. data/ext/ruby_http_parser/vendor/http-parser/bench.c +111 -0
  67. data/ext/ruby_http_parser/vendor/http-parser/contrib/parsertrace.c +160 -0
  68. data/ext/ruby_http_parser/vendor/http-parser/contrib/url_parser.c +47 -0
  69. data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +2470 -0
  70. data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +111 -0
  71. data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +432 -0
  72. data/ext/ruby_http_parser/vendor/http-parser/test.c +4226 -0
  73. data/ext/ruby_http_parser/vendor/http-parser/test_fast +0 -0
  74. data/ext/ruby_http_parser/vendor/http-parser/test_g +0 -0
  75. data/lib/http/parser.rb +1 -0
  76. data/lib/http_parser.rb +21 -0
  77. data/midori_http_parser.gemspec +24 -0
  78. data/spec/parser_spec.rb +376 -0
  79. data/spec/spec_helper.rb +1 -0
  80. data/spec/support/requests.json +631 -0
  81. data/spec/support/responses.json +375 -0
  82. data/tasks/compile.rake +42 -0
  83. data/tasks/fixtures.rake +71 -0
  84. data/tasks/spec.rake +5 -0
  85. data/tasks/submodules.rake +7 -0
  86. metadata +206 -0
@@ -0,0 +1,111 @@
1
+ # This file is used with the GYP meta build system.
2
+ # http://code.google.com/p/gyp/
3
+ # To build try this:
4
+ # svn co http://gyp.googlecode.com/svn/trunk gyp
5
+ # ./gyp/gyp -f make --depth=`pwd` http_parser.gyp
6
+ # ./out/Debug/test
7
+ {
8
+ 'target_defaults': {
9
+ 'default_configuration': 'Debug',
10
+ 'configurations': {
11
+ # TODO: hoist these out and put them somewhere common, because
12
+ # RuntimeLibrary MUST MATCH across the entire project
13
+ 'Debug': {
14
+ 'defines': [ 'DEBUG', '_DEBUG' ],
15
+ 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
16
+ 'msvs_settings': {
17
+ 'VCCLCompilerTool': {
18
+ 'RuntimeLibrary': 1, # static debug
19
+ },
20
+ },
21
+ },
22
+ 'Release': {
23
+ 'defines': [ 'NDEBUG' ],
24
+ 'cflags': [ '-Wall', '-Wextra', '-O3' ],
25
+ 'msvs_settings': {
26
+ 'VCCLCompilerTool': {
27
+ 'RuntimeLibrary': 0, # static release
28
+ },
29
+ },
30
+ }
31
+ },
32
+ 'msvs_settings': {
33
+ 'VCCLCompilerTool': {
34
+ },
35
+ 'VCLibrarianTool': {
36
+ },
37
+ 'VCLinkerTool': {
38
+ 'GenerateDebugInformation': 'true',
39
+ },
40
+ },
41
+ 'conditions': [
42
+ ['OS == "win"', {
43
+ 'defines': [
44
+ 'WIN32'
45
+ ],
46
+ }]
47
+ ],
48
+ },
49
+
50
+ 'targets': [
51
+ {
52
+ 'target_name': 'http_parser',
53
+ 'type': 'static_library',
54
+ 'include_dirs': [ '.' ],
55
+ 'direct_dependent_settings': {
56
+ 'defines': [ 'HTTP_PARSER_STRICT=0' ],
57
+ 'include_dirs': [ '.' ],
58
+ },
59
+ 'defines': [ 'HTTP_PARSER_STRICT=0' ],
60
+ 'sources': [ './http_parser.c', ],
61
+ 'conditions': [
62
+ ['OS=="win"', {
63
+ 'msvs_settings': {
64
+ 'VCCLCompilerTool': {
65
+ # Compile as C++. http_parser.c is actually C99, but C++ is
66
+ # close enough in this case.
67
+ 'CompileAs': 2,
68
+ },
69
+ },
70
+ }]
71
+ ],
72
+ },
73
+
74
+ {
75
+ 'target_name': 'http_parser_strict',
76
+ 'type': 'static_library',
77
+ 'include_dirs': [ '.' ],
78
+ 'direct_dependent_settings': {
79
+ 'defines': [ 'HTTP_PARSER_STRICT=1' ],
80
+ 'include_dirs': [ '.' ],
81
+ },
82
+ 'defines': [ 'HTTP_PARSER_STRICT=1' ],
83
+ 'sources': [ './http_parser.c', ],
84
+ 'conditions': [
85
+ ['OS=="win"', {
86
+ 'msvs_settings': {
87
+ 'VCCLCompilerTool': {
88
+ # Compile as C++. http_parser.c is actually C99, but C++ is
89
+ # close enough in this case.
90
+ 'CompileAs': 2,
91
+ },
92
+ },
93
+ }]
94
+ ],
95
+ },
96
+
97
+ {
98
+ 'target_name': 'test-nonstrict',
99
+ 'type': 'executable',
100
+ 'dependencies': [ 'http_parser' ],
101
+ 'sources': [ 'test.c' ]
102
+ },
103
+
104
+ {
105
+ 'target_name': 'test-strict',
106
+ 'type': 'executable',
107
+ 'dependencies': [ 'http_parser_strict' ],
108
+ 'sources': [ 'test.c' ]
109
+ }
110
+ ]
111
+ }
@@ -0,0 +1,432 @@
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 1
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
+ /* Status Codes */
94
+ #define HTTP_STATUS_MAP(XX) \
95
+ XX(100, CONTINUE, Continue) \
96
+ XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
97
+ XX(102, PROCESSING, Processing) \
98
+ XX(200, OK, OK) \
99
+ XX(201, CREATED, Created) \
100
+ XX(202, ACCEPTED, Accepted) \
101
+ XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
102
+ XX(204, NO_CONTENT, No Content) \
103
+ XX(205, RESET_CONTENT, Reset Content) \
104
+ XX(206, PARTIAL_CONTENT, Partial Content) \
105
+ XX(207, MULTI_STATUS, Multi-Status) \
106
+ XX(208, ALREADY_REPORTED, Already Reported) \
107
+ XX(226, IM_USED, IM Used) \
108
+ XX(300, MULTIPLE_CHOICES, Multiple Choices) \
109
+ XX(301, MOVED_PERMANENTLY, Moved Permanently) \
110
+ XX(302, FOUND, Found) \
111
+ XX(303, SEE_OTHER, See Other) \
112
+ XX(304, NOT_MODIFIED, Not Modified) \
113
+ XX(305, USE_PROXY, Use Proxy) \
114
+ XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
115
+ XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
116
+ XX(400, BAD_REQUEST, Bad Request) \
117
+ XX(401, UNAUTHORIZED, Unauthorized) \
118
+ XX(402, PAYMENT_REQUIRED, Payment Required) \
119
+ XX(403, FORBIDDEN, Forbidden) \
120
+ XX(404, NOT_FOUND, Not Found) \
121
+ XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
122
+ XX(406, NOT_ACCEPTABLE, Not Acceptable) \
123
+ XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
124
+ XX(408, REQUEST_TIMEOUT, Request Timeout) \
125
+ XX(409, CONFLICT, Conflict) \
126
+ XX(410, GONE, Gone) \
127
+ XX(411, LENGTH_REQUIRED, Length Required) \
128
+ XX(412, PRECONDITION_FAILED, Precondition Failed) \
129
+ XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
130
+ XX(414, URI_TOO_LONG, URI Too Long) \
131
+ XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
132
+ XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
133
+ XX(417, EXPECTATION_FAILED, Expectation Failed) \
134
+ XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
135
+ XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
136
+ XX(423, LOCKED, Locked) \
137
+ XX(424, FAILED_DEPENDENCY, Failed Dependency) \
138
+ XX(426, UPGRADE_REQUIRED, Upgrade Required) \
139
+ XX(428, PRECONDITION_REQUIRED, Precondition Required) \
140
+ XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
141
+ XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
142
+ XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
143
+ XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
144
+ XX(501, NOT_IMPLEMENTED, Not Implemented) \
145
+ XX(502, BAD_GATEWAY, Bad Gateway) \
146
+ XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
147
+ XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
148
+ XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
149
+ XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
150
+ XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
151
+ XX(508, LOOP_DETECTED, Loop Detected) \
152
+ XX(510, NOT_EXTENDED, Not Extended) \
153
+ XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
154
+
155
+ enum http_status
156
+ {
157
+ #define XX(num, name, string) HTTP_STATUS_##name = num,
158
+ HTTP_STATUS_MAP(XX)
159
+ #undef XX
160
+ };
161
+
162
+
163
+ /* Request Methods */
164
+ #define HTTP_METHOD_MAP(XX) \
165
+ XX(0, DELETE, DELETE) \
166
+ XX(1, GET, GET) \
167
+ XX(2, HEAD, HEAD) \
168
+ XX(3, POST, POST) \
169
+ XX(4, PUT, PUT) \
170
+ /* pathological */ \
171
+ XX(5, CONNECT, CONNECT) \
172
+ XX(6, OPTIONS, OPTIONS) \
173
+ XX(7, TRACE, TRACE) \
174
+ /* WebDAV */ \
175
+ XX(8, COPY, COPY) \
176
+ XX(9, LOCK, LOCK) \
177
+ XX(10, MKCOL, MKCOL) \
178
+ XX(11, MOVE, MOVE) \
179
+ XX(12, PROPFIND, PROPFIND) \
180
+ XX(13, PROPPATCH, PROPPATCH) \
181
+ XX(14, SEARCH, SEARCH) \
182
+ XX(15, UNLOCK, UNLOCK) \
183
+ XX(16, BIND, BIND) \
184
+ XX(17, REBIND, REBIND) \
185
+ XX(18, UNBIND, UNBIND) \
186
+ XX(19, ACL, ACL) \
187
+ /* subversion */ \
188
+ XX(20, REPORT, REPORT) \
189
+ XX(21, MKACTIVITY, MKACTIVITY) \
190
+ XX(22, CHECKOUT, CHECKOUT) \
191
+ XX(23, MERGE, MERGE) \
192
+ /* upnp */ \
193
+ XX(24, MSEARCH, M-SEARCH) \
194
+ XX(25, NOTIFY, NOTIFY) \
195
+ XX(26, SUBSCRIBE, SUBSCRIBE) \
196
+ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
197
+ /* RFC-5789 */ \
198
+ XX(28, PATCH, PATCH) \
199
+ XX(29, PURGE, PURGE) \
200
+ /* CalDAV */ \
201
+ XX(30, MKCALENDAR, MKCALENDAR) \
202
+ /* RFC-2068, section 19.6.1.2 */ \
203
+ XX(31, LINK, LINK) \
204
+ XX(32, UNLINK, UNLINK) \
205
+
206
+ enum http_method
207
+ {
208
+ #define XX(num, name, string) HTTP_##name = num,
209
+ HTTP_METHOD_MAP(XX)
210
+ #undef XX
211
+ };
212
+
213
+
214
+ enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
215
+
216
+
217
+ /* Flag values for http_parser.flags field */
218
+ enum flags
219
+ { F_CHUNKED = 1 << 0
220
+ , F_CONNECTION_KEEP_ALIVE = 1 << 1
221
+ , F_CONNECTION_CLOSE = 1 << 2
222
+ , F_CONNECTION_UPGRADE = 1 << 3
223
+ , F_TRAILING = 1 << 4
224
+ , F_UPGRADE = 1 << 5
225
+ , F_SKIPBODY = 1 << 6
226
+ , F_CONTENTLENGTH = 1 << 7
227
+ };
228
+
229
+
230
+ /* Map for errno-related constants
231
+ *
232
+ * The provided argument should be a macro that takes 2 arguments.
233
+ */
234
+ #define HTTP_ERRNO_MAP(XX) \
235
+ /* No error */ \
236
+ XX(OK, "success") \
237
+ \
238
+ /* Callback-related errors */ \
239
+ XX(CB_message_begin, "the on_message_begin callback failed") \
240
+ XX(CB_url, "the on_url callback failed") \
241
+ XX(CB_header_field, "the on_header_field callback failed") \
242
+ XX(CB_header_value, "the on_header_value callback failed") \
243
+ XX(CB_headers_complete, "the on_headers_complete callback failed") \
244
+ XX(CB_body, "the on_body callback failed") \
245
+ XX(CB_message_complete, "the on_message_complete callback failed") \
246
+ XX(CB_status, "the on_status callback failed") \
247
+ XX(CB_chunk_header, "the on_chunk_header callback failed") \
248
+ XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
249
+ \
250
+ /* Parsing-related errors */ \
251
+ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
252
+ XX(HEADER_OVERFLOW, \
253
+ "too many header bytes seen; overflow detected") \
254
+ XX(CLOSED_CONNECTION, \
255
+ "data received after completed connection: close message") \
256
+ XX(INVALID_VERSION, "invalid HTTP version") \
257
+ XX(INVALID_STATUS, "invalid HTTP status code") \
258
+ XX(INVALID_METHOD, "invalid HTTP method") \
259
+ XX(INVALID_URL, "invalid URL") \
260
+ XX(INVALID_HOST, "invalid host") \
261
+ XX(INVALID_PORT, "invalid port") \
262
+ XX(INVALID_PATH, "invalid path") \
263
+ XX(INVALID_QUERY_STRING, "invalid query string") \
264
+ XX(INVALID_FRAGMENT, "invalid fragment") \
265
+ XX(LF_EXPECTED, "LF character expected") \
266
+ XX(INVALID_HEADER_TOKEN, "invalid character in header") \
267
+ XX(INVALID_CONTENT_LENGTH, \
268
+ "invalid character in content-length header") \
269
+ XX(UNEXPECTED_CONTENT_LENGTH, \
270
+ "unexpected content-length header") \
271
+ XX(INVALID_CHUNK_SIZE, \
272
+ "invalid character in chunk size header") \
273
+ XX(INVALID_CONSTANT, "invalid constant string") \
274
+ XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
275
+ XX(STRICT, "strict mode assertion failed") \
276
+ XX(PAUSED, "parser is paused") \
277
+ XX(UNKNOWN, "an unknown error occurred")
278
+
279
+
280
+ /* Define HPE_* values for each errno value above */
281
+ #define HTTP_ERRNO_GEN(n, s) HPE_##n,
282
+ enum http_errno {
283
+ HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
284
+ };
285
+ #undef HTTP_ERRNO_GEN
286
+
287
+
288
+ /* Get an http_errno value from an http_parser */
289
+ #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
290
+
291
+
292
+ struct http_parser {
293
+ /** PRIVATE **/
294
+ unsigned int type : 2; /* enum http_parser_type */
295
+ unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
296
+ unsigned int state : 7; /* enum state from http_parser.c */
297
+ unsigned int header_state : 7; /* enum header_state from http_parser.c */
298
+ unsigned int index : 7; /* index into current matcher */
299
+ unsigned int lenient_http_headers : 1;
300
+
301
+ uint32_t nread; /* # bytes read in various scenarios */
302
+ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
303
+
304
+ /** READ-ONLY **/
305
+ unsigned short http_major;
306
+ unsigned short http_minor;
307
+ unsigned int status_code : 16; /* responses only */
308
+ unsigned int method : 8; /* requests only */
309
+ unsigned int http_errno : 7;
310
+
311
+ /* 1 = Upgrade header was present and the parser has exited because of that.
312
+ * 0 = No upgrade header present.
313
+ * Should be checked when http_parser_execute() returns in addition to
314
+ * error checking.
315
+ */
316
+ unsigned int upgrade : 1;
317
+
318
+ /** PUBLIC **/
319
+ void *data; /* A pointer to get hook to the "connection" or "socket" object */
320
+ };
321
+
322
+
323
+ struct http_parser_settings {
324
+ http_cb on_message_begin;
325
+ http_data_cb on_url;
326
+ http_data_cb on_status;
327
+ http_data_cb on_header_field;
328
+ http_data_cb on_header_value;
329
+ http_cb on_headers_complete;
330
+ http_data_cb on_body;
331
+ http_cb on_message_complete;
332
+ /* When on_chunk_header is called, the current chunk length is stored
333
+ * in parser->content_length.
334
+ */
335
+ http_cb on_chunk_header;
336
+ http_cb on_chunk_complete;
337
+ };
338
+
339
+
340
+ enum http_parser_url_fields
341
+ { UF_SCHEMA = 0
342
+ , UF_HOST = 1
343
+ , UF_PORT = 2
344
+ , UF_PATH = 3
345
+ , UF_QUERY = 4
346
+ , UF_FRAGMENT = 5
347
+ , UF_USERINFO = 6
348
+ , UF_MAX = 7
349
+ };
350
+
351
+
352
+ /* Result structure for http_parser_parse_url().
353
+ *
354
+ * Callers should index into field_data[] with UF_* values iff field_set
355
+ * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
356
+ * because we probably have padding left over), we convert any port to
357
+ * a uint16_t.
358
+ */
359
+ struct http_parser_url {
360
+ uint16_t field_set; /* Bitmask of (1 << UF_*) values */
361
+ uint16_t port; /* Converted UF_PORT string */
362
+
363
+ struct {
364
+ uint16_t off; /* Offset into buffer in which field starts */
365
+ uint16_t len; /* Length of run in buffer */
366
+ } field_data[UF_MAX];
367
+ };
368
+
369
+
370
+ /* Returns the library version. Bits 16-23 contain the major version number,
371
+ * bits 8-15 the minor version number and bits 0-7 the patch level.
372
+ * Usage example:
373
+ *
374
+ * unsigned long version = http_parser_version();
375
+ * unsigned major = (version >> 16) & 255;
376
+ * unsigned minor = (version >> 8) & 255;
377
+ * unsigned patch = version & 255;
378
+ * printf("http_parser v%u.%u.%u\n", major, minor, patch);
379
+ */
380
+ unsigned long http_parser_version(void);
381
+
382
+ void http_parser_init(http_parser *parser, enum http_parser_type type);
383
+
384
+
385
+ /* Initialize http_parser_settings members to 0
386
+ */
387
+ void http_parser_settings_init(http_parser_settings *settings);
388
+
389
+
390
+ /* Executes the parser. Returns number of parsed bytes. Sets
391
+ * `parser->http_errno` on error. */
392
+ size_t http_parser_execute(http_parser *parser,
393
+ const http_parser_settings *settings,
394
+ const char *data,
395
+ size_t len);
396
+
397
+
398
+ /* If http_should_keep_alive() in the on_headers_complete or
399
+ * on_message_complete callback returns 0, then this should be
400
+ * the last message on the connection.
401
+ * If you are the server, respond with the "Connection: close" header.
402
+ * If you are the client, close the connection.
403
+ */
404
+ int http_should_keep_alive(const http_parser *parser);
405
+
406
+ /* Returns a string version of the HTTP method. */
407
+ const char *http_method_str(enum http_method m);
408
+
409
+ /* Return a string name of the given error */
410
+ const char *http_errno_name(enum http_errno err);
411
+
412
+ /* Return a string description of the given error */
413
+ const char *http_errno_description(enum http_errno err);
414
+
415
+ /* Initialize all http_parser_url members to 0 */
416
+ void http_parser_url_init(struct http_parser_url *u);
417
+
418
+ /* Parse a URL; return nonzero on failure */
419
+ int http_parser_parse_url(const char *buf, size_t buflen,
420
+ int is_connect,
421
+ struct http_parser_url *u);
422
+
423
+ /* Pause or un-pause the parser; a nonzero value pauses */
424
+ void http_parser_pause(http_parser *parser, int paused);
425
+
426
+ /* Checks if this is the final chunk of the body. */
427
+ int http_body_is_final(const http_parser *parser);
428
+
429
+ #ifdef __cplusplus
430
+ }
431
+ #endif
432
+ #endif