llhttp 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/llhttp/llhttp.h CHANGED
@@ -24,9 +24,13 @@
24
24
  #ifndef INCLUDE_LLHTTP_H_
25
25
  #define INCLUDE_LLHTTP_H_
26
26
 
27
- #define LLHTTP_VERSION_MAJOR 1
28
- #define LLHTTP_VERSION_MINOR 1
29
- #define LLHTTP_VERSION_PATCH 1
27
+ #define LLHTTP_VERSION_MAJOR 4
28
+ #define LLHTTP_VERSION_MINOR 0
29
+ #define LLHTTP_VERSION_PATCH 0
30
+
31
+ #ifndef LLHTTP_STRICT_MODE
32
+ # define LLHTTP_STRICT_MODE 0
33
+ #endif
30
34
 
31
35
  #ifndef INCLUDE_LLHTTP_ITSELF_H_
32
36
  #define INCLUDE_LLHTTP_ITSELF_H_
@@ -52,10 +56,11 @@ struct llhttp__internal_s {
52
56
  uint8_t http_major;
53
57
  uint8_t http_minor;
54
58
  uint8_t header_state;
55
- uint8_t flags;
59
+ uint8_t lenient_flags;
56
60
  uint8_t upgrade;
57
- uint16_t status_code;
58
61
  uint8_t finish;
62
+ uint16_t flags;
63
+ uint16_t status_code;
59
64
  void* settings;
60
65
  };
61
66
 
@@ -89,14 +94,15 @@ enum llhttp_errno {
89
94
  HPE_INVALID_CHUNK_SIZE = 12,
90
95
  HPE_INVALID_STATUS = 13,
91
96
  HPE_INVALID_EOF_STATE = 14,
92
- HPE_CB_MESSAGE_BEGIN = 15,
93
- HPE_CB_HEADERS_COMPLETE = 16,
94
- HPE_CB_MESSAGE_COMPLETE = 17,
95
- HPE_CB_CHUNK_HEADER = 18,
96
- HPE_CB_CHUNK_COMPLETE = 19,
97
- HPE_PAUSED = 20,
98
- HPE_PAUSED_UPGRADE = 21,
99
- HPE_USER = 22
97
+ HPE_INVALID_TRANSFER_ENCODING = 15,
98
+ HPE_CB_MESSAGE_BEGIN = 16,
99
+ HPE_CB_HEADERS_COMPLETE = 17,
100
+ HPE_CB_MESSAGE_COMPLETE = 18,
101
+ HPE_CB_CHUNK_HEADER = 19,
102
+ HPE_CB_CHUNK_COMPLETE = 20,
103
+ HPE_PAUSED = 21,
104
+ HPE_PAUSED_UPGRADE = 22,
105
+ HPE_USER = 23
100
106
  };
101
107
  typedef enum llhttp_errno llhttp_errno_t;
102
108
 
@@ -108,10 +114,17 @@ enum llhttp_flags {
108
114
  F_UPGRADE = 0x10,
109
115
  F_CONTENT_LENGTH = 0x20,
110
116
  F_SKIPBODY = 0x40,
111
- F_TRAILING = 0x80
117
+ F_TRAILING = 0x80,
118
+ F_TRANSFER_ENCODING = 0x200
112
119
  };
113
120
  typedef enum llhttp_flags llhttp_flags_t;
114
121
 
122
+ enum llhttp_lenient_flags {
123
+ LENIENT_HEADERS = 0x1,
124
+ LENIENT_CHUNKED_LENGTH = 0x2
125
+ };
126
+ typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
127
+
115
128
  enum llhttp_type {
116
129
  HTTP_BOTH = 0,
117
130
  HTTP_REQUEST = 1,
@@ -160,7 +173,19 @@ enum llhttp_method {
160
173
  HTTP_MKCALENDAR = 30,
161
174
  HTTP_LINK = 31,
162
175
  HTTP_UNLINK = 32,
163
- HTTP_SOURCE = 33
176
+ HTTP_SOURCE = 33,
177
+ HTTP_PRI = 34,
178
+ HTTP_DESCRIBE = 35,
179
+ HTTP_ANNOUNCE = 36,
180
+ HTTP_SETUP = 37,
181
+ HTTP_PLAY = 38,
182
+ HTTP_PAUSE = 39,
183
+ HTTP_TEARDOWN = 40,
184
+ HTTP_GET_PARAMETER = 41,
185
+ HTTP_SET_PARAMETER = 42,
186
+ HTTP_REDIRECT = 43,
187
+ HTTP_RECORD = 44,
188
+ HTTP_FLUSH = 45
164
189
  };
165
190
  typedef enum llhttp_method llhttp_method_t;
166
191
 
@@ -180,14 +205,15 @@ typedef enum llhttp_method llhttp_method_t;
180
205
  XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
181
206
  XX(13, INVALID_STATUS, INVALID_STATUS) \
182
207
  XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
183
- XX(15, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
184
- XX(16, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
185
- XX(17, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
186
- XX(18, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
187
- XX(19, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
188
- XX(20, PAUSED, PAUSED) \
189
- XX(21, PAUSED_UPGRADE, PAUSED_UPGRADE) \
190
- XX(22, USER, USER) \
208
+ XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
209
+ XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
210
+ XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
211
+ XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
212
+ XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
213
+ XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
214
+ XX(21, PAUSED, PAUSED) \
215
+ XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
216
+ XX(23, USER, USER) \
191
217
 
192
218
 
193
219
  #define HTTP_METHOD_MAP(XX) \
@@ -225,6 +251,18 @@ typedef enum llhttp_method llhttp_method_t;
225
251
  XX(31, LINK, LINK) \
226
252
  XX(32, UNLINK, UNLINK) \
227
253
  XX(33, SOURCE, SOURCE) \
254
+ XX(34, PRI, PRI) \
255
+ XX(35, DESCRIBE, DESCRIBE) \
256
+ XX(36, ANNOUNCE, ANNOUNCE) \
257
+ XX(37, SETUP, SETUP) \
258
+ XX(38, PLAY, PLAY) \
259
+ XX(39, PAUSE, PAUSE) \
260
+ XX(40, TEARDOWN, TEARDOWN) \
261
+ XX(41, GET_PARAMETER, GET_PARAMETER) \
262
+ XX(42, SET_PARAMETER, SET_PARAMETER) \
263
+ XX(43, REDIRECT, REDIRECT) \
264
+ XX(44, RECORD, RECORD) \
265
+ XX(45, FLUSH, FLUSH) \
228
266
 
229
267
 
230
268
 
@@ -277,12 +315,27 @@ struct llhttp_settings_s {
277
315
  */
278
316
  llhttp_cb on_chunk_header;
279
317
  llhttp_cb on_chunk_complete;
318
+
319
+ llhttp_cb on_url_complete;
320
+ llhttp_cb on_status_complete;
321
+ llhttp_cb on_header_field_complete;
322
+ llhttp_cb on_header_value_complete;
280
323
  };
281
324
 
282
- /* Initialize the parser with specific type and user settings */
325
+ /* Initialize the parser with specific type and user settings.
326
+ *
327
+ * NOTE: lifetime of `settings` has to be at least the same as the lifetime of
328
+ * the `parser` here. In practice, `settings` has to be either a static
329
+ * variable or be allocated with `malloc`, `new`, etc.
330
+ */
283
331
  void llhttp_init(llhttp_t* parser, llhttp_type_t type,
284
332
  const llhttp_settings_t* settings);
285
333
 
334
+ /* Reset an already initialized parser back to the start state, preserving the
335
+ * existing parser type, callback settings, user data, and lenient flags.
336
+ */
337
+ void llhttp_reset(llhttp_t* parser);
338
+
286
339
  /* Initialize the settings object */
287
340
  void llhttp_settings_init(llhttp_settings_t* settings);
288
341
 
@@ -300,7 +353,7 @@ void llhttp_settings_init(llhttp_settings_t* settings);
300
353
  *
301
354
  * NOTE: if this function ever returns a non-pause type error, it will continue
302
355
  * to return the same error upon each successive call up until `llhttp_init()`
303
- * call.
356
+ * is called.
304
357
  */
305
358
  llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
306
359
 
@@ -320,7 +373,7 @@ llhttp_errno_t llhttp_finish(llhttp_t* parser);
320
373
  int llhttp_message_needs_eof(const llhttp_t* parser);
321
374
 
322
375
  /* Returns `1` if there might be any other messages following the last that was
323
- * successfuly parsed.
376
+ * successfully parsed.
324
377
  */
325
378
  int llhttp_should_keep_alive(const llhttp_t* parser);
326
379
 
@@ -376,6 +429,31 @@ const char* llhttp_errno_name(llhttp_errno_t err);
376
429
  /* Returns textual name of HTTP method */
377
430
  const char* llhttp_method_name(llhttp_method_t method);
378
431
 
432
+
433
+ /* Enables/disables lenient header value parsing (disabled by default).
434
+ *
435
+ * Lenient parsing disables header value token checks, extending llhttp's
436
+ * protocol support to highly non-compliant clients/server. No
437
+ * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
438
+ * lenient parsing is "on".
439
+ *
440
+ * **(USE AT YOUR OWN RISK)**
441
+ */
442
+ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
443
+
444
+
445
+ /* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
446
+ * `Content-Length` headers (disabled by default).
447
+ *
448
+ * Normally `llhttp` would error when `Transfer-Encoding` is present in
449
+ * conjunction with `Content-Length`. This error is important to prevent HTTP
450
+ * request smuggling, but may be less desirable for small number of cases
451
+ * involving legacy servers.
452
+ *
453
+ * **(USE AT YOUR OWN RISK)**
454
+ */
455
+ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
456
+
379
457
  #ifdef __cplusplus
380
458
  } /* extern "C" */
381
459
  #endif
@@ -1,25 +1,8 @@
1
- // This software is licensed under the MIT License.
1
+ /*
2
+ This software is licensed under the MPL-2.0 License.
2
3
 
3
- // Copyright Bryan Powell, 2020.
4
-
5
- // Permission is hereby granted, free of charge, to any person obtaining a
6
- // copy of this software and associated documentation files (the
7
- // "Software"), to deal in the Software without restriction, including
8
- // without limitation the rights to use, copy, modify, merge, publish,
9
- // distribute, sublicense, and/or sell copies of the Software, and to permit
10
- // persons to whom the Software is furnished to do so, subject to the
11
- // following conditions:
12
-
13
- // The above copyright notice and this permission notice shall be included
14
- // in all copies or substantial portions of the Software.
15
-
16
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
19
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
4
+ Copyright Bryan Powell, 2020.
5
+ */
23
6
 
24
7
  #include <ruby/ruby.h>
25
8
 
@@ -27,6 +10,21 @@
27
10
 
28
11
  static VALUE mLLHttp, cParser, eError;
29
12
 
13
+ static ID rb_llhttp_callback_on_message_begin;
14
+ static ID rb_llhttp_callback_on_url;
15
+ static ID rb_llhttp_callback_on_status;
16
+ static ID rb_llhttp_callback_on_header_field;
17
+ static ID rb_llhttp_callback_on_header_value;
18
+ static ID rb_llhttp_callback_on_headers_complete;
19
+ static ID rb_llhttp_callback_on_body;
20
+ static ID rb_llhttp_callback_on_message_complete;
21
+ static ID rb_llhttp_callback_on_chunk_header;
22
+ static ID rb_llhttp_callback_on_chunk_complete;
23
+ static ID rb_llhttp_callback_on_url_complete;
24
+ static ID rb_llhttp_callback_on_status_complete;
25
+ static ID rb_llhttp_callback_on_header_field_complete;
26
+ static ID rb_llhttp_callback_on_header_value_complete;
27
+
30
28
  static void rb_llhttp_free(llhttp_t *parser) {
31
29
  if (parser) {
32
30
  free(parser->settings);
@@ -44,90 +42,86 @@ VALUE rb_llhttp_allocate(VALUE klass) {
44
42
  return Data_Wrap_Struct(klass, 0, rb_llhttp_free, parser);
45
43
  }
46
44
 
47
- void rb_llhttp_callback_call(VALUE delegate, const char *name) {
48
- rb_funcall(delegate, rb_intern(name), 0);
45
+ VALUE rb_llhttp_callback_call(VALUE delegate, ID method) {
46
+ return rb_funcall(delegate, method, 0);
49
47
  }
50
48
 
51
- void rb_llhttp_data_callback_call(VALUE delegate, const char *name, char *data, size_t length) {
52
- rb_funcall(delegate, rb_intern(name), 1, rb_str_new(data, length));
49
+ void rb_llhttp_data_callback_call(VALUE delegate, ID method, char *data, size_t length) {
50
+ rb_funcall(delegate, method, 1, rb_str_new(data, length));
53
51
  }
54
52
 
55
53
  int rb_llhttp_on_message_begin(llhttp_t *parser) {
56
- VALUE delegate = (VALUE)parser->data;
54
+ return NUM2INT(rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_message_begin));
55
+ }
57
56
 
58
- rb_llhttp_callback_call(delegate, "on_message_begin");
57
+ int rb_llhttp_on_headers_complete(llhttp_t *parser) {
58
+ return NUM2INT(rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_headers_complete));
59
+ }
59
60
 
60
- return 0;
61
+ int rb_llhttp_on_message_complete(llhttp_t *parser) {
62
+ return NUM2INT(rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_message_complete));
61
63
  }
62
64
 
63
- int rb_llhttp_on_url(llhttp_t *parser, char *data, size_t length) {
64
- VALUE delegate = (VALUE)parser->data;
65
+ int rb_llhttp_on_chunk_header(llhttp_t *parser) {
66
+ return NUM2INT(rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_chunk_header));
67
+ }
65
68
 
66
- rb_llhttp_data_callback_call(delegate, "on_url", data, length);
69
+ int rb_llhttp_on_url(llhttp_t *parser, char *data, size_t length) {
70
+ rb_llhttp_data_callback_call((VALUE)parser->data, rb_llhttp_callback_on_url, data, length);
67
71
 
68
72
  return 0;
69
73
  }
70
74
 
71
75
  int rb_llhttp_on_status(llhttp_t *parser, char *data, size_t length) {
72
- VALUE delegate = (VALUE)parser->data;
73
-
74
- rb_llhttp_data_callback_call(delegate, "on_status", data, length);
76
+ rb_llhttp_data_callback_call((VALUE)parser->data, rb_llhttp_callback_on_status, data, length);
75
77
 
76
78
  return 0;
77
79
  }
78
80
 
79
81
  int rb_llhttp_on_header_field(llhttp_t *parser, char *data, size_t length) {
80
- VALUE delegate = (VALUE)parser->data;
81
-
82
- rb_llhttp_data_callback_call(delegate, "on_header_field", data, length);
82
+ rb_llhttp_data_callback_call((VALUE)parser->data, rb_llhttp_callback_on_header_field, data, length);
83
83
 
84
84
  return 0;
85
85
  }
86
86
 
87
87
  int rb_llhttp_on_header_value(llhttp_t *parser, char *data, size_t length) {
88
- VALUE delegate = (VALUE)parser->data;
89
-
90
- rb_llhttp_data_callback_call(delegate, "on_header_value", data, length);
88
+ rb_llhttp_data_callback_call((VALUE)parser->data, rb_llhttp_callback_on_header_value, data, length);
91
89
 
92
90
  return 0;
93
91
  }
94
92
 
95
- int rb_llhttp_on_headers_complete(llhttp_t *parser) {
96
- VALUE delegate = (VALUE)parser->data;
97
-
98
- rb_llhttp_callback_call(delegate, "on_headers_complete");
93
+ int rb_llhttp_on_body(llhttp_t *parser, char *data, size_t length) {
94
+ rb_llhttp_data_callback_call((VALUE)parser->data, rb_llhttp_callback_on_body, data, length);
99
95
 
100
96
  return 0;
101
97
  }
102
98
 
103
- int rb_llhttp_on_body(llhttp_t *parser, char *data, size_t length) {
104
- VALUE delegate = (VALUE)parser->data;
105
-
106
- rb_llhttp_data_callback_call(delegate, "on_body", data, length);
99
+ int rb_llhttp_on_chunk_complete(llhttp_t *parser) {
100
+ rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_chunk_complete);
107
101
 
108
102
  return 0;
109
103
  }
110
104
 
111
- int rb_llhttp_on_message_complete(llhttp_t *parser) {
112
- VALUE delegate = (VALUE)parser->data;
113
-
114
- rb_llhttp_callback_call(delegate, "on_message_complete");
105
+ int rb_llhttp_on_url_complete(llhttp_t *parser) {
106
+ rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_url_complete);
115
107
 
116
108
  return 0;
117
109
  }
118
110
 
119
- int rb_llhttp_on_chunk_header(llhttp_t *parser) {
120
- VALUE delegate = (VALUE)parser->data;
121
-
122
- rb_llhttp_callback_call(delegate, "on_chunk_header");
111
+ int rb_llhttp_on_status_complete(llhttp_t *parser) {
112
+ rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_status_complete);
123
113
 
124
114
  return 0;
125
115
  }
126
116
 
127
- int rb_llhttp_on_chunk_complete(llhttp_t *parser) {
128
- VALUE delegate = (VALUE)parser->data;
117
+ int rb_llhttp_on_header_field_complete(llhttp_t *parser) {
118
+ rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_header_field_complete);
129
119
 
130
- rb_llhttp_callback_call(delegate, "on_chunk_complete");
120
+ return 0;
121
+ }
122
+
123
+ int rb_llhttp_on_header_value_complete(llhttp_t *parser) {
124
+ rb_llhttp_callback_call((VALUE)parser->data, rb_llhttp_callback_on_header_value_complete);
131
125
 
132
126
  return 0;
133
127
  }
@@ -165,10 +159,10 @@ VALUE rb_llhttp_content_length(VALUE self) {
165
159
 
166
160
  Data_Get_Struct(self, llhttp_t, parser);
167
161
 
168
- return UINT2NUM(parser->content_length);
162
+ return ULL2NUM(parser->content_length);
169
163
  }
170
164
 
171
- VALUE rb_llhttp_method(VALUE self) {
165
+ VALUE rb_llhttp_method_name(VALUE self) {
172
166
  llhttp_t *parser;
173
167
 
174
168
  Data_Get_Struct(self, llhttp_t, parser);
@@ -184,6 +178,22 @@ VALUE rb_llhttp_status_code(VALUE self) {
184
178
  return UINT2NUM(parser->status_code);
185
179
  }
186
180
 
181
+ VALUE rb_llhttp_http_major(VALUE self) {
182
+ llhttp_t *parser;
183
+
184
+ Data_Get_Struct(self, llhttp_t, parser);
185
+
186
+ return UINT2NUM(parser->http_major);
187
+ }
188
+
189
+ VALUE rb_llhttp_http_minor(VALUE self) {
190
+ llhttp_t *parser;
191
+
192
+ Data_Get_Struct(self, llhttp_t, parser);
193
+
194
+ return UINT2NUM(parser->http_minor);
195
+ }
196
+
187
197
  VALUE rb_llhttp_keep_alive(VALUE self) {
188
198
  llhttp_t *parser;
189
199
 
@@ -201,22 +211,81 @@ static VALUE rb_llhttp_init(VALUE self, VALUE type) {
201
211
 
202
212
  llhttp_settings_t *settings = parser->settings;
203
213
 
204
- settings->on_message_begin = (llhttp_cb)rb_llhttp_on_message_begin;
205
- settings->on_url = (llhttp_data_cb)rb_llhttp_on_url;
206
- settings->on_status = (llhttp_data_cb)rb_llhttp_on_status;
207
- settings->on_header_field = (llhttp_data_cb)rb_llhttp_on_header_field;
208
- settings->on_header_value = (llhttp_data_cb)rb_llhttp_on_header_value;
209
- settings->on_headers_complete = (llhttp_cb)rb_llhttp_on_headers_complete;
210
- settings->on_body = (llhttp_data_cb)rb_llhttp_on_body;
211
- settings->on_message_complete = (llhttp_cb)rb_llhttp_on_message_complete;
212
- settings->on_chunk_header = (llhttp_cb)rb_llhttp_on_chunk_header;
213
- settings->on_chunk_complete = (llhttp_cb)rb_llhttp_on_chunk_complete;
214
+ VALUE delegate = rb_iv_get(self, "@delegate");
215
+
216
+ rb_llhttp_callback_on_message_begin = rb_intern("internal_on_message_begin");
217
+ rb_llhttp_callback_on_headers_complete = rb_intern("internal_on_headers_complete");
218
+ rb_llhttp_callback_on_message_complete = rb_intern("internal_on_message_complete");
219
+ rb_llhttp_callback_on_chunk_header = rb_intern("internal_on_chunk_header");
220
+ rb_llhttp_callback_on_url = rb_intern("on_url");
221
+ rb_llhttp_callback_on_status = rb_intern("on_status");
222
+ rb_llhttp_callback_on_header_field = rb_intern("on_header_field");
223
+ rb_llhttp_callback_on_header_value = rb_intern("on_header_value");
224
+ rb_llhttp_callback_on_body = rb_intern("on_body");
225
+ rb_llhttp_callback_on_chunk_complete = rb_intern("on_chunk_complete");
226
+ rb_llhttp_callback_on_url_complete = rb_intern("on_url_complete");
227
+ rb_llhttp_callback_on_status_complete = rb_intern("on_status_complete");
228
+ rb_llhttp_callback_on_header_field_complete = rb_intern("on_header_field_complete");
229
+ rb_llhttp_callback_on_header_value_complete = rb_intern("on_header_value_complete");
230
+
231
+ if (rb_respond_to(delegate, rb_intern("on_message_begin"))) {
232
+ settings->on_message_begin = (llhttp_cb)rb_llhttp_on_message_begin;
233
+ }
234
+
235
+ if (rb_respond_to(delegate, rb_intern("on_headers_complete"))) {
236
+ settings->on_headers_complete = (llhttp_cb)rb_llhttp_on_headers_complete;
237
+ }
238
+
239
+ if (rb_respond_to(delegate, rb_intern("on_message_complete"))) {
240
+ settings->on_message_complete = (llhttp_cb)rb_llhttp_on_message_complete;
241
+ }
242
+
243
+ if (rb_respond_to(delegate, rb_intern("on_chunk_header"))) {
244
+ settings->on_chunk_header = (llhttp_cb)rb_llhttp_on_chunk_header;
245
+ }
246
+
247
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_url)) {
248
+ settings->on_url = (llhttp_data_cb)rb_llhttp_on_url;
249
+ }
250
+
251
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_status)) {
252
+ settings->on_status = (llhttp_data_cb)rb_llhttp_on_status;
253
+ }
254
+
255
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_header_field)) {
256
+ settings->on_header_field = (llhttp_data_cb)rb_llhttp_on_header_field;
257
+ }
258
+
259
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_header_value)) {
260
+ settings->on_header_value = (llhttp_data_cb)rb_llhttp_on_header_value;
261
+ }
262
+
263
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_body)) {
264
+ settings->on_body = (llhttp_data_cb)rb_llhttp_on_body;
265
+ }
266
+
267
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_chunk_complete)) {
268
+ settings->on_chunk_complete = (llhttp_cb)rb_llhttp_on_chunk_complete;
269
+ }
270
+
271
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_url_complete)) {
272
+ settings->on_url_complete = (llhttp_cb)rb_llhttp_on_url_complete;
273
+ }
274
+
275
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_status_complete)) {
276
+ settings->on_status_complete = (llhttp_cb)rb_llhttp_on_status_complete;
277
+ }
278
+
279
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_header_field_complete)) {
280
+ settings->on_header_field_complete = (llhttp_cb)rb_llhttp_on_header_field_complete;
281
+ }
282
+
283
+ if (rb_respond_to(delegate, rb_llhttp_callback_on_header_value_complete)) {
284
+ settings->on_header_value_complete = (llhttp_cb)rb_llhttp_on_header_value_complete;
285
+ }
214
286
 
215
287
  llhttp_init(parser, FIX2INT(type), settings);
216
288
 
217
- // Store a pointer to the delegate for lookup in callbacks.
218
- //
219
- VALUE delegate = rb_iv_get(self, "@delegate");
220
289
  parser->data = (void*)delegate;
221
290
 
222
291
  return Qtrue;
@@ -234,8 +303,10 @@ void Init_llhttp_ext(void) {
234
303
  rb_define_method(cParser, "finish", rb_llhttp_finish, 0);
235
304
 
236
305
  rb_define_method(cParser, "content_length", rb_llhttp_content_length, 0);
237
- rb_define_method(cParser, "method", rb_llhttp_method, 0);
306
+ rb_define_method(cParser, "method_name", rb_llhttp_method_name, 0);
238
307
  rb_define_method(cParser, "status_code", rb_llhttp_status_code, 0);
308
+ rb_define_method(cParser, "http_major", rb_llhttp_http_major, 0);
309
+ rb_define_method(cParser, "http_minor", rb_llhttp_http_minor, 0);
239
310
 
240
311
  rb_define_method(cParser, "keep_alive?", rb_llhttp_keep_alive, 0);
241
312