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/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
- sleep(1)
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
- - 2
8
- - 9
9
- version: 0.2.9
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: 2010-07-07 00:00:00 -04:00
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
- description: EventMachine based, async HTTP Request interface
49
- email: ilya@igvita.com
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
- - LICENSE
57
- - README.rdoc
139
+ extra_rdoc_files: []
140
+
58
141
  files:
59
142
  - .gitignore
60
- - LICENSE
61
- - README.rdoc
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
- - --charset=UTF-8
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
- - 1
111
- - 8
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.6
211
+ rubygems_version: 1.3.7
125
212
  signing_key:
126
213
  specification_version: 3
127
- summary: EventMachine based, async HTTP Request interface
214
+ summary: EventMachine based, async HTTP Request client
128
215
  test_files:
129
- - spec/hash_spec.rb
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