http-parser 1.0.4 → 1.0.5

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.
@@ -1,311 +1,311 @@
1
-
2
- module HttpParser
3
- HTTP_MAX_HEADER_SIZE = (80 * 1024)
4
-
5
- #
6
- # These share a byte of data as a bitmap
7
- #
8
- TYPES = enum :http_parser_type, [
9
- :request, 0,
10
- :response,
11
- :both
12
- ]
13
- FLAG = {
14
- :CHUNKED => 1 << 2,
15
- :CONNECTION_KEEP_ALIVE => 1 << 3,
16
- :CONNECTION_CLOSE => 1 << 4,
17
- :TRAILING => 1 << 5,
18
- :UPGRADE => 1 << 6,
19
- :SKIPBODY => 1 << 7
20
- }
21
-
22
- #
23
- # Request Methods
24
- #
25
- METHODS = enum :http_method, [
26
- :DELETE, 0,
27
- :GET,
28
- :HEAD,
29
- :POST,
30
- :PUT,
31
- # pathological
32
- :CONNECT,
33
- :OPTIONS,
34
- :TRACE,
35
- # webdav
36
- :COPY,
37
- :LOCK,
38
- :MKCOL,
39
- :MOVE,
40
- :PROPFIND,
41
- :PROPPATCH,
42
- :SEARCH,
43
- :UNLOCK,
44
- # subversion
45
- :REPORT,
46
- :MKACTIVITY,
47
- :CHECKOUT,
48
- :MERGE,
49
- # upnp
50
- :MSEARCH,
51
- :NOTIFY,
52
- :SUBSCRIBE,
53
- :UNSUBSCRIBE,
54
- # RFC-5789
55
- :PATCH,
56
- :PURGE
57
- ]
58
-
59
-
60
- UrlFields = enum :http_parser_url_fields, [
61
- :SCHEMA, 0,
62
- :HOST,
63
- :PORT,
64
- :PATH,
65
- :QUERY,
66
- :FRAGMENT,
67
- :USERINFO,
68
- :MAX
69
- ]
70
-
71
-
72
- #
73
- # Effectively this represents a request instance
74
- #
75
- class Instance < FFI::Struct
76
- layout :type_flags, :uchar,
77
- :state, :uchar,
78
- :header_state, :uchar,
79
- :index, :uchar,
80
-
81
- :nread, :uint32,
82
- :content_length, :int64,
83
-
84
- # READ-ONLY
85
- :http_major, :ushort,
86
- :http_minor, :ushort,
87
- :status_code, :ushort, # responses only
88
- :method, :uchar, # requests only
89
- :error_upgrade, :uchar, # errno = first 7bits, upgrade = last bit
90
-
91
- # PUBLIC
92
- :data, :pointer
93
-
94
-
95
- def initialize(ptr = nil)
96
- if ptr then super(ptr)
97
- else
98
- super()
99
- self.type = :both
100
- end
101
-
102
- yield self if block_given?
103
-
104
- ::HttpParser.http_parser_init(self, self.type) unless ptr
105
- end
106
-
107
- #
108
- # Resets the parser.
109
- #
110
- # @param [:request, :response, :both] new_type
111
- # The new type for the parser.
112
- #
113
- def reset!(new_type = type)
114
- ::HttpParser.http_parser_init(self, new_type)
115
- end
116
-
117
- #
118
- # The type of the parser.
119
- #
120
- # @return [:request, :response, :both]
121
- # The parser type.
122
- #
123
- def type
124
- TYPES[self[:type_flags] & 0x3]
125
- end
126
-
127
- #
128
- # Sets the type of the parser.
129
- #
130
- # @param [:request, :response, :both] new_type
131
- # The new parser type.
132
- #
133
- def type=(new_type)
134
- self[:type_flags] = (flags | TYPES[new_type])
135
- end
136
-
137
- #
138
- # Flags for the parser.
139
- #
140
- # @return [Integer]
141
- # Parser flags.
142
- #
143
- def flags
144
- (self[:type_flags] & 0xfc)
145
- end
146
-
147
- #
148
- # The parsed HTTP major version number.
149
- #
150
- # @return [Integer]
151
- # The HTTP major version number.
152
- #
153
- def http_major
154
- self[:http_major]
155
- end
156
-
157
- #
158
- # The parsed HTTP minor version number.
159
- #
160
- # @return [Integer]
161
- # The HTTP minor version number.
162
- #
163
- def http_minor
164
- self[:http_minor]
165
- end
166
-
167
- #
168
- # The parsed HTTP version.
169
- #
170
- # @return [String]
171
- # The HTTP version.
172
- #
173
- def http_version
174
- "%d.%d" % [self[:http_major], self[:http_minor]]
175
- end
176
-
177
- #
178
- # The parsed HTTP response Status Code.
179
- #
180
- # @return [Integer]
181
- # The HTTP Status Code.
182
- #
183
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1
184
- #
185
- def http_status
186
- self[:status_code]
187
- end
188
-
189
- #
190
- # The parsed HTTP Method.
191
- #
192
- # @return [Symbol]
193
- # The HTTP Method name.
194
- #
195
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1
196
- #
197
- def http_method
198
- METHODS[self[:method]]
199
- end
200
-
201
- #
202
- # Determines whether the `Upgrade` header has been parsed.
203
- #
204
- # @return [Boolean]
205
- # Specifies whether the `Upgrade` header has been seen.
206
- #
207
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.42
208
- #
209
- def upgrade?
210
- (self[:error_upgrade] & 0b10000000) > 0
211
- end
212
-
213
- #
214
- # Determines whether an error occurred during processing.
215
- #
216
- # @return [Boolean]
217
- # Did a parsing error occur with the request?
218
- #
219
- def error?
220
- error = (self[:error_upgrade] & 0b1111111)
221
- return error != 0
222
- end
223
-
224
- #
225
- # Returns the error that occurred during processing.
226
- #
227
- # @return [StandarError]
228
- # Returns the error that occurred.
229
- #
230
- def error
231
- error = (self[:error_upgrade] & 0b1111111)
232
- return nil if error == 0
233
-
234
- err = ::HttpParser.err_name(error)[4..-1] # HPE_ is at the start of all these errors
235
- klass = ERRORS[err.to_sym]
236
- err = "#{::HttpParser.err_desc(error)} (#{err})"
237
- return klass.nil? ? Error::UNKNOWN.new(err) : klass.new(err)
238
- end
239
-
240
- #
241
- # Additional data attached to the parser.
242
- #
243
- # @return [FFI::Pointer]
244
- # Pointer to the additional data.
245
- #
246
- def data
247
- self[:data]
248
- end
249
-
250
- #
251
- # Determines whether the `Connection: keep-alive` header has been
252
- # parsed.
253
- #
254
- # @return [Boolean]
255
- # Specifies whether the Connection should be kept alive.
256
- #
257
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
258
- #
259
- def keep_alive?
260
- ::HttpParser.http_should_keep_alive(self) > 0
261
- end
262
-
263
- #
264
- # Halts the parser if called in a callback
265
- #
266
- def stop!
267
- throw :return, 1
268
- end
269
-
270
- #
271
- # Indicates an error has occurred when called in a callback
272
- #
273
- def error!
274
- throw :return, -1
275
- end
276
- end
277
-
278
- class FieldData < FFI::Struct
279
- layout :off, :uint16,
280
- :len, :uint16
281
- end
282
-
283
- class HttpParserUrl < FFI::Struct
284
- layout :field_set, :uint16,
285
- :port, :uint16,
286
- :field_data, [FieldData, UrlFields[:MAX]]
287
- end
288
-
289
-
290
- callback :http_data_cb, [Instance.ptr, :pointer, :size_t], :int
291
- callback :http_cb, [Instance.ptr], :int
292
-
293
-
294
- class Settings < FFI::Struct
295
- layout :on_message_begin, :http_cb,
296
- :on_url, :http_data_cb,
297
- :on_status, :http_data_cb,
298
- :on_header_field, :http_data_cb,
299
- :on_header_value, :http_data_cb,
300
- :on_headers_complete, :http_cb,
301
- :on_body, :http_data_cb,
302
- :on_message_complete, :http_cb
303
- end
304
-
305
-
306
- attach_function :http_parser_init, [Instance.by_ref, :http_parser_type], :void, :blocking => true
307
- attach_function :http_parser_execute, [Instance.by_ref, Settings.by_ref, :pointer, :size_t], :size_t, :blocking => true
308
-
309
- attach_function :http_should_keep_alive, [Instance.by_ref], :int, :blocking => true
310
- attach_function :http_method_str, [:http_method], :string, :blocking => true
311
- end
1
+
2
+ module HttpParser
3
+ HTTP_MAX_HEADER_SIZE = (80 * 1024)
4
+
5
+ #
6
+ # These share a byte of data as a bitmap
7
+ #
8
+ TYPES = enum :http_parser_type, [
9
+ :request, 0,
10
+ :response,
11
+ :both
12
+ ]
13
+ FLAG = {
14
+ :CHUNKED => 1 << 2,
15
+ :CONNECTION_KEEP_ALIVE => 1 << 3,
16
+ :CONNECTION_CLOSE => 1 << 4,
17
+ :TRAILING => 1 << 5,
18
+ :UPGRADE => 1 << 6,
19
+ :SKIPBODY => 1 << 7
20
+ }
21
+
22
+ #
23
+ # Request Methods
24
+ #
25
+ METHODS = enum :http_method, [
26
+ :DELETE, 0,
27
+ :GET,
28
+ :HEAD,
29
+ :POST,
30
+ :PUT,
31
+ # pathological
32
+ :CONNECT,
33
+ :OPTIONS,
34
+ :TRACE,
35
+ # webdav
36
+ :COPY,
37
+ :LOCK,
38
+ :MKCOL,
39
+ :MOVE,
40
+ :PROPFIND,
41
+ :PROPPATCH,
42
+ :SEARCH,
43
+ :UNLOCK,
44
+ # subversion
45
+ :REPORT,
46
+ :MKACTIVITY,
47
+ :CHECKOUT,
48
+ :MERGE,
49
+ # upnp
50
+ :MSEARCH,
51
+ :NOTIFY,
52
+ :SUBSCRIBE,
53
+ :UNSUBSCRIBE,
54
+ # RFC-5789
55
+ :PATCH,
56
+ :PURGE
57
+ ]
58
+
59
+
60
+ UrlFields = enum :http_parser_url_fields, [
61
+ :SCHEMA, 0,
62
+ :HOST,
63
+ :PORT,
64
+ :PATH,
65
+ :QUERY,
66
+ :FRAGMENT,
67
+ :USERINFO,
68
+ :MAX
69
+ ]
70
+
71
+
72
+ #
73
+ # Effectively this represents a request instance
74
+ #
75
+ class Instance < FFI::Struct
76
+ layout :type_flags, :uchar,
77
+ :state, :uchar,
78
+ :header_state, :uchar,
79
+ :index, :uchar,
80
+
81
+ :nread, :uint32,
82
+ :content_length, :int64,
83
+
84
+ # READ-ONLY
85
+ :http_major, :ushort,
86
+ :http_minor, :ushort,
87
+ :status_code, :ushort, # responses only
88
+ :method, :uchar, # requests only
89
+ :error_upgrade, :uchar, # errno = first 7bits, upgrade = last bit
90
+
91
+ # PUBLIC
92
+ :data, :pointer
93
+
94
+
95
+ def initialize(ptr = nil)
96
+ if ptr then super(ptr)
97
+ else
98
+ super()
99
+ self.type = :both
100
+ end
101
+
102
+ yield self if block_given?
103
+
104
+ ::HttpParser.http_parser_init(self, self.type) unless ptr
105
+ end
106
+
107
+ #
108
+ # Resets the parser.
109
+ #
110
+ # @param [:request, :response, :both] new_type
111
+ # The new type for the parser.
112
+ #
113
+ def reset!(new_type = type)
114
+ ::HttpParser.http_parser_init(self, new_type)
115
+ end
116
+
117
+ #
118
+ # The type of the parser.
119
+ #
120
+ # @return [:request, :response, :both]
121
+ # The parser type.
122
+ #
123
+ def type
124
+ TYPES[self[:type_flags] & 0x3]
125
+ end
126
+
127
+ #
128
+ # Sets the type of the parser.
129
+ #
130
+ # @param [:request, :response, :both] new_type
131
+ # The new parser type.
132
+ #
133
+ def type=(new_type)
134
+ self[:type_flags] = (flags | TYPES[new_type])
135
+ end
136
+
137
+ #
138
+ # Flags for the parser.
139
+ #
140
+ # @return [Integer]
141
+ # Parser flags.
142
+ #
143
+ def flags
144
+ (self[:type_flags] & 0xfc)
145
+ end
146
+
147
+ #
148
+ # The parsed HTTP major version number.
149
+ #
150
+ # @return [Integer]
151
+ # The HTTP major version number.
152
+ #
153
+ def http_major
154
+ self[:http_major]
155
+ end
156
+
157
+ #
158
+ # The parsed HTTP minor version number.
159
+ #
160
+ # @return [Integer]
161
+ # The HTTP minor version number.
162
+ #
163
+ def http_minor
164
+ self[:http_minor]
165
+ end
166
+
167
+ #
168
+ # The parsed HTTP version.
169
+ #
170
+ # @return [String]
171
+ # The HTTP version.
172
+ #
173
+ def http_version
174
+ "%d.%d" % [self[:http_major], self[:http_minor]]
175
+ end
176
+
177
+ #
178
+ # The parsed HTTP response Status Code.
179
+ #
180
+ # @return [Integer]
181
+ # The HTTP Status Code.
182
+ #
183
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1
184
+ #
185
+ def http_status
186
+ self[:status_code]
187
+ end
188
+
189
+ #
190
+ # The parsed HTTP Method.
191
+ #
192
+ # @return [Symbol]
193
+ # The HTTP Method name.
194
+ #
195
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1
196
+ #
197
+ def http_method
198
+ METHODS[self[:method]]
199
+ end
200
+
201
+ #
202
+ # Determines whether the `Upgrade` header has been parsed.
203
+ #
204
+ # @return [Boolean]
205
+ # Specifies whether the `Upgrade` header has been seen.
206
+ #
207
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.42
208
+ #
209
+ def upgrade?
210
+ (self[:error_upgrade] & 0b10000000) > 0
211
+ end
212
+
213
+ #
214
+ # Determines whether an error occurred during processing.
215
+ #
216
+ # @return [Boolean]
217
+ # Did a parsing error occur with the request?
218
+ #
219
+ def error?
220
+ error = (self[:error_upgrade] & 0b1111111)
221
+ return error != 0
222
+ end
223
+
224
+ #
225
+ # Returns the error that occurred during processing.
226
+ #
227
+ # @return [StandarError]
228
+ # Returns the error that occurred.
229
+ #
230
+ def error
231
+ error = (self[:error_upgrade] & 0b1111111)
232
+ return nil if error == 0
233
+
234
+ err = ::HttpParser.err_name(error)[4..-1] # HPE_ is at the start of all these errors
235
+ klass = ERRORS[err.to_sym]
236
+ err = "#{::HttpParser.err_desc(error)} (#{err})"
237
+ return klass.nil? ? Error::UNKNOWN.new(err) : klass.new(err)
238
+ end
239
+
240
+ #
241
+ # Additional data attached to the parser.
242
+ #
243
+ # @return [FFI::Pointer]
244
+ # Pointer to the additional data.
245
+ #
246
+ def data
247
+ self[:data]
248
+ end
249
+
250
+ #
251
+ # Determines whether the `Connection: keep-alive` header has been
252
+ # parsed.
253
+ #
254
+ # @return [Boolean]
255
+ # Specifies whether the Connection should be kept alive.
256
+ #
257
+ # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
258
+ #
259
+ def keep_alive?
260
+ ::HttpParser.http_should_keep_alive(self) > 0
261
+ end
262
+
263
+ #
264
+ # Halts the parser if called in a callback
265
+ #
266
+ def stop!
267
+ throw :return, 1
268
+ end
269
+
270
+ #
271
+ # Indicates an error has occurred when called in a callback
272
+ #
273
+ def error!
274
+ throw :return, -1
275
+ end
276
+ end
277
+
278
+ class FieldData < FFI::Struct
279
+ layout :off, :uint16,
280
+ :len, :uint16
281
+ end
282
+
283
+ class HttpParserUrl < FFI::Struct
284
+ layout :field_set, :uint16,
285
+ :port, :uint16,
286
+ :field_data, [FieldData, UrlFields[:MAX]]
287
+ end
288
+
289
+
290
+ callback :http_data_cb, [Instance.ptr, :pointer, :size_t], :int
291
+ callback :http_cb, [Instance.ptr], :int
292
+
293
+
294
+ class Settings < FFI::Struct
295
+ layout :on_message_begin, :http_cb,
296
+ :on_url, :http_data_cb,
297
+ :on_status, :http_data_cb,
298
+ :on_header_field, :http_data_cb,
299
+ :on_header_value, :http_data_cb,
300
+ :on_headers_complete, :http_cb,
301
+ :on_body, :http_data_cb,
302
+ :on_message_complete, :http_cb
303
+ end
304
+
305
+
306
+ attach_function :http_parser_init, [Instance.by_ref, :http_parser_type], :void, :blocking => true
307
+ attach_function :http_parser_execute, [Instance.by_ref, Settings.by_ref, :pointer, :size_t], :size_t, :blocking => true
308
+
309
+ attach_function :http_should_keep_alive, [Instance.by_ref], :int, :blocking => true
310
+ attach_function :http_method_str, [:http_method], :string, :blocking => true
311
+ end