rack-proxy 0.8.0 → 0.8.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -0
- data/lib/rack/http_streaming_response.rb +2 -1
- data/lib/rack/proxy.rb +10 -2
- data/test/rack_proxy_test.rb +53 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40c24e4b559fc7669c3b675184af8d7f0b9ba693d3a7b41e6433274c16429adc
|
|
4
|
+
data.tar.gz: 6f8790c5c391e102275c11225a869e2572d109f2e52e4783cdc5cbbb50733579
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2885f787b2f08c712c99b938218749d7f5d35348588290414f058c446104e10ba80b7f0b439ea60c3fc4daea1a0b0f991c92e853a3a9de4ef238d5f864d85d20
|
|
7
|
+
data.tar.gz: 3f70b5ab5eee94517d10e82f72f517a7e4cd3fec346ba78142ed6d93bd34bb7d175f6e857c037c7b0beffd710889651f15d107920e38da7208bdc132f246f712
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Options can be set when initializing the middleware or overriding a method.
|
|
|
43
43
|
* `:ssl_version` - tell `Net::HTTP` to set a specific `ssl_version`
|
|
44
44
|
* `:backend` - the URI parseable format of host and port of the target proxy backend. If not set it will assume the backend target is the same as the source.
|
|
45
45
|
* `:read_timeout` - set proxy timeout it defaults to 60 seconds
|
|
46
|
+
* `:logger` - any object responding to `#<<` (e.g. `$stdout`, a `StringIO`, or a Ruby `Logger`). Wired through to `Net::HTTP#set_debug_output` so the full HTTP wire-level conversation is written to the sink. Useful for debugging.
|
|
46
47
|
|
|
47
48
|
To pass in options, when you configure your middleware you can pass them in as an optional hash.
|
|
48
49
|
|
|
@@ -10,7 +10,7 @@ module Rack
|
|
|
10
10
|
304 => true
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
|
-
attr_accessor :use_ssl, :verify_mode, :read_timeout, :ssl_version, :cert, :key
|
|
13
|
+
attr_accessor :use_ssl, :verify_mode, :read_timeout, :ssl_version, :cert, :key, :logger
|
|
14
14
|
|
|
15
15
|
def initialize(request, host, port = nil)
|
|
16
16
|
@request, @host, @port = request, host, port
|
|
@@ -61,6 +61,7 @@ module Rack
|
|
|
61
61
|
http.ssl_version = ssl_version if ssl_version
|
|
62
62
|
http.cert = cert if cert
|
|
63
63
|
http.key = key if key
|
|
64
|
+
http.set_debug_output(logger) if logger
|
|
64
65
|
http.start
|
|
65
66
|
end
|
|
66
67
|
end
|
data/lib/rack/proxy.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Rack
|
|
|
5
5
|
|
|
6
6
|
# Subclass and bring your own #rewrite_request and #rewrite_response
|
|
7
7
|
class Proxy
|
|
8
|
-
VERSION = "0.8.
|
|
8
|
+
VERSION = "0.8.2".freeze
|
|
9
9
|
|
|
10
10
|
HOP_BY_HOP_HEADERS = {
|
|
11
11
|
'connection' => true,
|
|
@@ -39,7 +39,9 @@ module Rack
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def build_header_hash(pairs)
|
|
42
|
-
|
|
42
|
+
# Pass inherit: false so we only check Rack's own constants — otherwise
|
|
43
|
+
# a top-level ::Headers defined by the host app would falsely match.
|
|
44
|
+
if Rack.const_defined?(:Headers, false)
|
|
43
45
|
# Rack::Headers is only available from Rack 3 onward
|
|
44
46
|
Headers.new.tap { |headers| pairs.each { |k, v| headers[k] = v } }
|
|
45
47
|
else
|
|
@@ -83,6 +85,10 @@ module Rack
|
|
|
83
85
|
@username = opts[:username]
|
|
84
86
|
@password = opts[:password]
|
|
85
87
|
|
|
88
|
+
# Optional logger for Net::HTTP debug output. Accepts anything with a #<< method
|
|
89
|
+
# (e.g. $stdout, a StringIO, or a Ruby Logger instance).
|
|
90
|
+
@logger = opts[:logger]
|
|
91
|
+
|
|
86
92
|
@opts = opts
|
|
87
93
|
end
|
|
88
94
|
|
|
@@ -143,6 +149,7 @@ module Rack
|
|
|
143
149
|
target_response.verify_mode = (@verify_mode || OpenSSL::SSL::VERIFY_PEER) if use_ssl
|
|
144
150
|
target_response.cert = @cert if @cert
|
|
145
151
|
target_response.key = @key if @key
|
|
152
|
+
target_response.logger = @logger if @logger
|
|
146
153
|
else
|
|
147
154
|
http = Net::HTTP.new(backend.host, backend.port)
|
|
148
155
|
http.use_ssl = use_ssl if use_ssl
|
|
@@ -151,6 +158,7 @@ module Rack
|
|
|
151
158
|
http.verify_mode = @verify_mode || OpenSSL::SSL::VERIFY_PEER if use_ssl
|
|
152
159
|
http.cert = @cert if @cert
|
|
153
160
|
http.key = @key if @key
|
|
161
|
+
http.set_debug_output(@logger) if @logger
|
|
154
162
|
|
|
155
163
|
target_response = http.start do
|
|
156
164
|
http.request(target_request)
|
data/test/rack_proxy_test.rb
CHANGED
|
@@ -226,6 +226,57 @@ class RackProxyTest < Test::Unit::TestCase
|
|
|
226
226
|
assert last_response.ok?
|
|
227
227
|
end
|
|
228
228
|
|
|
229
|
+
# Issue #80: a :logger option should pipe Net::HTTP debug output to the
|
|
230
|
+
# given sink (anything responding to #<<). We use a StringIO to capture it.
|
|
231
|
+
def test_logger_captures_request_in_non_streaming
|
|
232
|
+
sink = StringIO.new
|
|
233
|
+
with_webrick_proxy(streaming: false, logger: sink) do |port, proxy|
|
|
234
|
+
proxy.host = "127.0.0.1:#{port}"
|
|
235
|
+
get '/empty'
|
|
236
|
+
assert last_response.ok?
|
|
237
|
+
end
|
|
238
|
+
assert_match(/GET \/empty/, sink.string,
|
|
239
|
+
"expected debug output to include request line, got: #{sink.string.inspect}")
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def test_logger_captures_request_in_streaming
|
|
243
|
+
sink = StringIO.new
|
|
244
|
+
with_webrick_proxy(streaming: true, logger: sink) do |port, proxy|
|
|
245
|
+
proxy.host = "127.0.0.1:#{port}"
|
|
246
|
+
get '/empty'
|
|
247
|
+
assert last_response.ok?
|
|
248
|
+
end
|
|
249
|
+
assert_match(/GET \/empty/, sink.string,
|
|
250
|
+
"expected debug output to include request line, got: #{sink.string.inspect}")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Regression: build_header_hash must not match a top-level ::Headers
|
|
254
|
+
# constant defined by the host app (would happen with inherit: true).
|
|
255
|
+
def test_build_header_hash_ignores_toplevel_headers_constant
|
|
256
|
+
Object.send(:remove_const, :Headers) if Object.const_defined?(:Headers, false)
|
|
257
|
+
Object.const_set(:Headers, Class.new)
|
|
258
|
+
begin
|
|
259
|
+
result = Rack::Proxy.send(:build_header_hash, [['X-Test', 'value']])
|
|
260
|
+
# On Rack 3+ we get Rack::Headers; on Rack 2 we get Rack::Utils::HeaderHash.
|
|
261
|
+
# In neither case should we get the bogus top-level ::Headers.
|
|
262
|
+
assert_not_equal ::Headers, result.class,
|
|
263
|
+
"build_header_hash leaked into top-level ::Headers"
|
|
264
|
+
ensure
|
|
265
|
+
Object.send(:remove_const, :Headers)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def test_no_logger_means_no_debug_output
|
|
270
|
+
# Without a :logger option, Net::HTTP's set_debug_output should never be
|
|
271
|
+
# called. We can't directly assert that, but we can confirm requests still
|
|
272
|
+
# work when no logger is configured (covered by every other test).
|
|
273
|
+
with_webrick_proxy(streaming: false) do |port, proxy|
|
|
274
|
+
proxy.host = "127.0.0.1:#{port}"
|
|
275
|
+
get '/empty'
|
|
276
|
+
assert last_response.ok?
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
229
280
|
private
|
|
230
281
|
|
|
231
282
|
def assert_no_array_header_values(streaming:)
|
|
@@ -242,7 +293,7 @@ class RackProxyTest < Test::Unit::TestCase
|
|
|
242
293
|
|
|
243
294
|
# Spin up a tiny WEBrick server with fixed routes so we can exercise the
|
|
244
295
|
# proxy against real Net::HTTP requests without depending on a remote host.
|
|
245
|
-
def with_webrick_proxy(
|
|
296
|
+
def with_webrick_proxy(**proxy_opts)
|
|
246
297
|
require 'webrick'
|
|
247
298
|
server = WEBrick::HTTPServer.new(
|
|
248
299
|
Port: 0,
|
|
@@ -260,7 +311,7 @@ class RackProxyTest < Test::Unit::TestCase
|
|
|
260
311
|
Thread.new { server.start }
|
|
261
312
|
port = server.config[:Port]
|
|
262
313
|
|
|
263
|
-
proxy = HostProxy.new(
|
|
314
|
+
proxy = HostProxy.new(**proxy_opts)
|
|
264
315
|
@app = proxy
|
|
265
316
|
yield port, proxy
|
|
266
317
|
ensure
|