pretty_proxy 2.0.1 → 3.0.0

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: 5c71de1a7325089cea6ee46ebd45882e65119619
4
- data.tar.gz: 79bff31288cc6c7723e338e59bf010319b8e2d42
3
+ metadata.gz: 9ba185c1e9ef80173adf3ed23ad9b0ec056e305e
4
+ data.tar.gz: 4af0397bcdcaa6cd5baa7a2ea664e1ba1e734449
5
5
  SHA512:
6
- metadata.gz: be855fc2ac44bcb2e9cea9b7714288d5fc333e66863bd63deaa5133790d1c65e10bb5e602f53f7ae2c28314a92c9c785ca3c4d77666bf8fe4844ec19884044c6
7
- data.tar.gz: e19ea8b24a83f2d20a87d25776da3d77997bab40f0ceb955995888e68f0243f50a25b90d4893096c67c3497b40c3c67a3b5197de8a623731e5bb5d2b0a41d188
6
+ metadata.gz: a3f0e0c339617821d7122b1cfe8784e34f17b1f4c70e628c0f670061b71b8ba900cf32c7a202fe26b998b26b182312c50001810f36378b7456e73dec5db0ff74
7
+ data.tar.gz: da92cb376d0975d95faf9ab262b24405ebd2156da6d4a0170ab693e2d73247c7d7b2eafd1482005eb24d88b037e368966e2ef02cf3841334493c390a2f63a4a5
data/lib/pretty_proxy.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'pathname'
2
- require 'uri'
3
2
  require 'nokogiri'
4
3
  require 'rack'
5
4
  require 'rack-proxy'
5
+ require 'addressable/uri'
6
+ require 'uri'
6
7
 
7
8
  # The PrettyProxy class aggregate and validate the configuration of a
8
9
  # proxy based in simple pretty url oriented rewriting rules. It's too
@@ -47,9 +48,18 @@ require 'rack-proxy'
47
48
  # the proxy_path and is followed by a original_path.
48
49
  #
49
50
  # 'in(side)/out(side) the proxy control': The url have (or not) the path
50
- # starting with a original_path and the scheme, port and host are the
51
+ # starting with a original_path, and the scheme, port and host are the
51
52
  # same of the original_domain.
52
53
  #
54
+ # CHANGELOG:
55
+ # 3.0.0
56
+ # * return a String for unproxify_url (and not more a URI)
57
+ # because this is a change in the API (and can break code) the major
58
+ # version is now 3, if you don't use this method you can safely upgrade
59
+ # * depends in addressable gem
60
+ # * handles correctly the URIs without scheme (but with host)
61
+ # like '//duckduckgo.com/' (spec added for that)
62
+ #
53
63
  # @author Henrique Becker
54
64
  class PrettyProxy < Rack::Proxy
55
65
  # The supertype of any exceptions explicitly raised by the methods
@@ -83,7 +93,7 @@ class PrettyProxy < Rack::Proxy
83
93
  Utils.validate_original_domain_and_paths(original_domain, original_paths)
84
94
 
85
95
  @proxy_path = proxy_path.clone
86
- @original_domain = URI(original_domain.clone)
96
+ @original_domain = Addressable::URI.parse(original_domain.clone)
87
97
  @original_paths = Set.new
88
98
  if original_paths.respond_to? :each
89
99
  original_paths.each { | value | @original_paths << value.clone }
@@ -121,29 +131,21 @@ class PrettyProxy < Rack::Proxy
121
131
  # Take a proxy url and return the original URL behind the proxy. Preserve the
122
132
  # query and fragment, if any. For the rewrite of a request @see rewrite_env.
123
133
  # @param url [String, URI::HTTP, URI::HTTPS] A URL.
124
- # @return [URI::HTTP, URI::HTTPS] A URI object.
134
+ # @return [String] The unproxified URI in a string.
125
135
  # @raise PrettyProxy::ProxyError
126
136
  def unproxify_url(url)
127
- url = URI(url.clone)
128
- unless url.path.start_with?(@proxy_path)
129
- fail ProxyError, "url path has to be prefixed by proxy_path (#{@proxy_path})"
130
- end
131
- url.path = url.path.slice((proxy_path.size-1)..-1)
132
- unless original_paths.any? { | path | url.path.start_with? path }
133
- fail ProxyError, "the proxy only responds to paths in the original_paths (#{@original_paths})"
134
- end
135
- if url.host == original_domain.host && url.path.start_with?(@proxy_path)
136
- fail ProxyError, 'this is a request for the proxy for a proxy page (recursive request)'
137
+ url = Addressable::URI.parse(url.clone)
138
+
139
+ unless valid_path_for_proxy? url.path
140
+ fail ProxyError, "'#{url.to_s}' isn't inside the proxy control, it can't be unproxified"
137
141
  end
138
- url.host = original_domain.host
139
- url.scheme = original_domain.scheme
140
- url.port = original_domain.port
141
142
 
142
- url
143
- rescue URI::InvalidURIError
143
+ url.site = @original_domain.site
144
+ url.path = url.path.slice((@proxy_path.size-1)..-1)
145
+
146
+ url.to_s
147
+ rescue Addressable::URI::InvalidURIError
144
148
  raise ArgumentError, "the url argument isn't a valid uri"
145
- rescue URI::Error => e
146
- raise ProxyError, "an unexpected URI exception has been thrown, the message is '#{e.message}'"
147
149
  end
148
150
 
149
151
  # Take a hyperlink and the url of the proxy page (not the original page)
@@ -158,34 +160,38 @@ class PrettyProxy < Rack::Proxy
158
160
  # @return [String] A relative path or an url.
159
161
  # @raise PrettyProxy::ProxyError
160
162
  def proxify_hyperlink(hyperlink, proxy_page_url)
161
- hyperlink = URI(hyperlink.clone)
162
- proxy_page_url = URI(proxy_page_url)
163
- if hyperlink.scheme
164
- if inside_proxy_control? hyperlink
165
- unless point_to_a_proxy_page?(hyperlink, proxy_page_url)
166
- hyperlink = proxify_uri(hyperlink, proxy_page_url)
167
- end
168
- end
169
- else
170
- # recreate the original site url from the relative/absolute path
171
- absolute_link = unproxify_url proxy_page_url
172
- absolute_link.path = Pathname.new(absolute_link.path).join(hyperlink.path).to_s
173
- if inside_proxy_control? absolute_link
163
+ hyperlink = Addressable::URI.parse(hyperlink.clone)
164
+ proxy_page_url = Addressable::URI.parse(proxy_page_url)
165
+
166
+ # this is URI relative ('//duckduckgo.com', '/path', '../path')
167
+ if hyperlink.relative?
168
+ absolute_hyperlink = Addressable::URI.parse(unproxify_url(proxy_page_url))
169
+ .join(hyperlink)
170
+ if inside_proxy_control? absolute_hyperlink
171
+ # this is path relative ('../path', 'path', but not '//duckduckgo.com' or '/path')
174
172
  if Pathname.new(hyperlink.path).relative?
175
- if same_domain_as_original?(proxy_page_url) &&
176
- valid_path_for_proxy?(absolute_link.path)
173
+ if point_to_a_proxy_page?(absolute_hyperlink, proxy_page_url)
177
174
  # in the case of a relative path in the original page who points
178
175
  # to a proxy page, and the proxy page is inside the proxy control
179
- # we have to use the absolute_link or the page will be double proxified
180
- # example: ../proxy/content in http://example.com/proxy/content, with
181
- # original_path as '/' is http://example.com/proxy/proxy/content
182
- hyperlink = absolute_link
176
+ # we have to use the absolute_hyperlink or the page will be double
177
+ # proxified. Example: ../proxy/content in http://example.com/proxy/content,
178
+ # with original_path as '/' is http://example.com/proxy/proxy/content
179
+ hyperlink = absolute_hyperlink
183
180
  end
184
- else # is absolute
185
- hyperlink.path = @proxy_path + hyperlink.path[1..-1]
181
+ else
182
+ hyperlink.path = @proxy_path[0..-2] + absolute_hyperlink.path
183
+ hyperlink.host = proxy_page_url.host if hyperlink.host
184
+ hyperlink.port = proxy_page_url.port if hyperlink.port
186
185
  end
187
186
  else
188
- hyperlink = absolute_link
187
+ hyperlink = absolute_hyperlink
188
+ end
189
+ else # the hyperlink is absolute
190
+ if inside_proxy_control? hyperlink
191
+ # if points to the proxy itself we don't double-proxify
192
+ unless point_to_a_proxy_page?(hyperlink, proxy_page_url)
193
+ hyperlink = proxify_uri(hyperlink, proxy_page_url)
194
+ end
189
195
  end
190
196
  end
191
197
 
@@ -238,7 +244,8 @@ class PrettyProxy < Rack::Proxy
238
244
  def rewrite_env(env)
239
245
  env = env.clone
240
246
  url_requested_to_proxy = Rack::Request.new(env).url
241
- unproxified_url = unproxify_url(url_requested_to_proxy)
247
+ # Using URI, and not Addressable::URI because the port value is incorrect in the last
248
+ unproxified_url = URI(unproxify_url(url_requested_to_proxy))
242
249
 
243
250
  if env['HTTP_HOST']
244
251
  env['HTTP_HOST'] = unproxified_url.host
@@ -402,12 +409,10 @@ class PrettyProxy < Rack::Proxy
402
409
  end
403
410
 
404
411
  # api private Don't use this method.
405
- def proxify_uri(uri, proxy_domain)
406
- uri = uri.clone
412
+ def proxify_uri(absolute_uri, proxy_site)
413
+ uri = absolute_uri.clone
407
414
 
408
- uri.scheme = proxy_domain.scheme
409
- uri.host = proxy_domain.host
410
- uri.port = proxy_domain.port
415
+ uri.site = proxy_site.site
411
416
  uri.path = @proxy_path + uri.path[1..-1]
412
417
 
413
418
  uri
@@ -416,6 +421,7 @@ class PrettyProxy < Rack::Proxy
416
421
 
417
422
  # api private Don't use the methods of this class. They are for internal use only.
418
423
  module Utils
424
+ # TODO: check if isn't the case of change this for 'u1.site == u2.site'
419
425
  def self.same_domain?(u1, u2)
420
426
  u1.scheme == u2.scheme &&
421
427
  u1.host == u2.host &&
@@ -437,23 +443,23 @@ class PrettyProxy < Rack::Proxy
437
443
  def self.validate_original_domain_and_paths(original_domain, original_paths)
438
444
  fail ConfigError, 'original_paths is empty' if original_paths.empty?
439
445
 
440
- original_domain = URI(original_domain) # can raise URI:Error's
446
+ original_domain = Addressable::URI.parse(original_domain)
441
447
  fail ConfigError, 'the original_domain has to have no query or fragment' if original_domain.query || original_domain.fragment
442
448
 
443
- # can raise URI:Error's
449
+ # can raise errors
444
450
  test_uri = original_domain.clone
445
451
  if original_paths.respond_to?(:each)
446
- original_paths.each { | path | test_uri.path = path }
452
+ original_paths.each do | path |
453
+ fail ConfigError, "original_paths value '#{path}' don't start with a '/'" unless path.start_with? '/'
454
+ test_uri.path = path
455
+ end
447
456
  else
457
+ fail ConfigError, "original_paths value '#{original_paths}' don't start with a '/'" unless original_paths.start_with? '/'
448
458
  test_uri.path = original_paths
449
459
  end
450
460
 
451
- rescue URI::InvalidComponentError => e
452
- raise ConfigError, "the original_paths contain a invalid path, message of the URI exception: '#{e.message}'"
453
- rescue URI::InvalidURIError => e
454
- raise ConfigError, "the original_domain isn't a valid URI, message of the URI exception: '#{e.message}'"
455
- rescue URI::Error => e
456
- raise ConfigError, "a unexpected URI::Error exception was raised, message of the exception: '#{e.message}'"
461
+ rescue Addressable::URI::InvalidURIError => e
462
+ raise ConfigError, "the message of the URI exception: '#{e.message}'"
457
463
  end
458
464
  end
459
465
 
@@ -1,6 +1,7 @@
1
1
  require 'pretty_proxy'
2
2
  require 'equivalent-xml' # needed for be_equivalent_to xml rspec matcher
3
3
  require 'zlib'
4
+ require 'uri'
4
5
 
5
6
  shared_examples 'an reader method who encapsulate a mutable variable' do
6
7
  context 'when the return is changed' do
@@ -94,7 +95,7 @@ describe PrettyProxy do
94
95
  end
95
96
 
96
97
  context 'when the original_domain is invalid' do
97
- it { expect {new.call(right_args[0], 'http://myoriginalsite.com/%%%/', right_args[2])}.to raise_error(PrettyProxy::ConfigError)}
98
+ it { expect {new.call(right_args[0], 'http://<invalid>.com', right_args[2])}.to raise_error(PrettyProxy::ConfigError)}
98
99
  end
99
100
 
100
101
  context 'when the original_domain has a query' do
@@ -127,7 +128,7 @@ describe PrettyProxy do
127
128
 
128
129
  # NOTE: excessive metaprogramming? only save 3~6 lines
129
130
  [ [ :proxy_path=, "when proxy_path doesn't end with a '/'", '/proxy'],
130
- [ :original_domain=, 'when the original_domain is invalid', 'http://myoriginalsite.com/%%%/'],
131
+ [ :original_domain=, 'when the original_domain is invalid', 'http://<invalid>.com'],
131
132
  [ :original_paths=, "when the original_paths don't begin with a '/'", 'content']
132
133
  ].each do | error_case |
133
134
  writter, context_desc, invalid_input = *error_case
@@ -144,31 +145,31 @@ describe PrettyProxy do
144
145
 
145
146
  context 'when the original_path has no trailing slash' do
146
147
  it 'allow no trailing slash in the url' do
147
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1')).to eq URI('http://site.net/p1')
148
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1')).to eq 'http://site.net/p1'
148
149
  end
149
150
  it 'allow trailing slash in the url' do
150
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/')).to eq URI('http://site.net/p1/')
151
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/')).to eq 'http://site.net/p1/'
151
152
  end
152
153
  end
153
154
  context 'when the original_path has a trailing slash' do
154
155
  it 'allow trailing slash in the url' do
155
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p2/p2_2/')).to eq URI('http://site.net/p2/p2_2/')
156
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p2/p2_2/')).to eq 'http://site.net/p2/p2_2/'
156
157
  end
157
158
  it "don't allow no trailing slash" do
158
159
  expect { pp.unproxify_url('http://myproxy.net/proxys/sitez/p2/p2_2') }.to raise_error(PrettyProxy::ProxyError)
159
160
  end
160
161
  end
161
162
  it 'allow subdirectories inside that path' do
162
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/a/b/c/')).to eq URI('http://site.net/p1/a/b/c/')
163
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/a/b/c/')).to eq 'http://site.net/p1/a/b/c/'
163
164
  end
164
165
  it 'preserve querys in the url' do
165
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/?q=error&l=pt')).to eq URI('http://site.net/p1/?q=error&l=pt')
166
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/?q=error&l=pt')).to eq 'http://site.net/p1/?q=error&l=pt'
166
167
  end
167
168
  it 'preserve fragments in the url' do
168
- expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/#id')).to eq URI('http://site.net/p1/#id')
169
+ expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/#id')).to eq 'http://site.net/p1/#id'
169
170
  end
170
171
  it 'change the port to the original' do
171
- expect(pp.unproxify_url('http://myproxy.net:9292/proxys/sitez/p1/#id').port).to eq 80
172
+ expect(URI(pp.unproxify_url('http://myproxy.net:9292/proxys/sitez/p1/#id')).port).to eq 80
172
173
  end
173
174
 
174
175
  context 'when the url redirect to the own proxy' do
@@ -193,6 +194,9 @@ describe PrettyProxy do
193
194
  it "proxify hyperlinks with scheme to inside the proxy control" do
194
195
  expect(pp.proxify_hyperlink('http://site.net/p2/p2_2/', 'http://theproxy.net/proxy/p1')).to eq 'http://theproxy.net/proxy/p2/p2_2/'
195
196
  end
197
+ it "proxify hyperlinks without scheme to inside the proxy control" do
198
+ expect(pp.proxify_hyperlink('//site.net/p2/p2_2/', 'http://theproxy.net/proxy/p1')).to eq '//theproxy.net/proxy/p2/p2_2/'
199
+ end
196
200
  it "don't change hyperlinks with scheme to ouside the proxy control" do
197
201
  expect(pp.proxify_hyperlink('http://othersite.net', 'http://theproxy.net/proxy/p1')).to eq 'http://othersite.net'
198
202
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretty_proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henrique Becker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-21 00:00:00.000000000 Z
11
+ date: 2013-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: addressable
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.3'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: equivalent-xml
57
71
  requirement: !ruby/object:Gem::Requirement