pretty_proxy 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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