em-http-request 0.2.10 → 0.2.11
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.
Potentially problematic release.
This version of em-http-request might be problematic. Click here for more details.
- data/LICENSE +58 -58
- data/README.md +157 -0
- data/Rakefile +110 -106
- data/VERSION +1 -1
- data/em-http-request.gemspec +5 -4
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/examples/websocket-handler.rb +28 -28
- data/examples/websocket-server.rb +8 -8
- data/ext/buffer/extconf.rb +53 -53
- data/ext/http11_client/ext_help.h +14 -14
- data/ext/http11_client/extconf.rb +6 -6
- data/ext/http11_client/http11_client.c +328 -328
- data/ext/http11_client/http11_parser.c +418 -418
- data/ext/http11_client/http11_parser.h +48 -48
- data/ext/http11_client/http11_parser.rl +170 -170
- data/lib/em-http-request.rb +1 -1
- data/lib/em-http.rb +2 -1
- data/lib/em-http/client.rb +58 -26
- data/lib/em-http/core_ext/bytesize.rb +5 -5
- data/lib/em-http/core_ext/hash.rb +53 -53
- data/lib/em-http/decoders.rb +122 -122
- data/lib/em-http/http_options.rb +33 -31
- data/lib/em-http/mock.rb +90 -50
- data/lib/em-http/multi.rb +21 -17
- data/lib/em-http/request.rb +1 -0
- data/spec/fixtures/google.ca +20 -21
- data/spec/hash_spec.rb +24 -24
- data/spec/helper.rb +3 -2
- data/spec/mock_spec.rb +79 -34
- data/spec/multi_spec.rb +27 -10
- data/spec/request_spec.rb +198 -65
- data/spec/spec.opts +7 -0
- data/spec/stallion.rb +59 -2
- data/spec/stub_server.rb +22 -22
- metadata +6 -5
- data/README.rdoc +0 -138
data/spec/spec.opts
ADDED
data/spec/stallion.rb
CHANGED
@@ -78,6 +78,8 @@ 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'
|
@@ -113,6 +115,19 @@ Stallion.saddle :spec do |stable|
|
|
113
115
|
elsif stable.request.path_info == '/redirect'
|
114
116
|
stable.response.status = 301
|
115
117
|
stable.response["Location"] = "/gzip"
|
118
|
+
stable.response.write 'redirect'
|
119
|
+
|
120
|
+
elsif stable.request.path_info == '/redirect/bad'
|
121
|
+
stable.response.status = 301
|
122
|
+
stable.response["Location"] = "http://127.0.0.1:8080"
|
123
|
+
|
124
|
+
elsif stable.request.path_info == '/redirect/nohost'
|
125
|
+
stable.response.status = 301
|
126
|
+
stable.response["Location"] = "http:/"
|
127
|
+
|
128
|
+
elsif stable.request.path_info == '/redirect/badhost'
|
129
|
+
stable.response.status = 301
|
130
|
+
stable.response["Location"] = "http://$$$@$!%&^"
|
116
131
|
|
117
132
|
elsif stable.request.path_info == '/gzip'
|
118
133
|
io = StringIO.new
|
@@ -164,7 +179,7 @@ Thread.new do
|
|
164
179
|
end
|
165
180
|
|
166
181
|
#
|
167
|
-
# HTTP Proxy server
|
182
|
+
# Tunneling HTTP Proxy server
|
168
183
|
#
|
169
184
|
Thread.new do
|
170
185
|
server = TCPServer.new('127.0.0.1', 8082)
|
@@ -220,4 +235,46 @@ Thread.new do
|
|
220
235
|
end
|
221
236
|
end
|
222
237
|
|
223
|
-
|
238
|
+
#
|
239
|
+
# CONNECT-less HTTP Proxy server
|
240
|
+
#
|
241
|
+
Thread.new do
|
242
|
+
server = TCPServer.new('127.0.0.1', 8083)
|
243
|
+
loop do
|
244
|
+
session = server.accept
|
245
|
+
request = ""
|
246
|
+
while (data = session.gets) != "\r\n"
|
247
|
+
request << data
|
248
|
+
end
|
249
|
+
parts = request.split("\r\n")
|
250
|
+
method, destination, http_version = parts.first.split(' ')
|
251
|
+
if destination =~ /^http:/
|
252
|
+
uri = Addressable::URI.parse(destination)
|
253
|
+
absolute_path = uri.path + (uri.query ? "?#{uri.query}" : "")
|
254
|
+
client = TCPSocket.open(uri.host, uri.port || 80)
|
255
|
+
client.write "#{method} #{absolute_path} #{http_version}\r\n"
|
256
|
+
parts[1..-1].each do |part|
|
257
|
+
client.write "#{part}\r\n"
|
258
|
+
end
|
259
|
+
|
260
|
+
client.write "\r\n"
|
261
|
+
client.flush
|
262
|
+
client.close_write
|
263
|
+
|
264
|
+
# Take the initial line from the upstream response
|
265
|
+
session.write client.gets
|
266
|
+
|
267
|
+
# What (absolute) uri was requested? Send it back in a header
|
268
|
+
session.write "X-The-Requested-URI: #{destination}\r\n"
|
269
|
+
|
270
|
+
while data = client.gets
|
271
|
+
session.write data
|
272
|
+
end
|
273
|
+
session.flush
|
274
|
+
client.close
|
275
|
+
end
|
276
|
+
session.close
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
sleep(1)
|
data/spec/stub_server.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
class StubServer
|
2
|
-
module Server
|
3
|
-
def receive_data(data)
|
4
|
-
send_data @response
|
5
|
-
close_connection_after_writing
|
6
|
-
end
|
7
|
-
|
8
|
-
def response=(response)
|
9
|
-
@response = response
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(response, port=8081)
|
14
|
-
@sig = EventMachine::start_server("127.0.0.1", port, Server) { |s|
|
15
|
-
s.response = response
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
def stop
|
20
|
-
EventMachine.stop_server @sig
|
21
|
-
end
|
22
|
-
end
|
1
|
+
class StubServer
|
2
|
+
module Server
|
3
|
+
def receive_data(data)
|
4
|
+
send_data @response
|
5
|
+
close_connection_after_writing
|
6
|
+
end
|
7
|
+
|
8
|
+
def response=(response)
|
9
|
+
@response = response
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(response, port=8081)
|
14
|
+
@sig = EventMachine::start_server("127.0.0.1", port, Server) { |s|
|
15
|
+
s.response = response
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop
|
20
|
+
EventMachine.stop_server @sig
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 11
|
9
|
+
version: 0.2.11
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ilya Grigorik
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-08-16 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -54,11 +54,11 @@ extensions:
|
|
54
54
|
- ext/http11_client/extconf.rb
|
55
55
|
extra_rdoc_files:
|
56
56
|
- LICENSE
|
57
|
-
- README.
|
57
|
+
- README.md
|
58
58
|
files:
|
59
59
|
- .gitignore
|
60
60
|
- LICENSE
|
61
|
-
- README.
|
61
|
+
- README.md
|
62
62
|
- Rakefile
|
63
63
|
- VERSION
|
64
64
|
- em-http-request.gemspec
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- spec/mock_spec.rb
|
92
92
|
- spec/multi_spec.rb
|
93
93
|
- spec/request_spec.rb
|
94
|
+
- spec/spec.opts
|
94
95
|
- spec/stallion.rb
|
95
96
|
- spec/stub_server.rb
|
96
97
|
has_rdoc: true
|
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 :redirects => 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
|
-
}
|