rack-proxy 0.7.0 → 0.7.4

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: 228f3bf6e52dcd2bdcebf9c52bf1db47dfdc7179ed52cd3664e14cfd8df80db9
4
- data.tar.gz: 6613d7f13087046d9ad6ee22e5afa56db6910145df427e42101f5aa491d3fe26
3
+ metadata.gz: 896fa421268e5b014853a876ec69e499e5e48b5befd5c7438ffacd4094ceeb75
4
+ data.tar.gz: dfcdf003e020c8590eaaf1dd0a531f0a516b85ece47898261611e5149bd81411
5
5
  SHA512:
6
- metadata.gz: 151b04e286d1305d116cf743f00c6b811ed10fad0f24cf806b685a4e038a4dcf5c3b8f7e0dd0cf1e8aa95dd8c46763b0f8b114d36c668fdaabda541d48d5722a
7
- data.tar.gz: 234ec48678c973b203cf00f256039c6e88f63c67c5e279e6f0ec17fc51de07022f7a3099dfe0efdaacf46808a0512cd9e16444823b6d616fdee08ae5572efbb2
6
+ metadata.gz: 16d0245d20d2144d34fbbb15f23ba719dd189c8d9e9166caf55c13e3492406a3af9803f76b6ae07b10c1d6700385caf2d41825188554834ef010a90af666250e
7
+ data.tar.gz: f477d57ddd81d95f95e700952daf8168d4001098cc458b5aac2599cafc0847923ed25cd0ea6aed711e9bae6461b54a7e826f0d4ea34737a6b440bf961ba21251
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: [ncr]
data/.travis.yml CHANGED
@@ -1,4 +1,3 @@
1
- sudo: false
2
1
  cache: bundler
3
2
  language: ruby
4
3
  before_install:
data/Gemfile.lock CHANGED
@@ -1,18 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-proxy (0.7.0)
4
+ rack-proxy (0.7.4)
5
5
  rack
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- power_assert (0.2.6)
11
- rack (2.0.3)
12
- rack-test (0.5.6)
13
- rack (>= 1.0)
14
- rake (13.0.1)
15
- test-unit (3.1.5)
10
+ power_assert (2.0.1)
11
+ rack (2.2.4)
12
+ rack-test (1.1.0)
13
+ rack (>= 1.0, < 3)
14
+ rake (13.0.6)
15
+ test-unit (3.5.3)
16
16
  power_assert
17
17
 
18
18
  PLATFORMS
@@ -25,4 +25,4 @@ DEPENDENCIES
25
25
  test-unit
26
26
 
27
27
  BUNDLED WITH
28
- 1.17.2
28
+ 2.3.21
data/README.md CHANGED
@@ -6,7 +6,7 @@ Installation
6
6
  Add the following to your `Gemfile`:
7
7
 
8
8
  ```
9
- gem 'rack-proxy', '~> 0.7.0'
9
+ gem 'rack-proxy', '~> 0.7.4'
10
10
  ```
11
11
 
12
12
  Or install:
@@ -136,7 +136,7 @@ Test with `require 'rack_proxy_examples/example_service_proxy'`
136
136
  # 1. rails new test_app
137
137
  # 2. cd test_app
138
138
  # 3. install Rack-Proxy in `Gemfile`
139
- # a. `gem 'rack-proxy', '~> 0.7.0'`
139
+ # a. `gem 'rack-proxy', '~> 0.7.4'`
140
140
  # 4. install gem: `bundle install`
141
141
  # 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
142
142
  # 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
@@ -1,13 +1,16 @@
1
1
  require "net_http_hacked"
2
+ require "stringio"
2
3
 
3
4
  module Rack
4
-
5
5
  # Wraps the hacked net/http in a Rack way.
6
6
  class HttpStreamingResponse
7
- attr_accessor :use_ssl
8
- attr_accessor :verify_mode
9
- attr_accessor :read_timeout
10
- attr_accessor :ssl_version
7
+ STATUSES_WITH_NO_ENTITY_BODY = {
8
+ 204 => true,
9
+ 205 => true,
10
+ 304 => true
11
+ }.freeze
12
+
13
+ attr_accessor :use_ssl, :verify_mode, :read_timeout, :ssl_version
11
14
 
12
15
  def initialize(request, host, port = nil)
13
16
  @request, @host, @port = request, host, port
@@ -18,60 +21,62 @@ module Rack
18
21
  end
19
22
 
20
23
  def code
21
- response.code.to_i
24
+ response.code.to_i.tap do |response_code|
25
+ STATUSES_WITH_NO_ENTITY_BODY[response_code] && close_connection
26
+ end
22
27
  end
23
28
  # #status is deprecated
24
29
  alias_method :status, :code
25
30
 
26
31
  def headers
27
- h = Utils::HeaderHash.new
28
-
29
- response.to_hash.each do |k, v|
30
- h[k] = v
32
+ Utils::HeaderHash.new.tap do |h|
33
+ response.to_hash.each { |k, v| h[k] = v }
31
34
  end
32
-
33
- h
34
35
  end
35
36
 
36
37
  # Can be called only once!
37
38
  def each(&block)
39
+ return if connection_closed
40
+
38
41
  response.read_body(&block)
39
42
  ensure
40
- session.end_request_hacked
41
- session.finish
43
+ close_connection
42
44
  end
43
45
 
44
46
  def to_s
45
- @body ||= begin
46
- lines = []
47
-
48
- each do |line|
49
- lines << line
50
- end
51
-
52
- lines.join
53
- end
47
+ @to_s ||= StringIO.new.tap { |io| each { |line| io << line } }.string
54
48
  end
55
49
 
56
50
  protected
57
51
 
58
52
  # Net::HTTPResponse
59
53
  def response
60
- @response ||= session.begin_request_hacked(@request)
54
+ @response ||= session.begin_request_hacked(request)
61
55
  end
62
56
 
63
57
  # Net::HTTP
64
58
  def session
65
- @session ||= begin
66
- http = Net::HTTP.new @host, @port
67
- http.use_ssl = self.use_ssl
68
- http.verify_mode = self.verify_mode
69
- http.read_timeout = self.read_timeout
70
- http.ssl_version = self.ssl_version if self.use_ssl
59
+ @session ||= Net::HTTP.new(host, port).tap do |http|
60
+ http.use_ssl = use_ssl
61
+ http.verify_mode = verify_mode
62
+ http.read_timeout = read_timeout
63
+ http.ssl_version = ssl_version if use_ssl
71
64
  http.start
72
65
  end
73
66
  end
74
67
 
75
- end
68
+ private
69
+
70
+ attr_reader :request, :host, :port
71
+
72
+ attr_accessor :connection_closed
73
+
74
+ def close_connection
75
+ return if connection_closed
76
76
 
77
+ session.end_request_hacked
78
+ session.finish
79
+ self.connection_closed = true
80
+ end
81
+ end
77
82
  end
data/lib/rack/proxy.rb CHANGED
@@ -5,7 +5,18 @@ module Rack
5
5
 
6
6
  # Subclass and bring your own #rewrite_request and #rewrite_response
7
7
  class Proxy
8
- VERSION = "0.7.0"
8
+ VERSION = "0.7.4".freeze
9
+
10
+ HOP_BY_HOP_HEADERS = {
11
+ 'connection' => true,
12
+ 'keep-alive' => true,
13
+ 'proxy-authenticate' => true,
14
+ 'proxy-authorization' => true,
15
+ 'te' => true,
16
+ 'trailer' => true,
17
+ 'transfer-encoding' => true,
18
+ 'upgrade' => true
19
+ }.freeze
9
20
 
10
21
  class << self
11
22
  def extract_http_request_headers(env)
@@ -19,14 +30,14 @@ module Rack
19
30
  hash
20
31
  end
21
32
 
22
- x_forwarded_for = (headers["X-Forwarded-For"].to_s.split(/, +/) << env["REMOTE_ADDR"]).join(", ")
33
+ x_forwarded_for = (headers['X-Forwarded-For'].to_s.split(/, +/) << env['REMOTE_ADDR']).join(', ')
23
34
 
24
- headers.merge!("X-Forwarded-For" => x_forwarded_for)
35
+ headers.merge!('X-Forwarded-For' => x_forwarded_for)
25
36
  end
26
37
 
27
38
  def normalize_headers(headers)
28
39
  mapped = headers.map do |k, v|
29
- [k, if v.is_a? Array then v.join("\n") else v end]
40
+ [titleize(k), if v.is_a? Array then v.join("\n") else v end]
30
41
  end
31
42
  Utils::HeaderHash.new Hash[mapped]
32
43
  end
@@ -34,7 +45,11 @@ module Rack
34
45
  protected
35
46
 
36
47
  def reconstruct_header_name(name)
37
- name.sub(/^HTTP_/, "").gsub("_", "-")
48
+ titleize(name.sub(/^HTTP_/, "").gsub("_", "-"))
49
+ end
50
+
51
+ def titleize(str)
52
+ str.split("-").map(&:capitalize).join("-")
38
53
  end
39
54
  end
40
55
 
@@ -49,12 +64,12 @@ module Rack
49
64
 
50
65
  @streaming = opts.fetch(:streaming, true)
51
66
  @ssl_verify_none = opts.fetch(:ssl_verify_none, false)
52
- @backend = URI(opts[:backend]) if opts[:backend]
67
+ @backend = opts[:backend] ? URI(opts[:backend]) : nil
53
68
  @read_timeout = opts.fetch(:read_timeout, 60)
54
- @ssl_version = opts[:ssl_version] if opts[:ssl_version]
69
+ @ssl_version = opts[:ssl_version]
55
70
 
56
- @username = opts[:username] if opts[:username]
57
- @password = opts[:password] if opts[:password]
71
+ @username = opts[:username]
72
+ @password = opts[:password]
58
73
 
59
74
  @opts = opts
60
75
  end
@@ -85,7 +100,7 @@ module Rack
85
100
  full_path = source_request.fullpath
86
101
  end
87
102
 
88
- target_request = Net::HTTP.const_get(source_request.request_method.capitalize).new(full_path)
103
+ target_request = Net::HTTP.const_get(source_request.request_method.capitalize, false).new(full_path)
89
104
 
90
105
  # Setup headers
91
106
  target_request.initialize_http_header(self.class.extract_http_request_headers(source_request.env))
@@ -126,16 +141,16 @@ module Rack
126
141
  end
127
142
  end
128
143
 
144
+ code = target_response.code
129
145
  headers = self.class.normalize_headers(target_response.respond_to?(:headers) ? target_response.headers : target_response.to_hash)
130
146
  body = target_response.body || [""]
131
147
  body = [body] unless body.respond_to?(:each)
132
148
 
133
149
  # According to https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-14#section-7.1.3.1Acc
134
150
  # should remove hop-by-hop header fields
135
- headers.reject! { |k| ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', 'upgrade'].include? k.downcase }
136
- [target_response.code, headers, body]
137
- end
151
+ headers.reject! { |k| HOP_BY_HOP_HEADERS[k.downcase] }
138
152
 
153
+ [code, headers, body]
154
+ end
139
155
  end
140
-
141
156
  end
@@ -5,7 +5,7 @@
5
5
  # 1. rails new test_app
6
6
  # 2. cd test_app
7
7
  # 3. install Rack-Proxy in `Gemfile`
8
- # a. `gem 'rack-proxy', '~> 0.7.0'`
8
+ # a. `gem 'rack-proxy', '~> 0.7.4'`
9
9
  # 4. install gem: `bundle install`
10
10
  # 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
11
11
  # 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
@@ -4,23 +4,24 @@ require "rack/http_streaming_response"
4
4
  class HttpStreamingResponseTest < Test::Unit::TestCase
5
5
 
6
6
  def setup
7
- host, req = "www.trix.pl", Net::HTTP::Get.new("/")
8
- @response = Rack::HttpStreamingResponse.new(req, host)
7
+ host, req = "mockapi.io", Net::HTTP::Get.new("/")
8
+ @response = Rack::HttpStreamingResponse.new(req, host, 443)
9
+ @response.use_ssl = true
9
10
  end
10
11
 
11
12
  def test_streaming
12
13
  # Response status
13
- assert @response.code == 200
14
- assert @response.status == 200
14
+ assert_equal 200, @response.status
15
+ assert_equal 200, @response.status
15
16
 
16
17
  # Headers
17
18
  headers = @response.headers
18
19
 
19
- assert headers.size > 0
20
+ assert headers.size.positive?
20
21
 
21
- assert headers["content-type"] == ["text/html;charset=utf-8"]
22
- assert headers["CoNtEnT-TyPe"] == headers["content-type"]
23
- assert headers["content-length"].first.to_i > 0
22
+ assert_match %r{text/html; ?charset=utf-8}, headers["content-type"].first.downcase
23
+ assert_equal headers["content-type"], headers["CoNtEnT-TyPe"]
24
+ assert headers["content-length"].first.to_i.positive?
24
25
 
25
26
  # Body
26
27
  chunks = []
@@ -28,7 +29,7 @@ class HttpStreamingResponseTest < Test::Unit::TestCase
28
29
  chunks << chunk
29
30
  end
30
31
 
31
- assert chunks.size > 0
32
+ assert chunks.size.positive?
32
33
  chunks.each do |chunk|
33
34
  assert chunk.is_a?(String)
34
35
  end
@@ -78,10 +78,10 @@ class RackProxyTest < Test::Unit::TestCase
78
78
  proxy_class = Rack::Proxy
79
79
 
80
80
  header = proxy_class.send(:reconstruct_header_name, "HTTP_ABC")
81
- assert header == "ABC"
81
+ assert header == "Abc"
82
82
 
83
83
  header = proxy_class.send(:reconstruct_header_name, "HTTP_ABC_D")
84
- assert header == "ABC-D"
84
+ assert header == "Abc-D"
85
85
  end
86
86
 
87
87
  def test_extract_http_request_headers
@@ -120,7 +120,7 @@ class RackProxyTest < Test::Unit::TestCase
120
120
  end
121
121
 
122
122
  def test_response_header_included_Hop_by_hop
123
- app({:streaming => true}).host = 'auth.goeasyship.com'
123
+ app({:streaming => true}).host = 'mockapi.io'
124
124
  get 'https://example.com/oauth2/token/info?access_token=123'
125
125
  assert !last_response.headers.key?('transfer-encoding')
126
126
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacek Becela
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-28 00:00:00.000000000 Z
11
+ date: 2022-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -60,6 +60,7 @@ executables: []
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
+ - ".github/FUNDING.yml"
63
64
  - ".gitignore"
64
65
  - ".travis.yml"
65
66
  - Gemfile