rack-proxy 0.8.1 → 0.8.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5728c44041f0dddc056d3ebc1b35e5429e3319115c07ade4e98278d02f5ffc2
4
- data.tar.gz: 2d0a518195f43bb38557ab68c00c8bce11f234675fa1a4e1f242b3ce177d83f6
3
+ metadata.gz: 47505271ab54cee7d324c7fdd22c22ba7edae1b99146ee081913668925ff61f4
4
+ data.tar.gz: 74afa4cf47b33eba1e12a8a4b5f8b499237fa6a6fabacbb46c0bc820e627b07b
5
5
  SHA512:
6
- metadata.gz: 353fc92d5a941f141f18f17d885506ff51098756687fcab816aa7e61fa5ace9e62a2658530c23d917f059d36db6585988f80d829a2818036f4f232d02436cf4e
7
- data.tar.gz: 8874cf1e8ee86ad08db5b894ed9eb5e9975f1b43cf1c46e3b2422e720f57356b683a3c0782cd682435567506afeee690f90030e540b532a4c992b5724e9d820b
6
+ metadata.gz: 0ea871048c9cd7ceff7b13c7e59caad7d393947a9909e5372031cc51c85879d2e297b57c6245ea56dc7c104da3c5ed3bc5688e2ce7a8c006f68cba52c0ee1696
7
+ data.tar.gz: 1c3ee10747af4bc06e9a270ec21d1854f1112b82127940a198e075ee044c7be6e6c43847b83d5cfd6facfadd90a32e4260a2e8731665ced34d46ec7ffd2febc1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-proxy (0.8.1)
4
+ rack-proxy (0.8.3)
5
5
  rack
6
6
 
7
7
  GEM
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.1".freeze
8
+ VERSION = "0.8.3".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
- if Rack.const_defined?(:Headers)
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
@@ -126,7 +128,7 @@ module Rack
126
128
  target_request.body_stream = source_request.body
127
129
  target_request.content_length = source_request.content_length.to_i
128
130
  target_request.content_type = source_request.content_type if source_request.content_type
129
- target_request.body_stream.rewind
131
+ target_request.body_stream.rewind if target_request.body_stream.respond_to?(:rewind)
130
132
  end
131
133
 
132
134
  # Use basic auth if we have to
@@ -120,6 +120,42 @@ class RackProxyTest < Test::Unit::TestCase
120
120
  end
121
121
  end
122
122
 
123
+ # An input stream that deliberately omits #rewind, mimicking
124
+ # Rackup::Handler::WEBrick::Input under Rack 3 (the Rack 3 SPEC no longer
125
+ # requires the input stream to respond to #rewind, only gets/each/read).
126
+ class NonRewindableInput
127
+ def initialize(string)
128
+ @io = StringIO.new(string)
129
+ end
130
+
131
+ def read(*args) = @io.read(*args)
132
+ def gets(*args) = @io.gets(*args)
133
+ def each(&block) = @io.each(&block)
134
+ # intentionally NO #rewind
135
+ end
136
+
137
+ # Issue #128: a non-rewindable body stream must not raise (it used to blow up
138
+ # with NoMethodError on #rewind, surfacing confusingly as a 500). The body
139
+ # must still be forwarded intact, since it is never read before Net::HTTP sends it.
140
+ def test_non_rewindable_body_is_forwarded_without_raising
141
+ with_webrick_proxy(streaming: false) do |port, proxy|
142
+ proxy.host = "127.0.0.1:#{port}"
143
+
144
+ body = NonRewindableInput.new("hello=world")
145
+ assert !body.respond_to?(:rewind), "fixture must not be rewindable to exercise the guard"
146
+
147
+ env = Rack::MockRequest.env_for("/echo-body", method: "POST")
148
+ env["rack.input"] = body
149
+ env["CONTENT_LENGTH"] = "hello=world".bytesize.to_s
150
+ env["CONTENT_TYPE"] = "text/plain"
151
+
152
+ status, _headers, response = nil
153
+ assert_nothing_raised { status, _headers, response = proxy.call(env) }
154
+ assert_equal 200, status.to_i
155
+ assert_equal "hello=world", response.to_a.join, "body must be forwarded intact"
156
+ end
157
+ end
158
+
123
159
  def test_response_header_included_Hop_by_hop
124
160
  app({:streaming => true}).host = 'mockapi.io'
125
161
  get 'https://example.com/oauth2/token/info?access_token=123'
@@ -250,6 +286,22 @@ class RackProxyTest < Test::Unit::TestCase
250
286
  "expected debug output to include request line, got: #{sink.string.inspect}")
251
287
  end
252
288
 
289
+ # Regression: build_header_hash must not match a top-level ::Headers
290
+ # constant defined by the host app (would happen with inherit: true).
291
+ def test_build_header_hash_ignores_toplevel_headers_constant
292
+ Object.send(:remove_const, :Headers) if Object.const_defined?(:Headers, false)
293
+ Object.const_set(:Headers, Class.new)
294
+ begin
295
+ result = Rack::Proxy.send(:build_header_hash, [['X-Test', 'value']])
296
+ # On Rack 3+ we get Rack::Headers; on Rack 2 we get Rack::Utils::HeaderHash.
297
+ # In neither case should we get the bogus top-level ::Headers.
298
+ assert_not_equal ::Headers, result.class,
299
+ "build_header_hash leaked into top-level ::Headers"
300
+ ensure
301
+ Object.send(:remove_const, :Headers)
302
+ end
303
+ end
304
+
253
305
  def test_no_logger_means_no_debug_output
254
306
  # Without a :logger option, Net::HTTP's set_debug_output should never be
255
307
  # called. We can't directly assert that, but we can confirm requests still
@@ -292,6 +344,7 @@ class RackProxyTest < Test::Unit::TestCase
292
344
  res['x-custom'] = 'value-here'
293
345
  res.body = 'ok'
294
346
  end
347
+ server.mount_proc('/echo-body') { |req, res| res.body = req.body.to_s }
295
348
  Thread.new { server.start }
296
349
  port = server.config[:Port]
297
350
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacek Becela