em-http-request 0.3.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of em-http-request might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/.gitignore +1 -0
  2. data/Changelog.md +10 -0
  3. data/README.md +43 -160
  4. data/Rakefile +2 -73
  5. data/em-http-request.gemspec +7 -7
  6. data/examples/fetch.rb +30 -30
  7. data/examples/fibered-http.rb +38 -38
  8. data/examples/oauth-tweet.rb +49 -49
  9. data/lib/em-http.rb +4 -6
  10. data/lib/em-http/client.rb +101 -522
  11. data/lib/em-http/http_connection.rb +125 -0
  12. data/lib/em-http/http_encoding.rb +19 -12
  13. data/lib/em-http/http_header.rb +2 -17
  14. data/lib/em-http/http_options.rb +37 -19
  15. data/lib/em-http/request.rb +33 -66
  16. data/lib/em-http/version.rb +2 -2
  17. data/spec/client_spec.rb +575 -0
  18. data/spec/dns_spec.rb +41 -0
  19. data/spec/encoding_spec.rb +6 -6
  20. data/spec/external_spec.rb +99 -0
  21. data/spec/fixtures/google.ca +13 -17
  22. data/spec/helper.rb +17 -8
  23. data/spec/http_proxy_spec.rb +53 -0
  24. data/spec/middleware_spec.rb +114 -0
  25. data/spec/multi_spec.rb +11 -38
  26. data/spec/pipelining_spec.rb +38 -0
  27. data/spec/redirect_spec.rb +114 -0
  28. data/spec/socksify_proxy_spec.rb +24 -0
  29. data/spec/ssl_spec.rb +20 -0
  30. data/spec/stallion.rb +7 -63
  31. metadata +59 -39
  32. data/examples/websocket-handler.rb +0 -28
  33. data/examples/websocket-server.rb +0 -8
  34. data/ext/buffer/em_buffer.c +0 -639
  35. data/ext/buffer/extconf.rb +0 -53
  36. data/ext/http11_client/ext_help.h +0 -14
  37. data/ext/http11_client/extconf.rb +0 -6
  38. data/ext/http11_client/http11_client.c +0 -328
  39. data/ext/http11_client/http11_parser.c +0 -418
  40. data/ext/http11_client/http11_parser.h +0 -48
  41. data/ext/http11_client/http11_parser.rl +0 -170
  42. data/lib/em-http/mock.rb +0 -137
  43. data/spec/mock_spec.rb +0 -166
  44. data/spec/request_spec.rb +0 -1003
@@ -0,0 +1,38 @@
1
+ require 'helper'
2
+
3
+ requires_connection do
4
+
5
+ describe EventMachine::HttpRequest do
6
+
7
+ it "should perform successful pipelined GETs" do
8
+ EventMachine.run do
9
+
10
+ # Mongrel doesn't support pipelined requests - bah!
11
+ conn = EventMachine::HttpRequest.new('http://www.igvita.com/')
12
+
13
+ pipe1 = conn.get :keepalive => true
14
+ pipe2 = conn.get :path => '/about/', :keepalive => true
15
+
16
+ processed = 0
17
+ stop = proc { EM.stop if processed == 2}
18
+
19
+ pipe1.errback { failed(conn) }
20
+ pipe1.callback {
21
+ processed += 1
22
+ pipe1.response_header.status.should == 200
23
+ stop.call
24
+ }
25
+
26
+ pipe2.errback { p pipe2; failed(conn) }
27
+ pipe2.callback {
28
+ processed += 1
29
+ pipe2.response_header.status.should == 200
30
+ pipe2.response.should match('biography')
31
+ stop.call
32
+ }
33
+
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,114 @@
1
+ require 'helper'
2
+
3
+ describe EventMachine::HttpRequest do
4
+
5
+ it "should follow location redirects" do
6
+ EventMachine.run {
7
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect').get :redirects => 1
8
+ http.errback { failed(http) }
9
+ http.callback {
10
+ http.response_header.status.should == 200
11
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
12
+ http.response.should == "compressed"
13
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
14
+ http.redirects.should == 1
15
+
16
+ EM.stop
17
+ }
18
+ }
19
+ end
20
+
21
+ it "should redirect with missing content-length" do
22
+ EventMachine.run {
23
+ @s = StubServer.new("HTTP/1.0 301 MOVED PERMANENTLY\r\nlocation: http://127.0.0.1:8090/redirect\r\n\r\n")
24
+
25
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get :redirects => 3
26
+ http.errback { failed(http) }
27
+
28
+ http.callback {
29
+ http.response_header.status.should == 200
30
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
31
+ http.response.should == "compressed"
32
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
33
+ http.redirects.should == 3
34
+
35
+ @s.stop
36
+ EM.stop
37
+ }
38
+ }
39
+ end
40
+
41
+ it "should follow redirects on HEAD method" do
42
+ EventMachine.run {
43
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect/head').head :redirects => 1
44
+ http.errback { failed(http) }
45
+ http.callback {
46
+ http.response_header.status.should == 200
47
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/'
48
+ EM.stop
49
+ }
50
+ }
51
+ end
52
+
53
+ it "should report last_effective_url" do
54
+ EventMachine.run {
55
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
56
+ http.errback { failed(http) }
57
+ http.callback {
58
+ http.response_header.status.should == 200
59
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/'
60
+
61
+ EM.stop
62
+ }
63
+ }
64
+ end
65
+
66
+ it "should default to 0 redirects" do
67
+ EventMachine.run {
68
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect').get
69
+ http.errback { failed(http) }
70
+ http.callback {
71
+ http.response_header.status.should == 301
72
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/redirect'
73
+ http.redirects.should == 0
74
+
75
+ EM.stop
76
+ }
77
+ }
78
+ end
79
+
80
+ it "should not invoke redirect logic on failed(http) connections" do
81
+ EventMachine.run {
82
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/', :connect_timeout => 0.1).get :redirects => 5
83
+ http.callback { failed(http) }
84
+ http.errback {
85
+ http.redirects.should == 0
86
+ EM.stop
87
+ }
88
+ }
89
+ end
90
+
91
+ it "should normalize redirect urls" do
92
+ EventMachine.run {
93
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect/bad').get :redirects => 1
94
+ http.errback { failed(http) }
95
+ http.callback {
96
+ http.last_effective_url.to_s.should match('http://127.0.0.1:8090/')
97
+ http.response.should match('Hello, World!')
98
+ EM.stop
99
+ }
100
+ }
101
+ end
102
+
103
+ it "should fail gracefully on a missing host in absolute Location header" do
104
+ EventMachine.run {
105
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect/nohost').get :redirects => 1
106
+ http.callback { failed(http) }
107
+ http.errback {
108
+ http.error.should == 'Location header format error'
109
+ EM.stop
110
+ }
111
+ }
112
+ end
113
+
114
+ end
@@ -0,0 +1,24 @@
1
+ require 'helper'
2
+
3
+ requires_connection do
4
+
5
+ describe EventMachine::HttpRequest do
6
+
7
+ # ssh -D 8080 igvita
8
+ let(:proxy) { {:proxy => { :host => '127.0.0.1', :port => 8080, :type => :socks5 }} }
9
+
10
+ it "should use SOCKS5 proxy" do
11
+ EventMachine.run {
12
+ http = EventMachine::HttpRequest.new('http://whatismyip.everdot.org/', proxy).get
13
+
14
+ http.errback { failed(http) }
15
+ http.callback {
16
+ http.response_header.status.should == 200
17
+ http.response.should match('72.52.131')
18
+ EventMachine.stop
19
+ }
20
+ }
21
+ end
22
+ end
23
+
24
+ end
data/spec/ssl_spec.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ requires_connection do
4
+
5
+ describe EventMachine::HttpRequest do
6
+
7
+ it "should initiate SSL/TLS on HTTPS connections" do
8
+ EventMachine.run {
9
+ http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
10
+
11
+ http.errback { failed(http) }
12
+ http.callback {
13
+ http.response_header.status.should == 302
14
+ EventMachine.stop
15
+ }
16
+ }
17
+ end
18
+ end
19
+
20
+ end
data/spec/stallion.rb CHANGED
@@ -52,7 +52,7 @@ module Stallion
52
52
  end
53
53
 
54
54
  def self.run(options = {})
55
- options = {:Host => "127.0.0.1", :Port => 8080}.merge(options)
55
+ options = {:Host => "127.0.0.1", :Port => 8090}.merge(options)
56
56
  Rack::Handler::Mongrel.run(Rack::Lint.new(self), options)
57
57
  end
58
58
 
@@ -120,7 +120,7 @@ Stallion.saddle :spec do |stable|
120
120
 
121
121
  elsif stable.request.path_info == '/redirect/bad'
122
122
  stable.response.status = 301
123
- stable.response["Location"] = "http://127.0.0.1:8080"
123
+ stable.response["Location"] = "http://127.0.0.1:8090"
124
124
 
125
125
  elsif stable.request.path_info == '/redirect/head'
126
126
  stable.response.status = 301
@@ -151,11 +151,11 @@ Stallion.saddle :spec do |stable|
151
151
  stable.response.status = 304
152
152
 
153
153
  elsif stable.request.env["HTTP_AUTHORIZATION"]
154
- if stable.request.path_info == '/oauth_auth'
154
+ if stable.request.path_info == '/auth'
155
155
  stable.response.status = 200
156
156
  stable.response.write stable.request.env["HTTP_AUTHORIZATION"]
157
157
  else
158
- auth = "Basic %s" % Base64.encode64(['user', 'pass'].join(':')).chomp
158
+ auth = "Basic %s" % Base64.encode64(['user', 'pass'].join(':')).split.join
159
159
 
160
160
  if auth == stable.request.env["HTTP_AUTHORIZATION"]
161
161
  stable.response.status = 200
@@ -177,71 +177,14 @@ end
177
177
 
178
178
  Thread.new do
179
179
  begin
180
- Stallion.run :Host => '127.0.0.1', :Port => 8080
180
+ Stallion.run :Host => '127.0.0.1', :Port => 8090
181
181
  rescue Exception => e
182
182
  print e
183
183
  end
184
184
  end
185
185
 
186
186
  #
187
- # Tunneling HTTP Proxy server
188
- #
189
- Thread.new do
190
- server = TCPServer.new('127.0.0.1', 8082)
191
- loop do
192
- session = server.accept
193
- request = ""
194
- while (data = session.gets) != "\r\n"
195
- request << data
196
- end
197
- parts = request.split("\r\n")
198
- method, destination, http_version = parts.first.split(' ')
199
- if method == 'CONNECT'
200
- target_host, target_port = destination.split(':')
201
- client = TCPSocket.open(target_host, target_port)
202
- session.write "HTTP/1.1 200 Connection established\r\nProxy-agent: Whatever\r\n\r\n"
203
- session.flush
204
-
205
- content_length = -1
206
- verb = ""
207
- req = ""
208
-
209
- while data = session.gets
210
- if request = data.match(/(\w+).*HTTP\/1\.1/)
211
- verb = request[1]
212
- end
213
-
214
- if post = data.match(/Content-Length: (\d+)/)
215
- content_length = post[1].to_i
216
- end
217
-
218
- req += data
219
-
220
- # read POST data
221
- if data == "\r\n" and verb == "POST"
222
- req += session.read(content_length)
223
- end
224
-
225
- if data == "\r\n"
226
- client.write req
227
- client.flush
228
- client.close_write
229
- break
230
- end
231
- end
232
-
233
- while data = client.gets
234
- session.write data
235
- end
236
- session.flush
237
- client.close
238
- end
239
- session.close
240
- end
241
- end
242
-
243
- #
244
- # CONNECT-less HTTP Proxy server
187
+ # Simple HTTP Proxy server
245
188
  #
246
189
  Thread.new do
247
190
  server = TCPServer.new('127.0.0.1', 8083)
@@ -257,6 +200,7 @@ Thread.new do
257
200
  uri = Addressable::URI.parse(destination)
258
201
  absolute_path = uri.path + (uri.query ? "?#{uri.query}" : "")
259
202
  client = TCPSocket.open(uri.host, uri.port || 80)
203
+
260
204
  client.write "#{method} #{absolute_path} #{http_version}\r\n"
261
205
  parts[1..-1].each do |part|
262
206
  client.write "#{part}\r\n"
metadata CHANGED
@@ -1,12 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-http-request
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ prerelease: true
5
5
  segments:
6
+ - 1
6
7
  - 0
7
- - 3
8
8
  - 0
9
- version: 0.3.0
9
+ - beta
10
+ - 1
11
+ version: 1.0.0.beta.1
10
12
  platform: ruby
11
13
  authors:
12
14
  - Ilya Grigorik
@@ -14,7 +16,7 @@ autorequire:
14
16
  bindir: bin
15
17
  cert_chain: []
16
18
 
17
- date: 2011-01-15 00:00:00 -05:00
19
+ date: 2011-02-20 00:00:00 -05:00
18
20
  default_executable:
19
21
  dependencies:
20
22
  - !ruby/object:Gem::Dependency
@@ -27,9 +29,7 @@ dependencies:
27
29
  - !ruby/object:Gem::Version
28
30
  segments:
29
31
  - 0
30
- - 12
31
- - 9
32
- version: 0.12.9
32
+ version: "0"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
@@ -42,13 +42,13 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  segments:
44
44
  - 2
45
- - 0
46
- - 0
47
- version: 2.0.0
45
+ - 2
46
+ - 3
47
+ version: 2.2.3
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
50
  - !ruby/object:Gem::Dependency
51
- name: escape_utils
51
+ name: http_parser.rb
52
52
  prerelease: false
53
53
  requirement: &id003 !ruby/object:Gem::Requirement
54
54
  none: false
@@ -57,11 +57,13 @@ dependencies:
57
57
  - !ruby/object:Gem::Version
58
58
  segments:
59
59
  - 0
60
- version: "0"
60
+ - 5
61
+ - 1
62
+ version: 0.5.1
61
63
  type: :runtime
62
64
  version_requirements: *id003
63
65
  - !ruby/object:Gem::Dependency
64
- name: rspec
66
+ name: em-socksify
65
67
  prerelease: false
66
68
  requirement: &id004 !ruby/object:Gem::Requirement
67
69
  none: false
@@ -71,10 +73,10 @@ dependencies:
71
73
  segments:
72
74
  - 0
73
75
  version: "0"
74
- type: :development
76
+ type: :runtime
75
77
  version_requirements: *id004
76
78
  - !ruby/object:Gem::Dependency
77
- name: rake
79
+ name: rspec
78
80
  prerelease: false
79
81
  requirement: &id005 !ruby/object:Gem::Requirement
80
82
  none: false
@@ -87,7 +89,7 @@ dependencies:
87
89
  type: :development
88
90
  version_requirements: *id005
89
91
  - !ruby/object:Gem::Dependency
90
- name: em-websocket
92
+ name: rake
91
93
  prerelease: false
92
94
  requirement: &id006 !ruby/object:Gem::Requirement
93
95
  none: false
@@ -113,9 +115,22 @@ dependencies:
113
115
  type: :development
114
116
  version_requirements: *id007
115
117
  - !ruby/object:Gem::Dependency
116
- name: mongrel
118
+ name: yajl-ruby
117
119
  prerelease: false
118
120
  requirement: &id008 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 0
127
+ version: "0"
128
+ type: :development
129
+ version_requirements: *id008
130
+ - !ruby/object:Gem::Dependency
131
+ name: mongrel
132
+ prerelease: false
133
+ requirement: &id009 !ruby/object:Gem::Requirement
119
134
  none: false
120
135
  requirements:
121
136
  - - ~>
@@ -127,15 +142,14 @@ dependencies:
127
142
  - pre2
128
143
  version: 1.2.0.pre2
129
144
  type: :development
130
- version_requirements: *id008
145
+ version_requirements: *id009
131
146
  description: EventMachine based, async HTTP Request client
132
147
  email:
133
148
  - ilya@igvita.com
134
149
  executables: []
135
150
 
136
- extensions:
137
- - ext/buffer/extconf.rb
138
- - ext/http11_client/extconf.rb
151
+ extensions: []
152
+
139
153
  extra_rdoc_files: []
140
154
 
141
155
  files:
@@ -150,34 +164,31 @@ files:
150
164
  - examples/fibered-http.rb
151
165
  - examples/oauth-tweet.rb
152
166
  - examples/socks5.rb
153
- - examples/websocket-handler.rb
154
- - examples/websocket-server.rb
155
- - ext/buffer/em_buffer.c
156
- - ext/buffer/extconf.rb
157
- - ext/http11_client/ext_help.h
158
- - ext/http11_client/extconf.rb
159
- - ext/http11_client/http11_client.c
160
- - ext/http11_client/http11_parser.c
161
- - ext/http11_client/http11_parser.h
162
- - ext/http11_client/http11_parser.rl
163
167
  - lib/em-http-request.rb
164
168
  - lib/em-http.rb
165
169
  - lib/em-http/client.rb
166
170
  - lib/em-http/core_ext/bytesize.rb
167
171
  - lib/em-http/decoders.rb
172
+ - lib/em-http/http_connection.rb
168
173
  - lib/em-http/http_encoding.rb
169
174
  - lib/em-http/http_header.rb
170
175
  - lib/em-http/http_options.rb
171
- - lib/em-http/mock.rb
172
176
  - lib/em-http/multi.rb
173
177
  - lib/em-http/request.rb
174
178
  - lib/em-http/version.rb
179
+ - spec/client_spec.rb
180
+ - spec/dns_spec.rb
175
181
  - spec/encoding_spec.rb
182
+ - spec/external_spec.rb
176
183
  - spec/fixtures/google.ca
177
184
  - spec/helper.rb
178
- - spec/mock_spec.rb
185
+ - spec/http_proxy_spec.rb
186
+ - spec/middleware_spec.rb
179
187
  - spec/multi_spec.rb
180
- - spec/request_spec.rb
188
+ - spec/pipelining_spec.rb
189
+ - spec/redirect_spec.rb
190
+ - spec/socksify_proxy_spec.rb
191
+ - spec/ssl_spec.rb
181
192
  - spec/stallion.rb
182
193
  - spec/stub_server.rb
183
194
  has_rdoc: true
@@ -200,11 +211,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
211
  required_rubygems_version: !ruby/object:Gem::Requirement
201
212
  none: false
202
213
  requirements:
203
- - - ">="
214
+ - - ">"
204
215
  - !ruby/object:Gem::Version
205
216
  segments:
206
- - 0
207
- version: "0"
217
+ - 1
218
+ - 3
219
+ - 1
220
+ version: 1.3.1
208
221
  requirements: []
209
222
 
210
223
  rubyforge_project: em-http-request
@@ -213,11 +226,18 @@ signing_key:
213
226
  specification_version: 3
214
227
  summary: EventMachine based, async HTTP Request client
215
228
  test_files:
229
+ - spec/client_spec.rb
230
+ - spec/dns_spec.rb
216
231
  - spec/encoding_spec.rb
232
+ - spec/external_spec.rb
217
233
  - spec/fixtures/google.ca
218
234
  - spec/helper.rb
219
- - spec/mock_spec.rb
235
+ - spec/http_proxy_spec.rb
236
+ - spec/middleware_spec.rb
220
237
  - spec/multi_spec.rb
221
- - spec/request_spec.rb
238
+ - spec/pipelining_spec.rb
239
+ - spec/redirect_spec.rb
240
+ - spec/socksify_proxy_spec.rb
241
+ - spec/ssl_spec.rb
222
242
  - spec/stallion.rb
223
243
  - spec/stub_server.rb