llhttp 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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