julien51-em-http-request 0.1.9
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/.autotest +1 -0
- data/.gitignore +4 -0
- data/LICENSE +58 -0
- data/README.rdoc +71 -0
- data/Rakefile +84 -0
- data/em-http-request.gemspec +42 -0
- data/ext/buffer/em_buffer.c +630 -0
- data/ext/buffer/extconf.rb +53 -0
- data/ext/http11_client/ext_help.h +14 -0
- data/ext/http11_client/extconf.rb +6 -0
- data/ext/http11_client/http11_client.c +302 -0
- data/ext/http11_client/http11_parser.c +403 -0
- data/ext/http11_client/http11_parser.h +48 -0
- data/ext/http11_client/http11_parser.rl +173 -0
- data/lib/em-http.rb +18 -0
- data/lib/em-http/client.rb +462 -0
- data/lib/em-http/core_ext/hash.rb +53 -0
- data/lib/em-http/decoders.rb +119 -0
- data/lib/em-http/multi.rb +51 -0
- data/lib/em-http/request.rb +77 -0
- data/test/helper.rb +5 -0
- data/test/stallion.rb +137 -0
- data/test/test_hash.rb +18 -0
- data/test/test_multi.rb +29 -0
- data/test/test_request.rb +344 -0
- metadata +88 -0
data/test/test_hash.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
|
5
|
+
describe ".to_params" do
|
6
|
+
it "should transform a basic hash into HTTP POST Params" do
|
7
|
+
{:a => "alpha", :b => "beta"}.to_params.should == "a=alpha&b=beta"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should transform a more complex hash into HTTP POST Params" do
|
11
|
+
{:a => "a", :b => ["c", "d", "e"]}.to_params.should == "a=a&b[0]=c&b[1]=d&b[2]=e"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should transform a very complex hash into HTTP POST Params" do
|
15
|
+
{:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}.to_params.should == "a=a&b[0][d]=d&b[0][c]=c&b[1][f]=f&b[1][e]=e"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/test_multi.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
require 'test/stallion'
|
3
|
+
|
4
|
+
describe EventMachine::MultiRequest do
|
5
|
+
|
6
|
+
it "should submit multiple requests in parallel and return once all of them are complete" do
|
7
|
+
EventMachine.run {
|
8
|
+
|
9
|
+
# create an instance of multi-request handler, and the requests themselves
|
10
|
+
multi = EventMachine::MultiRequest.new
|
11
|
+
|
12
|
+
# add multiple requests to the multi-handler
|
13
|
+
multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
|
14
|
+
multi.add(EventMachine::HttpRequest.new('http://0.0.0.0/').get(:timeout => 1))
|
15
|
+
|
16
|
+
multi.callback {
|
17
|
+
# verify successfull request
|
18
|
+
multi.responses[:succeeded].size.should == 1
|
19
|
+
multi.responses[:succeeded].first.response.should match(/test/)
|
20
|
+
|
21
|
+
# verify invalid requests
|
22
|
+
multi.responses[:failed].size.should == 1
|
23
|
+
multi.responses[:failed].first.response_header.status.should == 0
|
24
|
+
|
25
|
+
EventMachine.stop
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,344 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
require 'test/stallion'
|
3
|
+
|
4
|
+
describe EventMachine::HttpRequest do
|
5
|
+
|
6
|
+
def failed
|
7
|
+
EventMachine.stop
|
8
|
+
fail
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should fail GET on DNS timeout" do
|
12
|
+
EventMachine.run {
|
13
|
+
http = EventMachine::HttpRequest.new('http://127.1.1.1/').get
|
14
|
+
http.callback { failed }
|
15
|
+
http.errback {
|
16
|
+
http.response_header.status.should == 0
|
17
|
+
EventMachine.stop
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should fail GET on invalid host" do
|
23
|
+
EventMachine.run {
|
24
|
+
http = EventMachine::HttpRequest.new('http://google1.com/').get
|
25
|
+
http.callback { failed }
|
26
|
+
http.errback {
|
27
|
+
http.response_header.status.should == 0
|
28
|
+
http.errors.should match(/no connection/)
|
29
|
+
EventMachine.stop
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should fail GET on missing path" do
|
35
|
+
EventMachine.run {
|
36
|
+
lambda {
|
37
|
+
EventMachine::HttpRequest.new('http://www.google.com').get
|
38
|
+
}.should raise_error(ArgumentError)
|
39
|
+
|
40
|
+
EventMachine.stop
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should perform successfull GET" do
|
45
|
+
EventMachine.run {
|
46
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
47
|
+
|
48
|
+
http.errback { failed }
|
49
|
+
http.callback {
|
50
|
+
http.response_header.status.should == 200
|
51
|
+
http.response.should match(/Hello/)
|
52
|
+
EventMachine.stop
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should perform successfull GET with a URI passed as argument" do
|
58
|
+
EventMachine.run {
|
59
|
+
uri = URI.parse('http://127.0.0.1:8080/')
|
60
|
+
http = EventMachine::HttpRequest.new(uri).get
|
61
|
+
|
62
|
+
http.errback { failed }
|
63
|
+
http.callback {
|
64
|
+
http.response_header.status.should == 200
|
65
|
+
http.response.should match(/Hello/)
|
66
|
+
EventMachine.stop
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return 404 on invalid path" do
|
72
|
+
EventMachine.run {
|
73
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/fail').get
|
74
|
+
|
75
|
+
http.errback { failed }
|
76
|
+
http.callback {
|
77
|
+
http.response_header.status.should == 404
|
78
|
+
EventMachine.stop
|
79
|
+
}
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should build query parameters from Hash" do
|
84
|
+
EventMachine.run {
|
85
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => {:q => 'test'}
|
86
|
+
|
87
|
+
http.errback { failed }
|
88
|
+
http.callback {
|
89
|
+
http.response_header.status.should == 200
|
90
|
+
http.response.should match(/test/)
|
91
|
+
EventMachine.stop
|
92
|
+
}
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should pass query parameters string" do
|
97
|
+
EventMachine.run {
|
98
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => "q=test"
|
99
|
+
|
100
|
+
http.errback { failed }
|
101
|
+
http.callback {
|
102
|
+
http.response_header.status.should == 200
|
103
|
+
http.response.should match(/test/)
|
104
|
+
EventMachine.stop
|
105
|
+
}
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should encode an array of query parameters" do
|
110
|
+
EventMachine.run {
|
111
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get :query => {:hash => ['value1', 'value2']}
|
112
|
+
|
113
|
+
http.errback { failed }
|
114
|
+
http.callback {
|
115
|
+
http.response_header.status.should == 200
|
116
|
+
http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
|
117
|
+
EventMachine.stop
|
118
|
+
}
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should perform successfull POST" do
|
123
|
+
EventMachine.run {
|
124
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => "data"
|
125
|
+
|
126
|
+
http.errback { failed }
|
127
|
+
http.callback {
|
128
|
+
http.response_header.status.should == 200
|
129
|
+
http.response.should match(/data/)
|
130
|
+
EventMachine.stop
|
131
|
+
}
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should perform successfull POST with Ruby Hash/Array as params" do
|
136
|
+
EventMachine.run {
|
137
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {"key1" => 1, "key2" => [2,3]}
|
138
|
+
|
139
|
+
http.errback { failed }
|
140
|
+
http.callback {
|
141
|
+
http.response_header.status.should == 200
|
142
|
+
|
143
|
+
http.response.should match(/key1=1&key2\[0\]=2&key2\[1\]=3/)
|
144
|
+
EventMachine.stop
|
145
|
+
}
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should perform successfull POST with Ruby Hash/Array as params and with the correct content length" do
|
150
|
+
EventMachine.run {
|
151
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_length').post :body => {"key1" => "data1"}
|
152
|
+
|
153
|
+
http.errback { failed }
|
154
|
+
http.callback {
|
155
|
+
http.response_header.status.should == 200
|
156
|
+
|
157
|
+
http.response.to_i.should == 10
|
158
|
+
EventMachine.stop
|
159
|
+
}
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should perform successfull GET with custom header" do
|
164
|
+
EventMachine.run {
|
165
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'if-none-match' => 'evar!'}
|
166
|
+
|
167
|
+
http.errback { failed }
|
168
|
+
http.callback {
|
169
|
+
http.response_header.status.should == 304
|
170
|
+
EventMachine.stop
|
171
|
+
}
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should perform a streaming GET" do
|
176
|
+
EventMachine.run {
|
177
|
+
|
178
|
+
# digg.com uses chunked encoding
|
179
|
+
http = EventMachine::HttpRequest.new('http://digg.com/').get
|
180
|
+
|
181
|
+
http.errback { failed }
|
182
|
+
http.callback {
|
183
|
+
http.response_header.status.should == 200
|
184
|
+
EventMachine.stop
|
185
|
+
}
|
186
|
+
}
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should perform basic auth" do
|
190
|
+
EventMachine.run {
|
191
|
+
|
192
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'authorization' => ['user', 'pass']}
|
193
|
+
|
194
|
+
http.errback { failed }
|
195
|
+
http.callback {
|
196
|
+
http.response_header.status.should == 200
|
197
|
+
EventMachine.stop
|
198
|
+
}
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should work with keep-alive servers" do
|
203
|
+
EventMachine.run {
|
204
|
+
|
205
|
+
http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get
|
206
|
+
|
207
|
+
http.errback { failed }
|
208
|
+
http.callback {
|
209
|
+
http.response_header.status.should == 200
|
210
|
+
EventMachine.stop
|
211
|
+
}
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should detect deflate encoding" do
|
216
|
+
EventMachine.run {
|
217
|
+
|
218
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate"}
|
219
|
+
|
220
|
+
http.errback { failed }
|
221
|
+
http.callback {
|
222
|
+
http.response_header.status.should == 200
|
223
|
+
http.response_header["CONTENT_ENCODING"].should == "deflate"
|
224
|
+
http.response.should == "compressed"
|
225
|
+
|
226
|
+
EventMachine.stop
|
227
|
+
}
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should detect gzip encoding" do
|
232
|
+
EventMachine.run {
|
233
|
+
|
234
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/gzip').get :head => {"accept-encoding" => "gzip, compressed"}
|
235
|
+
|
236
|
+
http.errback { failed }
|
237
|
+
http.callback {
|
238
|
+
http.response_header.status.should == 200
|
239
|
+
http.response_header["CONTENT_ENCODING"].should == "gzip"
|
240
|
+
http.response.should == "compressed"
|
241
|
+
|
242
|
+
EventMachine.stop
|
243
|
+
}
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should timeout after 10 seconds" do
|
248
|
+
EventMachine.run {
|
249
|
+
t = Time.now.to_i
|
250
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/timeout').get :timeout => 2
|
251
|
+
|
252
|
+
http.errback {
|
253
|
+
(Time.now.to_i - t).should == 2
|
254
|
+
EventMachine.stop
|
255
|
+
}
|
256
|
+
http.callback { failed }
|
257
|
+
}
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should optionally pass the response body progressively" do
|
261
|
+
EventMachine.run {
|
262
|
+
body = ''
|
263
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
264
|
+
|
265
|
+
http.errback { failed }
|
266
|
+
http.stream { |chunk| body += chunk }
|
267
|
+
|
268
|
+
http.callback {
|
269
|
+
http.response_header.status.should == 200
|
270
|
+
http.response.should == ''
|
271
|
+
body.should match(/Hello/)
|
272
|
+
EventMachine.stop
|
273
|
+
}
|
274
|
+
}
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should optionally pass the deflate-encoded response body progressively" do
|
278
|
+
EventMachine.run {
|
279
|
+
body = ''
|
280
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"}
|
281
|
+
|
282
|
+
http.errback { failed }
|
283
|
+
http.stream { |chunk| body += chunk }
|
284
|
+
|
285
|
+
http.callback {
|
286
|
+
http.response_header.status.should == 200
|
287
|
+
http.response_header["CONTENT_ENCODING"].should == "deflate"
|
288
|
+
http.response.should == ''
|
289
|
+
body.should == "compressed"
|
290
|
+
EventMachine.stop
|
291
|
+
}
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should initiate SSL/TLS on HTTPS connections" do
|
296
|
+
EventMachine.run {
|
297
|
+
http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
|
298
|
+
|
299
|
+
http.errback { failed }
|
300
|
+
http.callback {
|
301
|
+
http.response_header.status.should == 302
|
302
|
+
EventMachine.stop
|
303
|
+
}
|
304
|
+
}
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should accept & return cookie header to user" do
|
308
|
+
EventMachine.run {
|
309
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/set_cookie').get
|
310
|
+
|
311
|
+
http.errback { failed }
|
312
|
+
http.callback {
|
313
|
+
http.response_header.status.should == 200
|
314
|
+
http.response_header.cookie.should == "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
|
315
|
+
EventMachine.stop
|
316
|
+
}
|
317
|
+
}
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should pass cookie header to server from string" do
|
321
|
+
EventMachine.run {
|
322
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => 'id=2;'}
|
323
|
+
|
324
|
+
http.errback { failed }
|
325
|
+
http.callback {
|
326
|
+
http.response.should == "id=2;"
|
327
|
+
EventMachine.stop
|
328
|
+
}
|
329
|
+
}
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should pass cookie header to server from Hash" do
|
333
|
+
EventMachine.run {
|
334
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => {'id' => 2}}
|
335
|
+
|
336
|
+
http.errback { failed }
|
337
|
+
http.callback {
|
338
|
+
http.response.should == "id=2;"
|
339
|
+
EventMachine.stop
|
340
|
+
}
|
341
|
+
}
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: julien51-em-http-request
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ilya Grigorik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: eventmachine
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.12.2
|
24
|
+
version:
|
25
|
+
description: EventMachine based HTTP Request interface
|
26
|
+
email: ilya@igvita.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions:
|
30
|
+
- ext/buffer/extconf.rb
|
31
|
+
- ext/http11_client/extconf.rb
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- .autotest
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- em-http-request.gemspec
|
41
|
+
- ext/buffer/em_buffer.c
|
42
|
+
- ext/buffer/extconf.rb
|
43
|
+
- ext/http11_client/ext_help.h
|
44
|
+
- ext/http11_client/extconf.rb
|
45
|
+
- ext/http11_client/http11_client.c
|
46
|
+
- ext/http11_client/http11_parser.c
|
47
|
+
- ext/http11_client/http11_parser.h
|
48
|
+
- ext/http11_client/http11_parser.rl
|
49
|
+
- lib/em-http.rb
|
50
|
+
- lib/em-http/client.rb
|
51
|
+
- lib/em-http/core_ext/hash.rb
|
52
|
+
- lib/em-http/decoders.rb
|
53
|
+
- lib/em-http/multi.rb
|
54
|
+
- lib/em-http/request.rb
|
55
|
+
- test/test_hash.rb
|
56
|
+
- test/helper.rb
|
57
|
+
- test/stallion.rb
|
58
|
+
- test/test_multi.rb
|
59
|
+
- test/test_request.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/igrigorik/em-http-request
|
62
|
+
licenses:
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project: em-http-request
|
83
|
+
rubygems_version: 1.3.5
|
84
|
+
signing_key:
|
85
|
+
specification_version: 2
|
86
|
+
summary: EventMachine based HTTP Request interface
|
87
|
+
test_files: []
|
88
|
+
|