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

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.

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