em-http-request 0.2.9 → 0.3.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/.gitignore +2 -1
- data/.rspec +0 -0
- data/Changelog.md +54 -0
- data/Gemfile +3 -0
- data/README.md +175 -0
- data/Rakefile +11 -37
- data/em-http-request.gemspec +25 -90
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/examples/socks5.rb +26 -0
- data/examples/websocket-handler.rb +28 -28
- data/examples/websocket-server.rb +8 -8
- data/lib/em-http/client.rb +242 -207
- data/lib/em-http/http_encoding.rb +135 -0
- data/lib/em-http/http_header.rb +71 -0
- data/lib/em-http/http_options.rb +7 -4
- data/lib/em-http/mock.rb +90 -50
- data/lib/em-http/multi.rb +55 -51
- data/lib/em-http/request.rb +2 -4
- data/lib/em-http/version.rb +5 -0
- data/lib/em-http.rb +19 -19
- data/spec/encoding_spec.rb +40 -0
- data/spec/fixtures/google.ca +20 -21
- data/spec/helper.rb +5 -4
- data/spec/mock_spec.rb +85 -36
- data/spec/multi_spec.rb +68 -51
- data/spec/request_spec.rb +422 -108
- data/spec/stallion.rb +65 -3
- metadata +111 -28
- data/LICENSE +0 -58
- data/README.rdoc +0 -138
- data/VERSION +0 -1
- data/lib/em-http/core_ext/hash.rb +0 -53
- data/spec/hash_spec.rb +0 -24
data/spec/stallion.rb
CHANGED
|
@@ -78,12 +78,14 @@ Stallion.saddle :spec do |stable|
|
|
|
78
78
|
stable.response.write 'test'
|
|
79
79
|
|
|
80
80
|
elsif stable.request.path_info == '/echo_query'
|
|
81
|
+
stable.response["ETag"] = "abcdefg"
|
|
82
|
+
stable.response["Last-Modified"] = "Fri, 13 Aug 2010 17:31:21 GMT"
|
|
81
83
|
stable.response.write stable.request.query_string
|
|
82
84
|
|
|
83
85
|
elsif stable.request.path_info == '/echo_content_length'
|
|
84
86
|
stable.response.write stable.request.content_length
|
|
85
87
|
|
|
86
|
-
elsif stable.request.head?
|
|
88
|
+
elsif stable.request.head? && stable.request.path_info == '/'
|
|
87
89
|
stable.response.status = 200
|
|
88
90
|
|
|
89
91
|
elsif stable.request.delete?
|
|
@@ -94,6 +96,7 @@ Stallion.saddle :spec do |stable|
|
|
|
94
96
|
|
|
95
97
|
elsif stable.request.post?
|
|
96
98
|
if stable.request.path_info == '/echo_content_type'
|
|
99
|
+
stable.response["Content-Type"] = stable.request.env["CONTENT_TYPE"] || 'text/html'
|
|
97
100
|
stable.response.write stable.request.env["CONTENT_TYPE"]
|
|
98
101
|
else
|
|
99
102
|
stable.response.write stable.request.body.read
|
|
@@ -113,6 +116,23 @@ Stallion.saddle :spec do |stable|
|
|
|
113
116
|
elsif stable.request.path_info == '/redirect'
|
|
114
117
|
stable.response.status = 301
|
|
115
118
|
stable.response["Location"] = "/gzip"
|
|
119
|
+
stable.response.write 'redirect'
|
|
120
|
+
|
|
121
|
+
elsif stable.request.path_info == '/redirect/bad'
|
|
122
|
+
stable.response.status = 301
|
|
123
|
+
stable.response["Location"] = "http://127.0.0.1:8080"
|
|
124
|
+
|
|
125
|
+
elsif stable.request.path_info == '/redirect/head'
|
|
126
|
+
stable.response.status = 301
|
|
127
|
+
stable.response["Location"] = "/"
|
|
128
|
+
|
|
129
|
+
elsif stable.request.path_info == '/redirect/nohost'
|
|
130
|
+
stable.response.status = 301
|
|
131
|
+
stable.response["Location"] = "http:/"
|
|
132
|
+
|
|
133
|
+
elsif stable.request.path_info == '/redirect/badhost'
|
|
134
|
+
stable.response.status = 301
|
|
135
|
+
stable.response["Location"] = "http://$$$@$!%&^"
|
|
116
136
|
|
|
117
137
|
elsif stable.request.path_info == '/gzip'
|
|
118
138
|
io = StringIO.new
|
|
@@ -164,7 +184,7 @@ Thread.new do
|
|
|
164
184
|
end
|
|
165
185
|
|
|
166
186
|
#
|
|
167
|
-
# HTTP Proxy server
|
|
187
|
+
# Tunneling HTTP Proxy server
|
|
168
188
|
#
|
|
169
189
|
Thread.new do
|
|
170
190
|
server = TCPServer.new('127.0.0.1', 8082)
|
|
@@ -220,4 +240,46 @@ Thread.new do
|
|
|
220
240
|
end
|
|
221
241
|
end
|
|
222
242
|
|
|
223
|
-
|
|
243
|
+
#
|
|
244
|
+
# CONNECT-less HTTP Proxy server
|
|
245
|
+
#
|
|
246
|
+
Thread.new do
|
|
247
|
+
server = TCPServer.new('127.0.0.1', 8083)
|
|
248
|
+
loop do
|
|
249
|
+
session = server.accept
|
|
250
|
+
request = ""
|
|
251
|
+
while (data = session.gets) != "\r\n"
|
|
252
|
+
request << data
|
|
253
|
+
end
|
|
254
|
+
parts = request.split("\r\n")
|
|
255
|
+
method, destination, http_version = parts.first.split(' ')
|
|
256
|
+
if destination =~ /^http:/
|
|
257
|
+
uri = Addressable::URI.parse(destination)
|
|
258
|
+
absolute_path = uri.path + (uri.query ? "?#{uri.query}" : "")
|
|
259
|
+
client = TCPSocket.open(uri.host, uri.port || 80)
|
|
260
|
+
client.write "#{method} #{absolute_path} #{http_version}\r\n"
|
|
261
|
+
parts[1..-1].each do |part|
|
|
262
|
+
client.write "#{part}\r\n"
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
client.write "\r\n"
|
|
266
|
+
client.flush
|
|
267
|
+
client.close_write
|
|
268
|
+
|
|
269
|
+
# Take the initial line from the upstream response
|
|
270
|
+
session.write client.gets
|
|
271
|
+
|
|
272
|
+
# What (absolute) uri was requested? Send it back in a header
|
|
273
|
+
session.write "X-The-Requested-URI: #{destination}\r\n"
|
|
274
|
+
|
|
275
|
+
while data = client.gets
|
|
276
|
+
session.write data
|
|
277
|
+
end
|
|
278
|
+
session.flush
|
|
279
|
+
client.close
|
|
280
|
+
end
|
|
281
|
+
session.close
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
sleep(1)
|
metadata
CHANGED
|
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
|
4
4
|
prerelease: false
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
version: 0.
|
|
7
|
+
- 3
|
|
8
|
+
- 0
|
|
9
|
+
version: 0.3.0
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Ilya Grigorik
|
|
@@ -14,13 +14,14 @@ autorequire:
|
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
16
|
|
|
17
|
-
date:
|
|
17
|
+
date: 2011-01-15 00:00:00 -05:00
|
|
18
18
|
default_executable:
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
21
21
|
name: eventmachine
|
|
22
22
|
prerelease: false
|
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
none: false
|
|
24
25
|
requirements:
|
|
25
26
|
- - ">="
|
|
26
27
|
- !ruby/object:Gem::Version
|
|
@@ -35,6 +36,7 @@ dependencies:
|
|
|
35
36
|
name: addressable
|
|
36
37
|
prerelease: false
|
|
37
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
38
40
|
requirements:
|
|
39
41
|
- - ">="
|
|
40
42
|
- !ruby/object:Gem::Version
|
|
@@ -45,26 +47,109 @@ dependencies:
|
|
|
45
47
|
version: 2.0.0
|
|
46
48
|
type: :runtime
|
|
47
49
|
version_requirements: *id002
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
- !ruby/object:Gem::Dependency
|
|
51
|
+
name: escape_utils
|
|
52
|
+
prerelease: false
|
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
54
|
+
none: false
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
segments:
|
|
59
|
+
- 0
|
|
60
|
+
version: "0"
|
|
61
|
+
type: :runtime
|
|
62
|
+
version_requirements: *id003
|
|
63
|
+
- !ruby/object:Gem::Dependency
|
|
64
|
+
name: rspec
|
|
65
|
+
prerelease: false
|
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
67
|
+
none: false
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
segments:
|
|
72
|
+
- 0
|
|
73
|
+
version: "0"
|
|
74
|
+
type: :development
|
|
75
|
+
version_requirements: *id004
|
|
76
|
+
- !ruby/object:Gem::Dependency
|
|
77
|
+
name: rake
|
|
78
|
+
prerelease: false
|
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
|
80
|
+
none: false
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
segments:
|
|
85
|
+
- 0
|
|
86
|
+
version: "0"
|
|
87
|
+
type: :development
|
|
88
|
+
version_requirements: *id005
|
|
89
|
+
- !ruby/object:Gem::Dependency
|
|
90
|
+
name: em-websocket
|
|
91
|
+
prerelease: false
|
|
92
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
|
93
|
+
none: false
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
segments:
|
|
98
|
+
- 0
|
|
99
|
+
version: "0"
|
|
100
|
+
type: :development
|
|
101
|
+
version_requirements: *id006
|
|
102
|
+
- !ruby/object:Gem::Dependency
|
|
103
|
+
name: rack
|
|
104
|
+
prerelease: false
|
|
105
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
|
106
|
+
none: false
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
segments:
|
|
111
|
+
- 0
|
|
112
|
+
version: "0"
|
|
113
|
+
type: :development
|
|
114
|
+
version_requirements: *id007
|
|
115
|
+
- !ruby/object:Gem::Dependency
|
|
116
|
+
name: mongrel
|
|
117
|
+
prerelease: false
|
|
118
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
|
119
|
+
none: false
|
|
120
|
+
requirements:
|
|
121
|
+
- - ~>
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
segments:
|
|
124
|
+
- 1
|
|
125
|
+
- 2
|
|
126
|
+
- 0
|
|
127
|
+
- pre2
|
|
128
|
+
version: 1.2.0.pre2
|
|
129
|
+
type: :development
|
|
130
|
+
version_requirements: *id008
|
|
131
|
+
description: EventMachine based, async HTTP Request client
|
|
132
|
+
email:
|
|
133
|
+
- ilya@igvita.com
|
|
50
134
|
executables: []
|
|
51
135
|
|
|
52
136
|
extensions:
|
|
53
137
|
- ext/buffer/extconf.rb
|
|
54
138
|
- ext/http11_client/extconf.rb
|
|
55
|
-
extra_rdoc_files:
|
|
56
|
-
|
|
57
|
-
- README.rdoc
|
|
139
|
+
extra_rdoc_files: []
|
|
140
|
+
|
|
58
141
|
files:
|
|
59
142
|
- .gitignore
|
|
60
|
-
-
|
|
61
|
-
-
|
|
143
|
+
- .rspec
|
|
144
|
+
- Changelog.md
|
|
145
|
+
- Gemfile
|
|
146
|
+
- README.md
|
|
62
147
|
- Rakefile
|
|
63
|
-
- VERSION
|
|
64
148
|
- em-http-request.gemspec
|
|
65
149
|
- examples/fetch.rb
|
|
66
150
|
- examples/fibered-http.rb
|
|
67
151
|
- examples/oauth-tweet.rb
|
|
152
|
+
- examples/socks5.rb
|
|
68
153
|
- examples/websocket-handler.rb
|
|
69
154
|
- examples/websocket-server.rb
|
|
70
155
|
- ext/buffer/em_buffer.c
|
|
@@ -79,14 +164,16 @@ files:
|
|
|
79
164
|
- lib/em-http.rb
|
|
80
165
|
- lib/em-http/client.rb
|
|
81
166
|
- lib/em-http/core_ext/bytesize.rb
|
|
82
|
-
- lib/em-http/core_ext/hash.rb
|
|
83
167
|
- lib/em-http/decoders.rb
|
|
168
|
+
- lib/em-http/http_encoding.rb
|
|
169
|
+
- lib/em-http/http_header.rb
|
|
84
170
|
- lib/em-http/http_options.rb
|
|
85
171
|
- lib/em-http/mock.rb
|
|
86
172
|
- lib/em-http/multi.rb
|
|
87
173
|
- lib/em-http/request.rb
|
|
174
|
+
- lib/em-http/version.rb
|
|
175
|
+
- spec/encoding_spec.rb
|
|
88
176
|
- spec/fixtures/google.ca
|
|
89
|
-
- spec/hash_spec.rb
|
|
90
177
|
- spec/helper.rb
|
|
91
178
|
- spec/mock_spec.rb
|
|
92
179
|
- spec/multi_spec.rb
|
|
@@ -98,20 +185,20 @@ homepage: http://github.com/igrigorik/em-http-request
|
|
|
98
185
|
licenses: []
|
|
99
186
|
|
|
100
187
|
post_install_message:
|
|
101
|
-
rdoc_options:
|
|
102
|
-
|
|
188
|
+
rdoc_options: []
|
|
189
|
+
|
|
103
190
|
require_paths:
|
|
104
191
|
- lib
|
|
105
192
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
193
|
+
none: false
|
|
106
194
|
requirements:
|
|
107
195
|
- - ">="
|
|
108
196
|
- !ruby/object:Gem::Version
|
|
109
197
|
segments:
|
|
110
|
-
-
|
|
111
|
-
|
|
112
|
-
- 6
|
|
113
|
-
version: 1.8.6
|
|
198
|
+
- 0
|
|
199
|
+
version: "0"
|
|
114
200
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
|
+
none: false
|
|
115
202
|
requirements:
|
|
116
203
|
- - ">="
|
|
117
204
|
- !ruby/object:Gem::Version
|
|
@@ -121,20 +208,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
121
208
|
requirements: []
|
|
122
209
|
|
|
123
210
|
rubyforge_project: em-http-request
|
|
124
|
-
rubygems_version: 1.3.
|
|
211
|
+
rubygems_version: 1.3.7
|
|
125
212
|
signing_key:
|
|
126
213
|
specification_version: 3
|
|
127
|
-
summary: EventMachine based, async HTTP Request
|
|
214
|
+
summary: EventMachine based, async HTTP Request client
|
|
128
215
|
test_files:
|
|
129
|
-
- spec/
|
|
216
|
+
- spec/encoding_spec.rb
|
|
217
|
+
- spec/fixtures/google.ca
|
|
130
218
|
- spec/helper.rb
|
|
131
219
|
- spec/mock_spec.rb
|
|
132
220
|
- spec/multi_spec.rb
|
|
133
221
|
- spec/request_spec.rb
|
|
134
222
|
- spec/stallion.rb
|
|
135
223
|
- spec/stub_server.rb
|
|
136
|
-
- examples/fetch.rb
|
|
137
|
-
- examples/fibered-http.rb
|
|
138
|
-
- examples/oauth-tweet.rb
|
|
139
|
-
- examples/websocket-handler.rb
|
|
140
|
-
- examples/websocket-server.rb
|
data/LICENSE
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
|
2
|
-
You can redistribute it and/or modify it under either the terms of the GPL
|
|
3
|
-
(see COPYING.txt file), or the conditions below:
|
|
4
|
-
|
|
5
|
-
1. You may make and give away verbatim copies of the source form of the
|
|
6
|
-
software without restriction, provided that you duplicate all of the
|
|
7
|
-
original copyright notices and associated disclaimers.
|
|
8
|
-
|
|
9
|
-
2. You may modify your copy of the software in any way, provided that
|
|
10
|
-
you do at least ONE of the following:
|
|
11
|
-
|
|
12
|
-
a) place your modifications in the Public Domain or otherwise
|
|
13
|
-
make them Freely Available, such as by posting said
|
|
14
|
-
modifications to Usenet or an equivalent medium, or by allowing
|
|
15
|
-
the author to include your modifications in the software.
|
|
16
|
-
|
|
17
|
-
b) use the modified software only within your corporation or
|
|
18
|
-
organization.
|
|
19
|
-
|
|
20
|
-
c) rename any non-standard executables so the names do not conflict
|
|
21
|
-
with standard executables, which must also be provided.
|
|
22
|
-
|
|
23
|
-
d) make other distribution arrangements with the author.
|
|
24
|
-
|
|
25
|
-
3. You may distribute the software in object code or executable
|
|
26
|
-
form, provided that you do at least ONE of the following:
|
|
27
|
-
|
|
28
|
-
a) distribute the executables and library files of the software,
|
|
29
|
-
together with instructions (in the manual page or equivalent)
|
|
30
|
-
on where to get the original distribution.
|
|
31
|
-
|
|
32
|
-
b) accompany the distribution with the machine-readable source of
|
|
33
|
-
the software.
|
|
34
|
-
|
|
35
|
-
c) give non-standard executables non-standard names, with
|
|
36
|
-
instructions on where to get the original software distribution.
|
|
37
|
-
|
|
38
|
-
d) make other distribution arrangements with the author.
|
|
39
|
-
|
|
40
|
-
4. You may modify and include the part of the software into any other
|
|
41
|
-
software (possibly commercial). But some files in the distribution
|
|
42
|
-
are not written by the author, so that they are not under this terms.
|
|
43
|
-
|
|
44
|
-
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
|
45
|
-
files under the ./missing directory. See each file for the copying
|
|
46
|
-
condition.
|
|
47
|
-
|
|
48
|
-
5. The scripts and library files supplied as input to or produced as
|
|
49
|
-
output from the software do not automatically fall under the
|
|
50
|
-
copyright of the software, but belong to whomever generated them,
|
|
51
|
-
and may be sold commercially, and may be aggregated with this
|
|
52
|
-
software.
|
|
53
|
-
|
|
54
|
-
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
|
55
|
-
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
56
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
57
|
-
PURPOSE.
|
|
58
|
-
|
data/README.rdoc
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
= EM-HTTP-Client
|
|
2
|
-
|
|
3
|
-
EventMachine based HTTP Request interface. Supports streaming response processing, uses Ragel HTTP parser.
|
|
4
|
-
- Simple interface for single & parallel requests via deferred callbacks
|
|
5
|
-
- Automatic gzip & deflate decoding
|
|
6
|
-
- Basic-Auth & OAuth support
|
|
7
|
-
- Custom timeouts
|
|
8
|
-
- Proxy support (with SSL Tunneling)
|
|
9
|
-
- Auto-follow 3xx redirects with max depth
|
|
10
|
-
- Bi-directional communication with web-socket services
|
|
11
|
-
|
|
12
|
-
Screencast / Demo of using EM-HTTP-Request:
|
|
13
|
-
- http://everburning.com/news/eventmachine-screencast-em-http-request/
|
|
14
|
-
|
|
15
|
-
== Getting started
|
|
16
|
-
|
|
17
|
-
# install & configure gemcutter repos
|
|
18
|
-
gem update --system
|
|
19
|
-
gem install gemcutter
|
|
20
|
-
gem tumble
|
|
21
|
-
|
|
22
|
-
gem install em-http-request
|
|
23
|
-
|
|
24
|
-
irb:0> require 'em-http'
|
|
25
|
-
|
|
26
|
-
== Simple client example
|
|
27
|
-
|
|
28
|
-
EventMachine.run {
|
|
29
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1/').get :query => {'keyname' => 'value'}, :timeout => 10
|
|
30
|
-
|
|
31
|
-
http.callback {
|
|
32
|
-
p http.response_header.status
|
|
33
|
-
p http.response_header
|
|
34
|
-
p http.response
|
|
35
|
-
|
|
36
|
-
EventMachine.stop
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
== Multi request example
|
|
41
|
-
Fire and wait for multiple requess to complete via the MultiRequest interface.
|
|
42
|
-
|
|
43
|
-
EventMachine.run {
|
|
44
|
-
multi = EventMachine::MultiRequest.new
|
|
45
|
-
|
|
46
|
-
# add multiple requests to the multi-handler
|
|
47
|
-
multi.add(EventMachine::HttpRequest.new('http://www.google.com/').get)
|
|
48
|
-
multi.add(EventMachine::HttpRequest.new('http://www.yahoo.com/').get)
|
|
49
|
-
|
|
50
|
-
multi.callback {
|
|
51
|
-
p multi.responses[:succeeded]
|
|
52
|
-
p multi.responses[:failed]
|
|
53
|
-
|
|
54
|
-
EventMachine.stop
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
== Basic-Auth example
|
|
59
|
-
Full basic author support. For OAuth, check examples/oauth-tweet.rb file.
|
|
60
|
-
|
|
61
|
-
EventMachine.run {
|
|
62
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :head => {'authorization' => ['user', 'pass']}
|
|
63
|
-
|
|
64
|
-
http.errback { failed }
|
|
65
|
-
http.callback {
|
|
66
|
-
p http.response_header
|
|
67
|
-
EventMachine.stop
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
== POST example
|
|
73
|
-
EventMachine.run {
|
|
74
|
-
http1 = EventMachine::HttpRequest.new('http://www.website.com/').post :body => {"key1" => 1, "key2" => [2,3]}
|
|
75
|
-
http2 = EventMachine::HttpRequest.new('http://www.website.com/').post :body => "some data"
|
|
76
|
-
|
|
77
|
-
# ...
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
== Streaming body processing
|
|
81
|
-
Allows you to consume an HTTP stream of content in real-time. Each time a new piece of conent is pushed
|
|
82
|
-
to the client, it is passed to the stream callback for you to operate on.
|
|
83
|
-
|
|
84
|
-
EventMachine.run {
|
|
85
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get
|
|
86
|
-
http.stream { |chunk| print chunk }
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
== Streaming file from disk
|
|
90
|
-
Allows you to efficiently stream a (large) file from disk via EventMachine's FileStream interface.
|
|
91
|
-
|
|
92
|
-
EventMachine.run {
|
|
93
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').post :file => 'largefile.txt'
|
|
94
|
-
http.callback { |chunk| puts "Upload finished!" }
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
== Proxy example
|
|
98
|
-
Full transparent proxy support with support for SSL tunneling.
|
|
99
|
-
|
|
100
|
-
EventMachine.run {
|
|
101
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :proxy => {
|
|
102
|
-
:host => 'www.myproxy.com',
|
|
103
|
-
:port => 8080,
|
|
104
|
-
:authorization => ['username', 'password'] # authorization is optional
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
== Auto-follow 3xx redirects
|
|
108
|
-
Specify the max depth of redirects to follow, default is 0.
|
|
109
|
-
|
|
110
|
-
EventMachine.run {
|
|
111
|
-
http = EventMachine::HttpRequest.new('http://www.google.com/').get :redirect => 1
|
|
112
|
-
http.callback { p http.last_effective_url }
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
== WebSocket example
|
|
117
|
-
Bi-directional communication with WebSockets: simply pass in a ws:// resource and the client will
|
|
118
|
-
negotiate the connection upgrade for you. On successfull handshake the callback is invoked, and
|
|
119
|
-
any incoming messages will be passed to the stream callback. The client can also send data to the
|
|
120
|
-
server at will by calling the "send" method!
|
|
121
|
-
- http://www.igvita.com/2009/12/22/ruby-websockets-tcp-for-the-browser/
|
|
122
|
-
|
|
123
|
-
EventMachine.run {
|
|
124
|
-
http = EventMachine::HttpRequest.new("ws://yourservice.com/websocket").get :timeout => 0
|
|
125
|
-
|
|
126
|
-
http.errback { puts "oops" }
|
|
127
|
-
http.callback {
|
|
128
|
-
puts "WebSocket connected!"
|
|
129
|
-
http.send("Hello client")
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
http.stream { |msg|
|
|
133
|
-
puts "Recieved: #{msg}"
|
|
134
|
-
http.send "Pong: #{msg}"
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
http.disconnect { puts "oops, dropped connection?" }
|
|
138
|
-
}
|
data/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.2.9
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
class Hash
|
|
2
|
-
# Stolen partially from Merb : http://noobkit.com/show/ruby/gems/development/merb/hash/to_params.html
|
|
3
|
-
# Convert this hash to a query string:
|
|
4
|
-
#
|
|
5
|
-
# { :name => "Bob",
|
|
6
|
-
# :address => {
|
|
7
|
-
# :street => '111 Ruby Ave.',
|
|
8
|
-
# :city => 'Ruby Central',
|
|
9
|
-
# :phones => ['111-111-1111', '222-222-2222']
|
|
10
|
-
# }
|
|
11
|
-
# }.to_params
|
|
12
|
-
# #=> "name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave."
|
|
13
|
-
#
|
|
14
|
-
def to_params
|
|
15
|
-
params = ''
|
|
16
|
-
stack = []
|
|
17
|
-
|
|
18
|
-
each do |k, v|
|
|
19
|
-
if v.is_a?(Hash)
|
|
20
|
-
stack << [k,v]
|
|
21
|
-
elsif v.is_a?(Array)
|
|
22
|
-
stack << [k,Hash.from_array(v)]
|
|
23
|
-
else
|
|
24
|
-
params << "#{k}=#{v}&"
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
stack.each do |parent, hash|
|
|
29
|
-
hash.each do |k, v|
|
|
30
|
-
if v.is_a?(Hash)
|
|
31
|
-
stack << ["#{parent}[#{k}]", v]
|
|
32
|
-
else
|
|
33
|
-
params << "#{parent}[#{k}]=#{v}&"
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
params.chop! # trailing &
|
|
39
|
-
params
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
##
|
|
43
|
-
# Builds a hash from an array with keys as array indices.
|
|
44
|
-
def self.from_array(array = [])
|
|
45
|
-
h = Hash.new
|
|
46
|
-
array.size.times do |t|
|
|
47
|
-
h[t] = array[t]
|
|
48
|
-
end
|
|
49
|
-
h
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
data/spec/hash_spec.rb
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
require 'spec/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.split("&").should include "a=alpha"
|
|
8
|
-
{:a => "alpha", :b => "beta"}.to_params.split("&").should include "b=beta"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it "should transform a more complex hash into HTTP POST Params" do
|
|
12
|
-
{:a => "a", :b => ["c", "d", "e"]}.to_params.split("&").should include "a=a"
|
|
13
|
-
{:a => "a", :b => ["c", "d", "e"]}.to_params.split("&").should include "b[0]=c"
|
|
14
|
-
{:a => "a", :b => ["c", "d", "e"]}.to_params.split("&").should include "b[1]=d"
|
|
15
|
-
{:a => "a", :b => ["c", "d", "e"]}.to_params.split("&").should include "b[2]=e"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "should transform a very complex hash into HTTP POST Params" do
|
|
19
|
-
params = {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}.to_params.split("&")
|
|
20
|
-
params.should include "a=a"
|
|
21
|
-
params.should include "b[0][d]=d"
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|