http_parser.rb 0.6.0.beta.1 → 0.6.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,11 +24,13 @@
24
24
  extern "C" {
25
25
  #endif
26
26
 
27
- #define HTTP_PARSER_VERSION_MAJOR 1
27
+ #define HTTP_PARSER_VERSION_MAJOR 2
28
28
  #define HTTP_PARSER_VERSION_MINOR 0
29
29
 
30
30
  #include <sys/types.h>
31
31
  #if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
32
+ #include <BaseTsd.h>
33
+ #include <stddef.h>
32
34
  typedef __int8 int8_t;
33
35
  typedef unsigned __int8 uint8_t;
34
36
  typedef __int16 int16_t;
@@ -37,9 +39,6 @@ typedef __int32 int32_t;
37
39
  typedef unsigned __int32 uint32_t;
38
40
  typedef __int64 int64_t;
39
41
  typedef unsigned __int64 uint64_t;
40
-
41
- typedef unsigned int size_t;
42
- typedef int ssize_t;
43
42
  #else
44
43
  #include <stdint.h>
45
44
  #endif
@@ -51,14 +50,6 @@ typedef int ssize_t;
51
50
  # define HTTP_PARSER_STRICT 1
52
51
  #endif
53
52
 
54
- /* Compile with -DHTTP_PARSER_DEBUG=1 to add extra debugging information to
55
- * the error reporting facility.
56
- */
57
- #ifndef HTTP_PARSER_DEBUG
58
- # define HTTP_PARSER_DEBUG 0
59
- #endif
60
-
61
-
62
53
  /* Maximium header size allowed */
63
54
  #define HTTP_MAX_HEADER_SIZE (80*1024)
64
55
 
@@ -77,7 +68,7 @@ typedef struct http_parser_settings http_parser_settings;
77
68
  * chunked' headers that indicate the presence of a body.
78
69
  *
79
70
  * http_data_cb does not return data chunks. It will be call arbitrarally
80
- * many times for each string. E.G. you might get 10 callbacks for "on_path"
71
+ * many times for each string. E.G. you might get 10 callbacks for "on_url"
81
72
  * each providing just a few characters more data.
82
73
  */
83
74
  typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
@@ -85,43 +76,44 @@ typedef int (*http_cb) (http_parser*);
85
76
 
86
77
 
87
78
  /* Request Methods */
88
- #define HTTP_METHOD_MAP(XX) \
89
- XX(0, DELETE) \
90
- XX(1, GET) \
91
- XX(2, HEAD) \
92
- XX(3, POST) \
93
- XX(4, PUT) \
94
- /* pathological */ \
95
- XX(5, CONNECT) \
96
- XX(6, OPTIONS) \
97
- XX(7, TRACE) \
98
- /* webdav */ \
99
- XX(8, COPY) \
100
- XX(9, LOCK) \
101
- XX(10, MKCOL) \
102
- XX(11, MOVE) \
103
- XX(12, PROPFIND) \
104
- XX(13, PROPPATCH) \
105
- XX(14, UNLOCK) \
106
- /* subversion */ \
107
- XX(15, REPORT) \
108
- XX(16, MKACTIVITY) \
109
- XX(17, CHECKOUT) \
110
- XX(18, MERGE) \
111
- /* upnp */ \
112
- XX(19, MSEARCH) \
113
- XX(20, NOTIFY) \
114
- XX(21, SUBSCRIBE) \
115
- XX(22, UNSUBSCRIBE) \
116
- /* RFC-5789 */ \
117
- XX(23, PATCH) \
118
- XX(24, PURGE) \
79
+ #define HTTP_METHOD_MAP(XX) \
80
+ XX(0, DELETE, DELETE) \
81
+ XX(1, GET, GET) \
82
+ XX(2, HEAD, HEAD) \
83
+ XX(3, POST, POST) \
84
+ XX(4, PUT, PUT) \
85
+ /* pathological */ \
86
+ XX(5, CONNECT, CONNECT) \
87
+ XX(6, OPTIONS, OPTIONS) \
88
+ XX(7, TRACE, TRACE) \
89
+ /* webdav */ \
90
+ XX(8, COPY, COPY) \
91
+ XX(9, LOCK, LOCK) \
92
+ XX(10, MKCOL, MKCOL) \
93
+ XX(11, MOVE, MOVE) \
94
+ XX(12, PROPFIND, PROPFIND) \
95
+ XX(13, PROPPATCH, PROPPATCH) \
96
+ XX(14, SEARCH, SEARCH) \
97
+ XX(15, UNLOCK, UNLOCK) \
98
+ /* subversion */ \
99
+ XX(16, REPORT, REPORT) \
100
+ XX(17, MKACTIVITY, MKACTIVITY) \
101
+ XX(18, CHECKOUT, CHECKOUT) \
102
+ XX(19, MERGE, MERGE) \
103
+ /* upnp */ \
104
+ XX(20, MSEARCH, M-SEARCH) \
105
+ XX(21, NOTIFY, NOTIFY) \
106
+ XX(22, SUBSCRIBE, SUBSCRIBE) \
107
+ XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
108
+ /* RFC-5789 */ \
109
+ XX(24, PATCH, PATCH) \
110
+ XX(25, PURGE, PURGE) \
119
111
 
120
112
  enum http_method
121
113
  {
122
- #define XX(num, name) HTTP_##name = num,
114
+ #define XX(num, name, string) HTTP_##name = num,
123
115
  HTTP_METHOD_MAP(XX)
124
- #undef X
116
+ #undef XX
125
117
  };
126
118
 
127
119
 
@@ -140,7 +132,7 @@ enum flags
140
132
 
141
133
 
142
134
  /* Map for errno-related constants
143
- *
135
+ *
144
136
  * The provided argument should be a macro that takes 2 arguments.
145
137
  */
146
138
  #define HTTP_ERRNO_MAP(XX) \
@@ -149,6 +141,7 @@ enum flags
149
141
  \
150
142
  /* Callback-related errors */ \
151
143
  XX(CB_message_begin, "the on_message_begin callback failed") \
144
+ XX(CB_status_complete, "the on_status_complete callback failed") \
152
145
  XX(CB_url, "the on_url callback failed") \
153
146
  XX(CB_header_field, "the on_header_field callback failed") \
154
147
  XX(CB_header_value, "the on_header_value callback failed") \
@@ -195,13 +188,6 @@ enum http_errno {
195
188
  /* Get an http_errno value from an http_parser */
196
189
  #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
197
190
 
198
- /* Get the line number that generated the current error */
199
- #if HTTP_PARSER_DEBUG
200
- #define HTTP_PARSER_ERRNO_LINE(p) ((p)->error_lineno)
201
- #else
202
- #define HTTP_PARSER_ERRNO_LINE(p) 0
203
- #endif
204
-
205
191
 
206
192
  struct http_parser {
207
193
  /** PRIVATE **/
@@ -228,10 +214,6 @@ struct http_parser {
228
214
  */
229
215
  unsigned char upgrade : 1;
230
216
 
231
- #if HTTP_PARSER_DEBUG
232
- uint32_t error_lineno;
233
- #endif
234
-
235
217
  /** PUBLIC **/
236
218
  void *data; /* A pointer to get hook to the "connection" or "socket" object */
237
219
  };
@@ -240,6 +222,7 @@ struct http_parser {
240
222
  struct http_parser_settings {
241
223
  http_cb on_message_begin;
242
224
  http_data_cb on_url;
225
+ http_cb on_status_complete;
243
226
  http_data_cb on_header_field;
244
227
  http_data_cb on_header_value;
245
228
  http_cb on_headers_complete;
@@ -255,7 +238,8 @@ enum http_parser_url_fields
255
238
  , UF_PATH = 3
256
239
  , UF_QUERY = 4
257
240
  , UF_FRAGMENT = 5
258
- , UF_MAX = 6
241
+ , UF_USERINFO = 6
242
+ , UF_MAX = 7
259
243
  };
260
244
 
261
245
 
@@ -287,12 +271,12 @@ size_t http_parser_execute(http_parser *parser,
287
271
 
288
272
 
289
273
  /* If http_should_keep_alive() in the on_headers_complete or
290
- * on_message_complete callback returns true, then this will be should be
274
+ * on_message_complete callback returns 0, then this should be
291
275
  * the last message on the connection.
292
276
  * If you are the server, respond with the "Connection: close" header.
293
277
  * If you are the client, close the connection.
294
278
  */
295
- int http_should_keep_alive(http_parser *parser);
279
+ int http_should_keep_alive(const http_parser *parser);
296
280
 
297
281
  /* Returns a string version of the HTTP method. */
298
282
  const char *http_method_str(enum http_method m);
@@ -311,6 +295,9 @@ int http_parser_parse_url(const char *buf, size_t buflen,
311
295
  /* Pause or un-pause the parser; a nonzero value pauses */
312
296
  void http_parser_pause(http_parser *parser, int paused);
313
297
 
298
+ /* Checks if this is the final chunk of the body. */
299
+ int http_body_is_final(const http_parser *parser);
300
+
314
301
  #ifdef __cplusplus
315
302
  }
316
303
  #endif
@@ -8,6 +8,7 @@ public enum HTTPMethod {
8
8
  , HTTP_HEAD("HEAD")
9
9
  , HTTP_POST("POST")
10
10
  , HTTP_PUT("PUT")
11
+ , HTTP_PATCH("PATCH")
11
12
  /* pathological */
12
13
  , HTTP_CONNECT("CONNECT")
13
14
  , HTTP_OPTIONS("OPTIONS")
@@ -28,7 +29,6 @@ public enum HTTPMethod {
28
29
  , HTTP_NOTIFY("NOTIFY")
29
30
  , HTTP_SUBSCRIBE("SUBSCRIBE")
30
31
  , HTTP_UNSUBSCRIBE("UNSUBSCRIBE")
31
- , HTTP_PATCH("PATCH")
32
32
  , HTTP_PURGE("PURGE")
33
33
  ;
34
34
 
@@ -39,7 +39,7 @@ public enum HTTPMethod {
39
39
  public byte[] bytes;
40
40
 
41
41
  HTTPMethod(String name) {
42
- // good grief, Charlie Brown, the following is necessary because
42
+ // good grief, Charlie Brown, the following is necessary because
43
43
  // java is retarded:
44
44
  // illegal reference to static field from initializer
45
45
  // this.bytes = name.getBytes(ASCII);
@@ -58,6 +58,8 @@ public enum HTTPMethod {
58
58
  else if ("POST".equalsIgnoreCase(s)) {return HTTP_POST;}
59
59
  else if ("HTTP_PUT".equalsIgnoreCase(s)) {return HTTP_PUT;}
60
60
  else if ("PUT".equalsIgnoreCase(s)) {return HTTP_PUT;}
61
+ else if ("HTTP_PATCH".equalsIgnoreCase(s)) {return HTTP_PATCH;}
62
+ else if ("PATCH".equalsIgnoreCase(s)) {return HTTP_PATCH;}
61
63
  else if ("HTTP_CONNECT".equalsIgnoreCase(s)) {return HTTP_CONNECT;}
62
64
  else if ("CONNECT".equalsIgnoreCase(s)) {return HTTP_CONNECT;}
63
65
  else if ("HTTP_OPTIONS".equalsIgnoreCase(s)) {return HTTP_OPTIONS;}
@@ -97,7 +99,7 @@ public enum HTTPMethod {
97
99
  else if ("PATCH".equalsIgnoreCase(s)) {return HTTP_PATCH;}
98
100
  else if ("PURGE".equalsIgnoreCase(s)) {return HTTP_PURGE;}
99
101
  else {return null;}
100
- }
102
+ }
101
103
  void init (String name) {
102
104
  ASCII = null == ASCII ? Charset.forName("US-ASCII") : ASCII;
103
105
  this.bytes = name.getBytes(ASCII);
@@ -5,45 +5,47 @@ package http_parser;
5
5
  import primitive.collection.ByteList;
6
6
 
7
7
  public class ParserSettings extends http_parser.lolevel.ParserSettings {
8
-
8
+
9
9
  public HTTPCallback on_message_begin;
10
10
  public HTTPDataCallback on_path;
11
11
  public HTTPDataCallback on_query_string;
12
12
  public HTTPDataCallback on_url;
13
13
  public HTTPDataCallback on_fragment;
14
+ public HTTPCallback on_status_complete;
14
15
  public HTTPDataCallback on_header_field;
15
16
  public HTTPDataCallback on_header_value;
16
-
17
+
17
18
  public HTTPCallback on_headers_complete;
18
19
  public HTTPDataCallback on_body;
19
20
  public HTTPCallback on_message_complete;
20
-
21
+
21
22
  public HTTPErrorCallback on_error;
22
-
23
+
23
24
  private HTTPCallback _on_message_begin;
24
25
  private HTTPDataCallback _on_path;
25
26
  private HTTPDataCallback _on_query_string;
26
27
  private HTTPDataCallback _on_url;
27
28
  private HTTPDataCallback _on_fragment;
29
+ private HTTPCallback _on_status_complete;
28
30
  private HTTPDataCallback _on_header_field;
29
31
  private HTTPDataCallback _on_header_value;
30
- private HTTPHeadersCompleteCallback _on_headers_complete;
32
+ private HTTPCallback _on_headers_complete;
31
33
  private HTTPDataCallback _on_body;
32
34
  private HTTPCallback _on_message_complete;
33
35
  private HTTPErrorCallback _on_error;
34
-
36
+
35
37
  private http_parser.lolevel.ParserSettings settings;
36
-
38
+
37
39
  protected ByteList field = new ByteList();
38
40
  protected ByteList value = new ByteList();
39
41
  protected ByteList body = new ByteList();
40
-
42
+
41
43
  public ParserSettings() {
42
44
  this.settings = new http_parser.lolevel.ParserSettings();
43
45
  createMirrorCallbacks();
44
46
  attachCallbacks();
45
47
  }
46
-
48
+
47
49
  protected http_parser.lolevel.ParserSettings getLoLevelSettings() {
48
50
  return this.settings;
49
51
  }
@@ -93,7 +95,16 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
93
95
  return 0;
94
96
  }
95
97
  };
96
- this._on_error = new HTTPErrorCallback() {
98
+ this._on_status_complete = new HTTPCallback() {
99
+ @Override
100
+ public int cb(HTTPParser p) {
101
+ if (null != ParserSettings.this.on_status_complete) {
102
+ return ParserSettings.this.on_status_complete.cb(p);
103
+ }
104
+ return 0;
105
+ }
106
+ };
107
+ this._on_error = new HTTPErrorCallback() {
97
108
  @Override
98
109
  public void cb(HTTPParser parser, String error) {
99
110
  if (null != ParserSettings.this.on_error) {
@@ -101,11 +112,11 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
101
112
  } else {
102
113
  throw new HTTPException(error);
103
114
  }
104
-
115
+
105
116
  }
106
117
  };
107
-
108
-
118
+
119
+
109
120
 
110
121
  // (on_header_field and on_header_value shortened to on_h_*)
111
122
  // ------------------------ ------------ --------------------------------------------
@@ -142,19 +153,19 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
142
153
  ParserSettings.this.value.clear();
143
154
  }
144
155
  }
145
-
156
+
146
157
  if (null == ParserSettings.this.on_header_field) {
147
158
  return 0;
148
159
  }
149
-
160
+
150
161
  ParserSettings.this.field.addAll(by);
151
162
  return 0;
152
163
  }
153
164
  };
154
- this._on_header_value = new HTTPDataCallback() {
165
+ this._on_header_value = new HTTPDataCallback() {
155
166
  @Override
156
167
  public int cb(HTTPParser p, byte[] by, int pos, int len) {
157
-
168
+
158
169
  // previous field complete, call on_field with full field value, reset field.
159
170
  if (0 != ParserSettings.this.field.size()) {
160
171
  // check we're even interested...
@@ -167,7 +178,7 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
167
178
  ParserSettings.this.field.clear();
168
179
  }
169
180
  }
170
-
181
+
171
182
  if (null == ParserSettings.this.on_header_value) {
172
183
  return 0;
173
184
  }
@@ -175,7 +186,7 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
175
186
  return 0;
176
187
  }
177
188
  };
178
- this._on_headers_complete = new HTTPHeadersCompleteCallback() {
189
+ this._on_headers_complete = new HTTPCallback() {
179
190
  @Override
180
191
  public int cb(HTTPParser parser) {
181
192
  // is there an uncompleted value ... ?
@@ -195,9 +206,9 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
195
206
  }
196
207
  return 0;
197
208
  }
198
-
209
+
199
210
  };
200
- this._on_body = new HTTPDataCallback() {
211
+ this._on_body = new HTTPDataCallback() {
201
212
  @Override
202
213
  public int cb(HTTPParser p, byte[] by, int pos, int len) {
203
214
  if (null != ParserSettings.this.on_body) {
@@ -206,8 +217,8 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
206
217
  return 0;
207
218
  }
208
219
  };
209
-
210
- this._on_message_complete = new HTTPCallback() {
220
+
221
+ this._on_message_complete = new HTTPCallback() {
211
222
  @Override
212
223
  public int cb(HTTPParser parser) {
213
224
  if (null != ParserSettings.this.on_body) {
@@ -224,7 +235,7 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
224
235
  return 0;
225
236
  }
226
237
  };
227
-
238
+
228
239
  }
229
240
 
230
241
  private void attachCallbacks() {
@@ -234,90 +245,12 @@ public class ParserSettings extends http_parser.lolevel.ParserSettings {
234
245
  this.settings.on_query_string = this._on_query_string;
235
246
  this.settings.on_url = this._on_url;
236
247
  this.settings.on_fragment = this._on_fragment;
248
+ this.settings.on_status_complete = this._on_status_complete;
237
249
  this.settings.on_header_field = this._on_header_field;
238
- this.settings.on_header_value = this._on_header_value;
250
+ this.settings.on_header_value = this._on_header_value;
239
251
  this.settings.on_headers_complete = this._on_headers_complete;
240
252
  this.settings.on_body = this._on_body;
241
253
  this.settings.on_message_complete = this._on_message_complete;
242
254
  this.settings.on_error = this._on_error;
243
255
  }
244
256
  }
245
- //import http_parser.HTTPException;
246
- //public class ParserSettings extends http_parser.lolevel.ParserSettings{
247
- //
248
- //
249
- //
250
- //
251
- // public HTTPCallback on_message_begin;
252
- // public HTTPDataCallback on_path;
253
- // public HTTPDataCallback on_query_string;
254
- // public HTTPDataCallback on_url;
255
- // public HTTPDataCallback on_fragment;
256
- // public HTTPDataCallback on_header_field;
257
- // public HTTPDataCallback on_header_value;
258
- // public HTTPCallback on_headers_complete;
259
- // public HTTPDataCallback on_body;
260
- // public HTTPCallback on_message_complete;
261
- // public HTTPErrorCallback on_error;
262
- //
263
- // void call_on_message_begin (HTTPParser p) {
264
- // call_on(on_message_begin, p);
265
- // }
266
- //
267
- // void call_on_message_complete (HTTPParser p) {
268
- // call_on(on_message_complete, p);
269
- // }
270
- //
271
- // // this one is a little bit different:
272
- // // the current `position` of the buffer is the location of the
273
- // // error, `ini_pos` indicates where the position of
274
- // // the buffer when it was passed to the `execute` method of the parser, i.e.
275
- // // using this information and `limit` we'll know all the valid data
276
- // // in the buffer around the error we can use to print pretty error
277
- // // messages.
278
- // void call_on_error (HTTPParser p, String mes, ByteBuffer buf, int ini_pos) {
279
- // if (null != on_error) {
280
- // on_error.cb(p, mes, buf, ini_pos);
281
- // }
282
- // // if on_error gets called it MUST throw an exception, else the parser
283
- // // will attempt to continue parsing, which it can't because it's
284
- // // in an invalid state.
285
- // throw new HTTPException(mes);
286
- // }
287
- //
288
- // void call_on_header_field (HTTPParser p, ByteBuffer buf, int pos, int len) {
289
- // call_on(on_header_field, p, buf, pos, len);
290
- // }
291
- // void call_on_query_string (HTTPParser p, ByteBuffer buf, int pos, int len) {
292
- // call_on(on_query_string, p, buf, pos, len);
293
- // }
294
- // void call_on_fragment (HTTPParser p, ByteBuffer buf, int pos, int len) {
295
- // call_on(on_fragment, p, buf, pos, len);
296
- // }
297
- // void call_on_path (HTTPParser p, ByteBuffer buf, int pos, int len) {
298
- // call_on(on_path, p, buf, pos, len);
299
- // }
300
- // void call_on_header_value (HTTPParser p, ByteBuffer buf, int pos, int len) {
301
- // call_on(on_header_value, p, buf, pos, len);
302
- // }
303
- // void call_on_url (HTTPParser p, ByteBuffer buf, int pos, int len) {
304
- // call_on(on_url, p, buf, pos, len);
305
- // }
306
- // void call_on_body(HTTPParser p, ByteBuffer buf, int pos, int len) {
307
- // call_on(on_body, p, buf, pos, len);
308
- // }
309
- // void call_on_headers_complete(HTTPParser p) {
310
- // call_on(on_headers_complete, p);
311
- // }
312
- // void call_on (HTTPCallback cb, HTTPParser p) {
313
- // // cf. CALLBACK2 macro
314
- // if (null != cb) {
315
- // cb.cb(p);
316
- // }
317
- // }
318
- // void call_on (HTTPDataCallback cb, HTTPParser p, ByteBuffer buf, int pos, int len) {
319
- // if (null != cb && -1 != pos) {
320
- // cb.cb(p,buf,pos,len);
321
- // }
322
- // }
323
- //}