rack-proxy 0.6.3 → 0.6.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
  SHA1:
3
- metadata.gz: 7cd49adb5cd0843a5467ecf9cacc3a5d7f3c903d
4
- data.tar.gz: 64cc29bbc91ee24fbe14e200b3b69b5e8b2c0e71
3
+ metadata.gz: ce99adfb07beb9e42b72e91bd39860d2ec1efb7b
4
+ data.tar.gz: dfb0ede7fc70291ba58a24c7a478691f2fa5558f
5
5
  SHA512:
6
- metadata.gz: 2986ff1e4178e92f172cdedcd38a8f7617f7d532018c1d687edecfe0bd694583a4ba409620c875b86b4d836a0e9926be078fd8aa99052c724b4fdb9f2468a774
7
- data.tar.gz: 0915046fbf017fee515398ca66f78515a4fcfa551f95a6c9134cceebf54e310040f0cfce2d325e75f8e95e0d386647a98cf61247396d321a98d56ff1f133f120
6
+ metadata.gz: 602c219b1b8151a7b77f1e6751d0919cc320cc13c6b0c0ce2f4c2a7c16dca345688ad3b3a4a109480660856a0ee7125ec36d892c97a22fb92a973e8b0a7bc005
7
+ data.tar.gz: 897c3d1db3ab71a70ce88bb9437b4a7be25cae6db20b2601f20e227b558a4a6b02416997dad68b03a7d38d0d6948bca74d3739fabfd877c0876043ea42a34dc6
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-proxy (0.6.2)
4
+ rack-proxy (0.6.4)
5
5
  rack
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  A request/response rewriting HTTP proxy. A Rack app. Subclass `Rack::Proxy` and provide your `rewrite_env` and `rewrite_response` methods.
2
2
 
3
3
  Installation
4
- -------
4
+ ----
5
5
 
6
- Add the following to your Gemfile:
6
+ Add the following to your `Gemfile`:
7
7
 
8
8
  ```
9
- gem 'rack-proxy', '~> 0.6.3'
9
+ gem 'rack-proxy', '~> 0.6.4'
10
10
  ```
11
11
 
12
12
  Or install:
@@ -15,22 +15,72 @@ Or install:
15
15
  gem install rack-proxy
16
16
  ```
17
17
 
18
- Example
19
- -------
18
+ Use Cases
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.
21
+
22
+ * Allowing one app to act as central trust authority
23
+ * handle accepting self-sign certificates for internal apps
24
+ * authentication / authorization prior to proxying requests to a blindly trusting backend
25
+ * avoiding CORs complications by proxying from same domain to another backend
26
+ * subdomain based pass-through to multiple apps
27
+ * Complex redirect rules
28
+ * redirect pages with different extensions (ex: `.php`) to another app
29
+ * useful for handling awkward redirection rules for moved pages
30
+ * fan Parallel Requests: turning a single API request to [multiple concurrent backend requests](https://github.com/typhoeus/typhoeus#making-parallel-requests) & merging results.
31
+ * inserting or stripping headers required or problematic for certain clients
32
+
33
+ Options
34
+ ----
35
+
36
+ Options can be set when initializing the middleware or overriding a method.
37
+
38
+
39
+ * `:streaming` - defaults to `true`, but does not work on all Ruby versions, recommend to set to `false`
40
+ * `:ssl_verify_none` - tell `Net::HTTP` to not validate certs
41
+ * `:ssl_version` - tell `Net::HTTP` to set a specific `ssl_version`
42
+ * `: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.
43
+ * `:read_timeout` - set proxy timeout it defaults to 60 seconds
44
+
45
+ To pass in options, when you configure your middleware you can pass them in as an optional hash.
20
46
 
21
47
  ```ruby
22
- class Foo < Rack::Proxy
48
+ Rails.application.config.middleware.use ExampleServiceProxy, backend: 'http://guides.rubyonrails.org', streaming: false
49
+ ```
50
+
51
+ Examples
52
+ ----
53
+
54
+ See and run the examples below from `lib/rack_proxy_examples/`. To mount any example into an existing Rails app:
55
+
56
+ 1. create `config/initializers/proxy.rb`
57
+ 2. modify the file to require the example file
58
+ ```ruby
59
+ require 'rack_proxy_examples/forward_host'
60
+ ```
61
+
62
+ ### Forward request to Host and Insert Header
63
+
64
+ Test with `require 'rack_proxy_examples/forward_host'`
65
+
66
+ ```ruby
67
+ class ForwardHost < Rack::Proxy
23
68
 
24
69
  def rewrite_env(env)
25
70
  env["HTTP_HOST"] = "example.com"
26
-
27
71
  env
28
72
  end
29
73
 
30
74
  def rewrite_response(triplet)
31
75
  status, headers, body = triplet
32
76
 
77
+ # example of inserting an additional header
33
78
  headers["X-Foo"] = "Bar"
79
+
80
+ # if you rewrite env, it appears that content-length isn't calculated correctly
81
+ # resulting in only partial responses being sent to users
82
+ # you can remove it or recalculate it here
83
+ headers["content-length"] = nil
34
84
 
35
85
  triplet
36
86
  end
@@ -40,15 +90,30 @@ end
40
90
 
41
91
  ### Disable SSL session verification when proxying a server with e.g. self-signed SSL certs
42
92
 
93
+ Test with `require 'rack_proxy_examples/trusting_proxy'`
94
+
43
95
  ```ruby
44
96
  class TrustingProxy < Rack::Proxy
45
97
 
46
98
  def rewrite_env(env)
47
- env["rack.ssl_verify_none"] = true
99
+ env["HTTP_HOST"] = "self-signed.badssl.com"
48
100
 
101
+ # We are going to trust the self-signed SSL
102
+ env["rack.ssl_verify_none"] = true
49
103
  env
50
104
  end
51
105
 
106
+ def rewrite_response(triplet)
107
+ status, headers, body = triplet
108
+
109
+ # if you rewrite env, it appears that content-length isn't calculated correctly
110
+ # resulting in only partial responses being sent to users
111
+ # you can remove it or recalculate it here
112
+ headers["content-length"] = nil
113
+
114
+ triplet
115
+ end
116
+
52
117
  end
53
118
  ```
54
119
 
@@ -58,31 +123,98 @@ The same can be achieved for *all* requests going through the `Rack::Proxy` inst
58
123
  Rack::Proxy.new(ssl_verify_none: true)
59
124
  ```
60
125
 
61
- Using it as a middleware:
62
- -------------------------
126
+ ### Rails middleware example
127
+
128
+ Test with `require 'rack_proxy_examples/example_service_proxy'`
129
+
130
+ ```ruby
131
+ ###
132
+ # This is an example of how to use Rack-Proxy in a Rails application.
133
+ #
134
+ # Setup:
135
+ # 1. rails new test_app
136
+ # 2. cd test_app
137
+ # 3. install Rack-Proxy in `Gemfile`
138
+ # a. `gem 'rack-proxy', '~> 0.6.3'`
139
+ # 4. install gem: `bundle install`
140
+ # 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
141
+ # 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
142
+ # 7. open in browser: `http://localhost:3000/example_service`
143
+ #
144
+ ###
145
+ ENV['SERVICE_URL'] ||= 'http://guides.rubyonrails.org'
146
+
147
+ class ExampleServiceProxy < Rack::Proxy
148
+ def perform_request(env)
149
+ request = Rack::Request.new(env)
150
+
151
+ # use rack proxy for anything hitting our host app at /example_service
152
+ if request.path =~ %r{^/example_service}
153
+ backend = URI(ENV['SERVICE_URL'])
154
+ # most backends required host set properly, but rack-proxy doesn't set this for you automatically
155
+ # even when a backend host is passed in via the options
156
+ env["HTTP_HOST"] = backend.host
157
+
158
+ # This is the only path that needs to be set currently on Rails 5 & greater
159
+ env['PATH_INFO'] = ENV['SERVICE_PATH'] || '/configuring.html'
160
+
161
+ # don't send your sites cookies to target service, unless it is a trusted internal service that can parse all your cookies
162
+ env['HTTP_COOKIE'] = ''
163
+ super(env)
164
+ else
165
+ @app.call(env)
166
+ end
167
+ end
168
+ end
169
+ ```
170
+
171
+ ### Using as middleware to forward only some extensions to another Application
172
+
173
+ Test with `require 'rack_proxy_examples/rack_php_proxy'`
63
174
 
64
175
  Example: Proxying only requests that end with ".php" could be done like this:
65
176
 
66
177
  ```ruby
67
- require 'rack/proxy'
178
+ ###
179
+ # Open http://localhost:3000/test.php to trigger proxy
180
+ ###
68
181
  class RackPhpProxy < Rack::Proxy
69
182
 
70
183
  def perform_request(env)
71
184
  request = Rack::Request.new(env)
72
185
  if request.path =~ %r{\.php}
73
- env["HTTP_HOST"] = "localhost"
74
- env["REQUEST_PATH"] = "/php/#{request.fullpath}"
186
+ env["HTTP_HOST"] = ENV["HTTP_HOST"] ? URI(ENV["HTTP_HOST"]).host : "localhost"
187
+ ENV["PHP_PATH"] ||= '/manual/en/tutorial.firstpage.php'
188
+
189
+ # Rails 3 & 4
190
+ env["REQUEST_PATH"] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
191
+ # Rails 5 and above
192
+ env['PATH_INFO'] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
193
+
194
+ env['content-length'] = nil
195
+
75
196
  super(env)
76
197
  else
77
198
  @app.call(env)
78
199
  end
79
200
  end
201
+
202
+ def rewrite_response(triplet)
203
+ status, headers, body = triplet
204
+
205
+ # if you proxy depending on the backend, it appears that content-length isn't calculated correctly
206
+ # resulting in only partial responses being sent to users
207
+ # you can remove it or recalculate it here
208
+ headers["content-length"] = nil
209
+
210
+ triplet
211
+ end
80
212
  end
81
213
  ```
82
214
 
83
215
  To use the middleware, please consider the following:
84
216
 
85
- 1) For Rails we could add a configuration in config/application.rb
217
+ 1) For Rails we could add a configuration in `config/application.rb`
86
218
 
87
219
  ```ruby
88
220
  config.middleware.use RackPhpProxy, {ssl_verify_none: true}
@@ -101,11 +233,13 @@ This will allow to run the other requests through the application and only proxy
101
233
  See tests for more examples.
102
234
 
103
235
  WARNING
104
- -------
236
+ ----
105
237
 
106
- Doesn't work with fakeweb/webmock. Both libraries monkey-patch net/http code.
238
+ Doesn't work with `fakeweb`/`webmock`. Both libraries monkey-patch net/http code.
107
239
 
108
240
  Todos
109
- -----
241
+ ----
110
242
 
111
- - 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.
243
+ * 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
+ * Improve and validate requirements for Host and Path rewrite rules
245
+ * Ability to inject logger and set log level
@@ -4,11 +4,11 @@
4
4
  #
5
5
  # [status, headers, streamable_body]
6
6
  #
7
- # See http://github.com/aniero/rack-streaming-proxy
7
+ # See http://github.com/aniero/rack-streaming-proxy
8
8
  # for alternative that uses additional process.
9
9
  #
10
10
  # BTW I don't like monkey patching either
11
- # but this is not real monkey patching.
11
+ # but this is not real monkey patching.
12
12
  # I just added some methods and named them very uniquely
13
13
  # to avoid eventual conflicts. You're safe. Trust me.
14
14
  #
@@ -45,7 +45,7 @@ class Net::HTTP
45
45
  #
46
46
  # res
47
47
  # end
48
-
48
+
49
49
  def begin_request_hacked(req)
50
50
  begin_transport req
51
51
  req.exec @socket, @curr_http_version, edit_path(req.path)
@@ -56,7 +56,7 @@ class Net::HTTP
56
56
  @req_hacked, @res_hacked = req, res
57
57
  @res_hacked
58
58
  end
59
-
59
+
60
60
  def end_request_hacked
61
61
  @res_hacked.end_reading_body_hacked
62
62
  end_transport @req_hacked, @res_hacked
@@ -77,12 +77,12 @@ class Net::HTTPResponse
77
77
  # @socket = nil
78
78
  # end
79
79
  # end
80
-
80
+
81
81
  def begin_reading_body_hacked(sock, reqmethodallowbody)
82
82
  @socket = sock
83
83
  @body_exist = reqmethodallowbody && self.class.body_permitted?
84
84
  end
85
-
85
+
86
86
  def end_reading_body_hacked
87
87
  self.body
88
88
  @socket = nil
@@ -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.6.3"
8
+ VERSION = "0.6.4"
9
9
 
10
10
  class << self
11
11
  def extract_http_request_headers(env)
@@ -0,0 +1,40 @@
1
+ ###
2
+ # This is an example of how to use Rack-Proxy in a Rails application.
3
+ #
4
+ # Setup:
5
+ # 1. rails new test_app
6
+ # 2. cd test_app
7
+ # 3. install Rack-Proxy in `Gemfile`
8
+ # a. `gem 'rack-proxy', '~> 0.6.3'`
9
+ # 4. install gem: `bundle install`
10
+ # 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
11
+ # 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
12
+ # 7. open in browser: `http://localhost:3000/example_service`
13
+ #
14
+ ###
15
+ ENV['SERVICE_URL'] ||= 'http://guides.rubyonrails.org'
16
+
17
+ class ExampleServiceProxy < Rack::Proxy
18
+ def perform_request(env)
19
+ request = Rack::Request.new(env)
20
+
21
+ # use rack proxy for anything hitting our host app at /example_service
22
+ if request.path =~ %r{^/example_service}
23
+ backend = URI(ENV['SERVICE_URL'])
24
+ # most backends required host set properly, but rack-proxy doesn't set this for you automatically
25
+ # even when a backend host is passed in via the options
26
+ env["HTTP_HOST"] = backend.host
27
+
28
+ # This is the only path that needs to be set currently on Rails 5 & greater
29
+ env['PATH_INFO'] = ENV['SERVICE_PATH'] || '/configuring.html'
30
+
31
+ # don't send your sites cookies to target service, unless it is a trusted internal service that can parse all your cookies
32
+ env['HTTP_COOKIE'] = ''
33
+ super(env)
34
+ else
35
+ @app.call(env)
36
+ end
37
+ end
38
+ end
39
+
40
+ Rails.application.config.middleware.use ExampleServiceProxy, backend: ENV['SERVICE_URL'], streaming: false
@@ -0,0 +1,24 @@
1
+ class ForwardHost < Rack::Proxy
2
+
3
+ def rewrite_env(env)
4
+ env["HTTP_HOST"] = "example.com"
5
+ env
6
+ end
7
+
8
+ def rewrite_response(triplet)
9
+ status, headers, body = triplet
10
+
11
+ # example of inserting an additional header
12
+ headers["X-Foo"] = "Bar"
13
+
14
+ # if you rewrite env, it appears that content-length isn't calculated correctly
15
+ # resulting in only partial responses being sent to users
16
+ # you can remove it or recalculate it here
17
+ headers["content-length"] = nil
18
+
19
+ triplet
20
+ end
21
+
22
+ end
23
+
24
+ Rails.application.config.middleware.use ForwardHost, backend: 'http://example.com', streaming: false
@@ -0,0 +1,37 @@
1
+ ###
2
+ # Open http://localhost:3000/test.php to trigger proxy
3
+ ###
4
+ class RackPhpProxy < Rack::Proxy
5
+
6
+ def perform_request(env)
7
+ request = Rack::Request.new(env)
8
+ if request.path =~ %r{\.php}
9
+ env["HTTP_HOST"] = ENV["HTTP_HOST"] ? URI(ENV["HTTP_HOST"]).host : "localhost"
10
+ ENV["PHP_PATH"] ||= '/manual/en/tutorial.firstpage.php'
11
+
12
+ # Rails 3 & 4
13
+ env["REQUEST_PATH"] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
14
+ # Rails 5 and above
15
+ env['PATH_INFO'] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
16
+
17
+ env['content-length'] = nil
18
+
19
+ super(env)
20
+ else
21
+ @app.call(env)
22
+ end
23
+ end
24
+
25
+ def rewrite_response(triplet)
26
+ status, headers, body = triplet
27
+
28
+ # if you proxy depending on the backend, it appears that content-length isn't calculated correctly
29
+ # resulting in only partial responses being sent to users
30
+ # you can remove it or recalculate it here
31
+ headers["content-length"] = nil
32
+
33
+ triplet
34
+ end
35
+ end
36
+
37
+ Rails.application.config.middleware.use RackPhpProxy, backend: ENV["HTTP_HOST"]='http://php.net', streaming: false
@@ -0,0 +1,24 @@
1
+ class TrustingProxy < Rack::Proxy
2
+
3
+ def rewrite_env(env)
4
+ env["HTTP_HOST"] = "self-signed.badssl.com"
5
+
6
+ # We are going to trust the self-signed SSL
7
+ env["rack.ssl_verify_none"] = true
8
+ env
9
+ end
10
+
11
+ def rewrite_response(triplet)
12
+ status, headers, body = triplet
13
+
14
+ # if you rewrite env, it appears that content-length isn't calculated correctly
15
+ # resulting in only partial responses being sent to users
16
+ # you can remove it or recalculate it here
17
+ headers["content-length"] = nil
18
+
19
+ triplet
20
+ end
21
+
22
+ end
23
+
24
+ Rails.application.config.middleware.use TrustingProxy, backend: 'https://self-signed.badssl.com', streaming: false
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Jacek Becela"]
10
10
  s.email = ["jacek.becela@gmail.com"]
11
- s.homepage = "http://rubygems.org/gems/rack-proxy"
11
+ s.homepage = "https://github.com/ncr/rack-proxy"
12
12
  s.summary = %q{A request/response rewriting HTTP proxy. A Rack app.}
13
13
  s.description = %q{A Rack app that provides request/response rewriting proxy capabilities with streaming.}
14
14
 
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.3
4
+ version: 0.6.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: 2017-12-08 00:00:00.000000000 Z
11
+ date: 2018-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -71,12 +71,16 @@ files:
71
71
  - lib/rack-proxy.rb
72
72
  - lib/rack/http_streaming_response.rb
73
73
  - lib/rack/proxy.rb
74
+ - lib/rack_proxy_examples/example_service_proxy.rb
75
+ - lib/rack_proxy_examples/forward_host.rb
76
+ - lib/rack_proxy_examples/rack_php_proxy.rb
77
+ - lib/rack_proxy_examples/trusting_proxy.rb
74
78
  - rack-proxy.gemspec
75
79
  - test/http_streaming_response_test.rb
76
80
  - test/net_http_hacked_test.rb
77
81
  - test/rack_proxy_test.rb
78
82
  - test/test_helper.rb
79
- homepage: http://rubygems.org/gems/rack-proxy
83
+ homepage: https://github.com/ncr/rack-proxy
80
84
  licenses: []
81
85
  metadata: {}
82
86
  post_install_message:
@@ -95,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
99
  version: '0'
96
100
  requirements: []
97
101
  rubyforge_project: rack-proxy
98
- rubygems_version: 2.5.1
102
+ rubygems_version: 2.5.2.2
99
103
  signing_key:
100
104
  specification_version: 4
101
105
  summary: A request/response rewriting HTTP proxy. A Rack app.