http-parser 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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