rack-proxy 0.6.5 → 0.7.7

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
- SHA1:
3
- metadata.gz: 7613a66b731bfac2c3f24a961757f359894ebdce
4
- data.tar.gz: f69050ff757d137cebc48c7afcf385661e703d33
2
+ SHA256:
3
+ metadata.gz: 888784aa8d1d28ae0dc2a1352aa44ba8e639d5cd604043facbb31da3fa1dc759
4
+ data.tar.gz: 9ba49effcffcacb930ab08fe2f6a9fd08040b60800b8aa8e5ccc274053f36c4e
5
5
  SHA512:
6
- metadata.gz: 9085c724256f803ecd1d232c41ef1811c560b4600759af715e44bbd06ab343f239a5c4db7c3da6c2ede58f8089bfdd00f76cda3f509f7e65ba99e5f6d4450c68
7
- data.tar.gz: e158ad03e8ff6f415d39f12759659f0148d2463d85f9734b73000401ac20b395ab7226f2cc49a5db0c69e8175f807823a9d1502a151b1aeddaaf970049190ba4
6
+ metadata.gz: 606ed720fb5b8c67cd1fc3058b9644e88fb2e7768d4fce4606ba0332fac24cadca11a36ab50d97cb7ff5767664864b1c1a2cf5108cd58a66fecfb3b93de37517
7
+ data.tar.gz: a91cc8541d7af6c390fe1c0faa3c923942a14cce746eebc3d170b95b45aafc5871a04ad1ec9fee6f0c07500534755c794f76d0c14bccdcf5fdaad06e239aeb07
@@ -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 CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  gem 'rake'
4
4
 
data/Gemfile.lock CHANGED
@@ -1,22 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-proxy (0.6.5)
4
+ rack-proxy (0.7.7)
5
5
  rack
6
6
 
7
7
  GEM
8
- remote: http://rubygems.org/
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 (0.9.2.2)
15
- test-unit (3.1.5)
10
+ power_assert (2.0.3)
11
+ rack (3.0.8)
12
+ rack-test (2.1.0)
13
+ rack (>= 1.3)
14
+ rake (13.0.6)
15
+ test-unit (3.6.1)
16
16
  power_assert
17
17
 
18
18
  PLATFORMS
19
- ruby
19
+ arm64-darwin-22
20
20
 
21
21
  DEPENDENCIES
22
22
  rack-proxy!
@@ -25,4 +25,4 @@ DEPENDENCIES
25
25
  test-unit
26
26
 
27
27
  BUNDLED WITH
28
- 1.16.0
28
+ 2.4.17
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.6.4'
9
+ gem 'rack-proxy', '~> 0.7.7'
10
10
  ```
11
11
 
12
12
  Or install:
@@ -17,7 +17,8 @@ gem install rack-proxy
17
17
 
18
18
  Use Cases
19
19
  ----
20
- Below are some examples of real world use cases for Rack-Proxy, done something interesting add the list below and send a PR.
20
+
21
+ Below are some examples of real world use cases for Rack-Proxy. If you have done something interesting, add it to the list below and send a PR.
21
22
 
22
23
  * Allowing one app to act as central trust authority
23
24
  * handle accepting self-sign certificates for internal apps
@@ -25,7 +26,7 @@ Below are some examples of real world use cases for Rack-Proxy, done something i
25
26
  * avoiding CORs complications by proxying from same domain to another backend
26
27
  * subdomain based pass-through to multiple apps
27
28
  * Complex redirect rules
28
- * redirect pages with different extensions (ex: `.php`) to another app
29
+ * redirect pages with different extensions (ex: `.php`) to another app
29
30
  * useful for handling awkward redirection rules for moved pages
30
31
  * fan Parallel Requests: turning a single API request to [multiple concurrent backend requests](https://github.com/typhoeus/typhoeus#making-parallel-requests) & merging results.
31
32
  * inserting or stripping headers required or problematic for certain clients
@@ -76,7 +77,7 @@ class ForwardHost < Rack::Proxy
76
77
 
77
78
  # example of inserting an additional header
78
79
  headers["X-Foo"] = "Bar"
79
-
80
+
80
81
  # if you rewrite env, it appears that content-length isn't calculated correctly
81
82
  # resulting in only partial responses being sent to users
82
83
  # you can remove it or recalculate it here
@@ -98,14 +99,14 @@ class TrustingProxy < Rack::Proxy
98
99
  def rewrite_env(env)
99
100
  env["HTTP_HOST"] = "self-signed.badssl.com"
100
101
 
101
- # We are going to trust the self-signed SSL
102
+ # We are going to trust the self-signed SSL
102
103
  env["rack.ssl_verify_none"] = true
103
104
  env
104
105
  end
105
106
 
106
107
  def rewrite_response(triplet)
107
108
  status, headers, body = triplet
108
-
109
+
109
110
  # if you rewrite env, it appears that content-length isn't calculated correctly
110
111
  # resulting in only partial responses being sent to users
111
112
  # you can remove it or recalculate it here
@@ -130,12 +131,12 @@ Test with `require 'rack_proxy_examples/example_service_proxy'`
130
131
  ```ruby
131
132
  ###
132
133
  # This is an example of how to use Rack-Proxy in a Rails application.
133
- #
134
+ #
134
135
  # Setup:
135
- # 1. rails new test_app
136
+ # 1. rails new test_app
136
137
  # 2. cd test_app
137
138
  # 3. install Rack-Proxy in `Gemfile`
138
- # a. `gem 'rack-proxy', '~> 0.6.3'`
139
+ # a. `gem 'rack-proxy', '~> 0.7.7'`
139
140
  # 4. install gem: `bundle install`
140
141
  # 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
141
142
  # 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
@@ -157,7 +158,7 @@ class ExampleServiceProxy < Rack::Proxy
157
158
 
158
159
  # This is the only path that needs to be set currently on Rails 5 & greater
159
160
  env['PATH_INFO'] = ENV['SERVICE_PATH'] || '/configuring.html'
160
-
161
+
161
162
  # don't send your sites cookies to target service, unless it is a trusted internal service that can parse all your cookies
162
163
  env['HTTP_COOKIE'] = ''
163
164
  super(env)
@@ -185,14 +186,14 @@ class RackPhpProxy < Rack::Proxy
185
186
  if request.path =~ %r{\.php}
186
187
  env["HTTP_HOST"] = ENV["HTTP_HOST"] ? URI(ENV["HTTP_HOST"]).host : "localhost"
187
188
  ENV["PHP_PATH"] ||= '/manual/en/tutorial.firstpage.php'
188
-
189
+
189
190
  # Rails 3 & 4
190
191
  env["REQUEST_PATH"] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
191
192
  # Rails 5 and above
192
193
  env['PATH_INFO'] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
193
194
 
194
195
  env['content-length'] = nil
195
-
196
+
196
197
  super(env)
197
198
  else
198
199
  @app.call(env)
@@ -201,7 +202,7 @@ class RackPhpProxy < Rack::Proxy
201
202
 
202
203
  def rewrite_response(triplet)
203
204
  status, headers, body = triplet
204
-
205
+
205
206
  # if you proxy depending on the backend, it appears that content-length isn't calculated correctly
206
207
  # resulting in only partial responses being sent to users
207
208
  # you can remove it or recalculate it here
@@ -232,6 +233,100 @@ This will allow to run the other requests through the application and only proxy
232
233
 
233
234
  See tests for more examples.
234
235
 
236
+ ### SSL proxy for SpringBoot applications debugging
237
+
238
+ Whenever you need to debug communication with external services with HTTPS protocol (like OAuth based) you have to be able to access to your local web app through HTTPS protocol too. Typical way is to use nginx or Apache httpd as a reverse proxy but it might be inconvinuent for development environment. Simple proxy server is a better way in this case. The only what we need is to unpack incoming SSL queries and proxy them to a backend. We can prepare minimal set of files to create autonomous proxy server.
239
+
240
+ Create `config.ru` file:
241
+ ```ruby
242
+ #
243
+ # config.ru
244
+ #
245
+ require 'rack'
246
+ require 'rack-proxy'
247
+
248
+ class ForwardHost < Rack::Proxy
249
+ def rewrite_env(env)
250
+ env['HTTP_X_FORWARDED_HOST'] = env['SERVER_NAME']
251
+ env['HTTP_X_FORWARDED_PROTO'] = env['rack.url_scheme']
252
+ env
253
+ end
254
+ end
255
+
256
+ run ForwardHost.new(backend: 'http://localhost:8080')
257
+ ```
258
+
259
+ Create `Gemfile` file:
260
+ ```ruby
261
+ source "https://rubygems.org"
262
+
263
+ gem 'thin'
264
+ gem 'rake'
265
+ gem 'rack-proxy'
266
+ ```
267
+
268
+ Create `config.yml` file with configuration of web server `thin`:
269
+ ```yml
270
+ ---
271
+ ssl: true
272
+ ssl-key-file: keys/domain.key
273
+ ssl-cert-file: keys/domain.crt
274
+ ssl-disable-verify: false
275
+ ```
276
+
277
+ Create 'keys' directory and generate SSL key and certificates files `domain.key` and `domain.crt`
278
+
279
+ Run `bundle exec thin start` for running it with `thin`'s default port.
280
+
281
+ Or use `sudo -E thin start -C config.yml -p 443` for running with default for `https://` port.
282
+
283
+ Don't forget to enable processing of `X-Forwarded-...` headers on your application side. Just add following strings to your `resources/application.yml` file.
284
+ ```yml
285
+ ---
286
+ server:
287
+ tomcat:
288
+ remote-ip-header: x-forwarded-for
289
+ protocol-header: x-forwarded-proto
290
+ use-forward-headers: true
291
+ ```
292
+
293
+ Add some domain name like `debug.your_app.com` into your local `/etc/hosts` file like
294
+ ```
295
+ 127.0.0.1 debug.your_app.com
296
+ ```
297
+
298
+ Next start the proxy and your app. And now you can access to your Spring application through SSL connection via `https://debug.your_app.com` URI in a browser.
299
+
300
+ ### Using SSL/TLS certificates with HTTP connection
301
+ This may be helpful, when third-party API has authentication by client TLS certificates and you need to proxy your requests and sign them with certificate.
302
+
303
+ Just specify Rack::Proxy SSL options and your request will use TLS HTTP connection:
304
+ ```ruby
305
+ # config.ru
306
+ . . .
307
+
308
+ cert_raw = File.read('./certs/rootCA.crt')
309
+ key_raw = File.read('./certs/key.pem')
310
+
311
+ cert = OpenSSL::X509::Certificate.new(cert_raw)
312
+ key = OpenSSL::PKey.read(key_raw)
313
+
314
+ use TLSProxy, cert: cert, key: key, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER, ssl_version: 'TLSv1_2'
315
+ ```
316
+
317
+ And rewrite host for example:
318
+ ```ruby
319
+ # tls_proxy.rb
320
+ class TLSProxy < Rack::Proxy
321
+ attr_accessor :original_request, :query_params
322
+
323
+ def rewrite_env(env)
324
+ env["HTTP_HOST"] = "client-tls-auth-api.com:443"
325
+ env
326
+ end
327
+ end
328
+ ```
329
+
235
330
  WARNING
236
331
  ----
237
332
 
@@ -242,4 +337,4 @@ Todos
242
337
 
243
338
  * Make the docs up to date with the current use case for this code: everything except streaming which involved a rather ugly monkey patch and only worked in 1.8, but does not work now.
244
339
  * Improve and validate requirements for Host and Path rewrite rules
245
- * Ability to inject logger and set log level
340
+ * Ability to inject logger and set log level
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # [status, headers, streamable_body]
6
6
  #
7
- # See http://github.com/aniero/rack-streaming-proxy
7
+ # See http://github.com/zerowidth/rack-streaming-proxy
8
8
  # for alternative that uses additional process.
9
9
  #
10
10
  # BTW I don't like monkey patching either
@@ -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, :cert, :key
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
31
- end
32
-
33
- h
32
+ Rack::Proxy.build_header_hash(response.to_hash)
34
33
  end
35
34
 
36
35
  # Can be called only once!
37
36
  def each(&block)
37
+ return if connection_closed
38
+
38
39
  response.read_body(&block)
39
40
  ensure
40
- session.end_request_hacked
41
- session.finish
41
+ close_connection
42
42
  end
43
43
 
44
44
  def to_s
45
- @body ||= begin
46
- lines = []
47
-
48
- each do |line|
49
- lines << line
50
- end
51
-
52
- lines.join
53
- end
45
+ @to_s ||= StringIO.new.tap { |io| each { |line| io << line } }.string
54
46
  end
55
47
 
56
48
  protected
57
49
 
58
50
  # Net::HTTPResponse
59
51
  def response
60
- @response ||= session.begin_request_hacked(@request)
52
+ @response ||= session.begin_request_hacked(request)
61
53
  end
62
54
 
63
55
  # Net::HTTP
64
56
  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
57
+ @session ||= Net::HTTP.new(host, port).tap do |http|
58
+ http.use_ssl = use_ssl
59
+ http.verify_mode = verify_mode
60
+ http.read_timeout = read_timeout
61
+ http.ssl_version = ssl_version if ssl_version
62
+ http.cert = cert if cert
63
+ http.key = key if key
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
76
73
 
74
+ def close_connection
75
+ return if connection_closed
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,36 +5,57 @@ module Rack
5
5
 
6
6
  # Subclass and bring your own #rewrite_request and #rewrite_response
7
7
  class Proxy
8
- VERSION = "0.6.5"
8
+ VERSION = "0.7.7".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)
12
23
  headers = env.reject do |k, v|
13
- !(/^HTTP_[A-Z0-9_]+$/ === k) || v.nil?
24
+ !(/^HTTP_[A-Z0-9_\.]+$/ === k) || v.nil?
14
25
  end.map do |k, v|
15
26
  [reconstruct_header_name(k), v]
16
- end.inject(Utils::HeaderHash.new) do |hash, k_v|
17
- k, v = k_v
18
- hash[k] = v
19
- hash
20
- end
27
+ end.then { |pairs| build_header_hash(pairs) }
21
28
 
22
- x_forwarded_for = (headers["X-Forwarded-For"].to_s.split(/, +/) << env["REMOTE_ADDR"]).join(", ")
29
+ x_forwarded_for = (headers['X-Forwarded-For'].to_s.split(/, +/) << env['REMOTE_ADDR']).join(', ')
23
30
 
24
- headers.merge!("X-Forwarded-For" => x_forwarded_for)
31
+ headers.merge!('X-Forwarded-For' => x_forwarded_for)
25
32
  end
26
33
 
27
34
  def normalize_headers(headers)
28
35
  mapped = headers.map do |k, v|
29
- [k, if v.is_a? Array then v.join("\n") else v end]
36
+ [titleize(k), if v.is_a? Array then v.join("\n") else v end]
37
+ end
38
+ build_header_hash Hash[mapped]
39
+ end
40
+
41
+ def build_header_hash(pairs)
42
+ if Rack.const_defined?(:Headers)
43
+ # Rack::Headers is only available from Rack 3 onward
44
+ Headers.new.tap { |headers| pairs.each { |k, v| headers[k] = v } }
45
+ else
46
+ # Rack::Utils::HeaderHash is deprecated from Rack 3 onward and is to be removed in 3.1
47
+ Utils::HeaderHash.new(pairs)
30
48
  end
31
- Utils::HeaderHash.new Hash[mapped]
32
49
  end
33
50
 
34
51
  protected
35
52
 
36
53
  def reconstruct_header_name(name)
37
- name.sub(/^HTTP_/, "").gsub("_", "-")
54
+ titleize(name.sub(/^HTTP_/, "").gsub("_", "-"))
55
+ end
56
+
57
+ def titleize(str)
58
+ str.split("-").map(&:capitalize).join("-")
38
59
  end
39
60
  end
40
61
 
@@ -46,11 +67,20 @@ module Rack
46
67
  else
47
68
  @app = app
48
69
  end
70
+
49
71
  @streaming = opts.fetch(:streaming, true)
50
72
  @ssl_verify_none = opts.fetch(:ssl_verify_none, false)
51
- @backend = URI(opts[:backend]) if opts[:backend]
73
+ @backend = opts[:backend] ? URI(opts[:backend]) : nil
52
74
  @read_timeout = opts.fetch(:read_timeout, 60)
53
- @ssl_version = opts[:ssl_version] if opts[:ssl_version]
75
+ @ssl_version = opts[:ssl_version]
76
+ @cert = opts[:cert]
77
+ @key = opts[:key]
78
+ @verify_mode = opts[:verify_mode]
79
+
80
+ @username = opts[:username]
81
+ @password = opts[:password]
82
+
83
+ @opts = opts
54
84
  end
55
85
 
56
86
  def call(env)
@@ -79,7 +109,7 @@ module Rack
79
109
  full_path = source_request.fullpath
80
110
  end
81
111
 
82
- target_request = Net::HTTP.const_get(source_request.request_method.capitalize).new(full_path)
112
+ target_request = Net::HTTP.const_get(source_request.request_method.capitalize, false).new(full_path)
83
113
 
84
114
  # Setup headers
85
115
  target_request.initialize_http_header(self.class.extract_http_request_headers(source_request.env))
@@ -92,9 +122,11 @@ module Rack
92
122
  target_request.body_stream.rewind
93
123
  end
94
124
 
125
+ # Use basic auth if we have to
126
+ target_request.basic_auth(@username, @password) if @username && @password
127
+
95
128
  backend = env.delete('rack.backend') || @backend || source_request
96
- use_ssl = backend.scheme == "https"
97
- ssl_verify_none = (env.delete('rack.ssl_verify_none') || @ssl_verify_none) == true
129
+ use_ssl = backend.scheme == "https" || @cert
98
130
  read_timeout = env.delete('http.read_timeout') || @read_timeout
99
131
 
100
132
  # Create the response
@@ -103,30 +135,34 @@ module Rack
103
135
  target_response = HttpStreamingResponse.new(target_request, backend.host, backend.port)
104
136
  target_response.use_ssl = use_ssl
105
137
  target_response.read_timeout = read_timeout
106
- target_response.verify_mode = OpenSSL::SSL::VERIFY_NONE if use_ssl && ssl_verify_none
107
138
  target_response.ssl_version = @ssl_version if @ssl_version
139
+ target_response.verify_mode = (@verify_mode || OpenSSL::SSL::VERIFY_NONE) if use_ssl
140
+ target_response.cert = @cert if @cert
141
+ target_response.key = @key if @key
108
142
  else
109
143
  http = Net::HTTP.new(backend.host, backend.port)
110
144
  http.use_ssl = use_ssl if use_ssl
111
145
  http.read_timeout = read_timeout
112
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE if use_ssl && ssl_verify_none
113
146
  http.ssl_version = @ssl_version if @ssl_version
147
+ http.verify_mode = (@verify_mode || OpenSSL::SSL::VERIFY_NONE if use_ssl) if use_ssl
148
+ http.cert = @cert if @cert
149
+ http.key = @key if @key
114
150
 
115
151
  target_response = http.start do
116
152
  http.request(target_request)
117
153
  end
118
154
  end
119
155
 
156
+ code = target_response.code
120
157
  headers = self.class.normalize_headers(target_response.respond_to?(:headers) ? target_response.headers : target_response.to_hash)
121
158
  body = target_response.body || [""]
122
159
  body = [body] unless body.respond_to?(:each)
123
160
 
124
161
  # According to https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-14#section-7.1.3.1Acc
125
162
  # should remove hop-by-hop header fields
126
- headers.reject! { |k| ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', 'upgrade'].include? k.downcase }
127
- [target_response.code, headers, body]
128
- end
163
+ headers.reject! { |k| HOP_BY_HOP_HEADERS[k.downcase] }
129
164
 
165
+ [code, headers, body]
166
+ end
130
167
  end
131
-
132
168
  end
@@ -1,11 +1,11 @@
1
1
  ###
2
2
  # This is an example of how to use Rack-Proxy in a Rails application.
3
- #
3
+ #
4
4
  # Setup:
5
- # 1. rails new test_app
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.6.3'`
8
+ # a. `gem 'rack-proxy', '~> 0.7.7'`
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`
@@ -27,7 +27,7 @@ class ExampleServiceProxy < Rack::Proxy
27
27
 
28
28
  # This is the only path that needs to be set currently on Rails 5 & greater
29
29
  env['PATH_INFO'] = ENV['SERVICE_PATH'] || '/configuring.html'
30
-
30
+
31
31
  # don't send your sites cookies to target service, unless it is a trusted internal service that can parse all your cookies
32
32
  env['HTTP_COOKIE'] = ''
33
33
  super(env)
data/rack-proxy.gemspec CHANGED
@@ -6,13 +6,13 @@ Gem::Specification.new do |s|
6
6
  s.name = "rack-proxy"
7
7
  s.version = Rack::Proxy::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
+ s.license = 'MIT'
9
10
  s.authors = ["Jacek Becela"]
10
11
  s.email = ["jacek.becela@gmail.com"]
11
12
  s.homepage = "https://github.com/ncr/rack-proxy"
12
13
  s.summary = %q{A request/response rewriting HTTP proxy. A Rack app.}
13
14
  s.description = %q{A Rack app that provides request/response rewriting proxy capabilities with streaming.}
14
-
15
- s.rubyforge_project = "rack-proxy"
15
+ s.required_ruby_version = '>= 2.6'
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -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 = "example.com", 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
@@ -36,7 +37,7 @@ class HttpStreamingResponseTest < Test::Unit::TestCase
36
37
  end
37
38
 
38
39
  def test_to_s
39
- assert_equal @response.headers["Content-Length"].first.to_i, @response.body.to_s.size
40
+ assert_equal @response.headers["Content-Length"].first.to_i, @response.body.to_s.bytesize
40
41
  end
41
42
 
42
43
  def test_to_s_called_twice
@@ -6,7 +6,7 @@ class RackProxyTest < Test::Unit::TestCase
6
6
  attr_accessor :host
7
7
 
8
8
  def rewrite_env(env)
9
- env["HTTP_HOST"] = self.host || 'www.trix.pl'
9
+ env["HTTP_HOST"] = self.host || 'example.com'
10
10
  env
11
11
  end
12
12
  end
@@ -18,14 +18,15 @@ class RackProxyTest < Test::Unit::TestCase
18
18
  def test_http_streaming
19
19
  get "/"
20
20
  assert last_response.ok?
21
- assert_match(/Jacek Becela/, last_response.body)
21
+
22
+ assert_match(/Example Domain/, last_response.body)
22
23
  end
23
24
 
24
25
  def test_http_full_request
25
26
  app(:streaming => false)
26
27
  get "/"
27
28
  assert last_response.ok?
28
- assert_match(/Jacek Becela/, last_response.body)
29
+ assert_match(/Example Domain/, last_response.body)
29
30
  end
30
31
 
31
32
  def test_http_full_request_headers
@@ -77,10 +78,10 @@ class RackProxyTest < Test::Unit::TestCase
77
78
  proxy_class = Rack::Proxy
78
79
 
79
80
  header = proxy_class.send(:reconstruct_header_name, "HTTP_ABC")
80
- assert header == "ABC"
81
+ assert header == "Abc"
81
82
 
82
83
  header = proxy_class.send(:reconstruct_header_name, "HTTP_ABC_D")
83
- assert header == "ABC-D"
84
+ assert header == "Abc-D"
84
85
  end
85
86
 
86
87
  def test_extract_http_request_headers
@@ -89,12 +90,14 @@ class RackProxyTest < Test::Unit::TestCase
89
90
  'NOT-HTTP-HEADER' => 'test-value',
90
91
  'HTTP_ACCEPT' => 'text/html',
91
92
  'HTTP_CONNECTION' => nil,
92
- 'HTTP_CONTENT_MD5' => 'deadbeef'
93
+ 'HTTP_CONTENT_MD5' => 'deadbeef',
94
+ 'HTTP_HEADER.WITH.PERIODS' => 'stillmooing'
93
95
  }
94
96
 
95
97
  headers = proxy_class.extract_http_request_headers(env)
96
98
  assert headers.key?('ACCEPT')
97
99
  assert headers.key?('CONTENT-MD5')
100
+ assert headers.key?('HEADER.WITH.PERIODS')
98
101
  assert !headers.key?('CONNECTION')
99
102
  assert !headers.key?('NOT-HTTP-HEADER')
100
103
  end
@@ -117,7 +120,7 @@ class RackProxyTest < Test::Unit::TestCase
117
120
  end
118
121
 
119
122
  def test_response_header_included_Hop_by_hop
120
- app({:streaming => true}).host = 'auth.goeasyship.com'
123
+ app({:streaming => true}).host = 'mockapi.io'
121
124
  get 'https://example.com/oauth2/token/info?access_token=123'
122
125
  assert !last_response.headers.key?('transfer-encoding')
123
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.6.5
4
+ version: 0.7.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacek Becela
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-17 00:00:00.000000000 Z
11
+ date: 2023-09-01 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
@@ -81,9 +82,10 @@ files:
81
82
  - test/rack_proxy_test.rb
82
83
  - test/test_helper.rb
83
84
  homepage: https://github.com/ncr/rack-proxy
84
- licenses: []
85
+ licenses:
86
+ - MIT
85
87
  metadata: {}
86
- post_install_message:
88
+ post_install_message:
87
89
  rdoc_options: []
88
90
  require_paths:
89
91
  - lib
@@ -91,16 +93,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
93
  requirements:
92
94
  - - ">="
93
95
  - !ruby/object:Gem::Version
94
- version: '0'
96
+ version: '2.6'
95
97
  required_rubygems_version: !ruby/object:Gem::Requirement
96
98
  requirements:
97
99
  - - ">="
98
100
  - !ruby/object:Gem::Version
99
101
  version: '0'
100
102
  requirements: []
101
- rubyforge_project: rack-proxy
102
- rubygems_version: 2.6.13
103
- signing_key:
103
+ rubygems_version: 3.2.3
104
+ signing_key:
104
105
  specification_version: 4
105
106
  summary: A request/response rewriting HTTP proxy. A Rack app.
106
107
  test_files: