pretty_proxy 3.0.1 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/example.ru +3 -2
- data/example/example_spec.rb +3 -1
- data/lib/pretty_proxy.rb +120 -71
- data/spec/pretty_proxy_spec.rb +108 -55
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d98ec7a74142c72c40fbc20de2aa4553829196e
|
4
|
+
data.tar.gz: 671e81774cfc968511a1b9350538411cf935b50e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38e3c0e99b16af783e0f34c488d94a161cb8a034eb9a5aef609c3a8117c0c8a6e051f0d8fb66cb4dc040cebc980da0a00edfeb718b186a34f1fc5a0b367ca843
|
7
|
+
data.tar.gz: b204811390ada1dadf6b127d377dea989f9c475a577bc99ff9050ca0d79b074aab10afdb7e75c0e0dd46c759c813c9c7e471d2430477a3656af7b2702af8c760
|
data/example/example.ru
CHANGED
@@ -11,9 +11,10 @@ proxy_path = pretty_proxy_new_args['proxy_path']
|
|
11
11
|
original_domain = pretty_proxy_new_args['original_domain']
|
12
12
|
original_paths = pretty_proxy_new_args['original_paths']
|
13
13
|
|
14
|
+
# replace the constants with the paths without trailing slashs
|
14
15
|
original_html = config['xhtml_template'].join("\n")
|
15
|
-
.gsub('PROXY_PATH', proxy_path)
|
16
|
-
.gsub('ORIGINAL_DOMAIN', original_domain)
|
16
|
+
.gsub('PROXY_PATH', proxy_path[1..-2])
|
17
|
+
.gsub('ORIGINAL_DOMAIN', original_domain[0..-2])
|
17
18
|
|
18
19
|
pp = PrettyProxy.new(proxy_path, original_domain, original_paths)
|
19
20
|
|
data/example/example_spec.rb
CHANGED
@@ -17,6 +17,8 @@ proxy_url = original_domain + Pathname.new(proxy_path).join('.' + config['conten
|
|
17
17
|
|
18
18
|
describe 'PrettyProxy example' do
|
19
19
|
let (:pp) { PrettyProxy.new(proxy_path, original_domain, original_paths) }
|
20
|
-
|
20
|
+
let (:original_page) { open(original_url) }
|
21
|
+
let (:proxy_page) { open(proxy_url) }
|
22
|
+
it { expect(proxy_page.read).to be_equivalent_to(pp.proxify_html(original_page.read, proxy_url, original_page.content_type)) }
|
21
23
|
end
|
22
24
|
|
data/lib/pretty_proxy.rb
CHANGED
@@ -51,6 +51,19 @@ require 'addressable/uri'
|
|
51
51
|
# same of the original_domain.
|
52
52
|
#
|
53
53
|
# CHANGELOG:
|
54
|
+
# 4.0.0
|
55
|
+
# * proxify_hyperlink don't take relative paths or urls anymore, only
|
56
|
+
# absolute urls. This is because the proxy url was used for a double
|
57
|
+
# purpose (know the proxy scheme+host+port and resolve relative
|
58
|
+
# hyperlinks). This can lead to the mistake of believing that the
|
59
|
+
# base url to resolve relative links in the page is the page url
|
60
|
+
# (what's false if the page has a base tag). See more in:
|
61
|
+
# http://www.w3.org/TR/html5/infrastructure.html#base-urls
|
62
|
+
# * proxify_html (and other methods who use it, as #call) use the base
|
63
|
+
# tag from the page to determine the base url, and add the the base
|
64
|
+
# tag (if the page don't have one) to simplify the assets proxification.
|
65
|
+
# All a[href] are changed to absolute urls.
|
66
|
+
# * rspec-html-matchers added as development dependency
|
54
67
|
# 3.0.0
|
55
68
|
# * return a String for unproxify_url (and not more a URI)
|
56
69
|
# because this is a change in the API (and can break code) the major
|
@@ -147,84 +160,81 @@ class PrettyProxy < Rack::Proxy
|
|
147
160
|
raise ArgumentError, "the url argument isn't a valid uri"
|
148
161
|
end
|
149
162
|
|
150
|
-
# Take a
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
# @param
|
158
|
-
#
|
159
|
-
# @
|
163
|
+
# Take a absolute URL and the scheme://host[:port] of the proxy page
|
164
|
+
# (can have path/?query#fragment, but they are ignored) and return the
|
165
|
+
# rewritten hyperlink.
|
166
|
+
# The url only is rewritten to point the proxyfied version if it's under
|
167
|
+
# proxy control.
|
168
|
+
# If the url is under proxy control, but it's also a url to the proxy, the
|
169
|
+
# url isn't changed (to not double proxyfy, /proxy/ ~> /proxy/proxy/).
|
170
|
+
# @param hyperlink [String, URI::HTTP, URI::HTTPS] A string or URI object
|
171
|
+
# with a absolute url.
|
172
|
+
# @param proxy_site [String, URI::HTTP, URI::HTTPS] A URL with
|
173
|
+
# scheme://host[:port] to use in the hyperlink proxification.
|
174
|
+
# @return [String] A absolute URL.
|
160
175
|
# @raise PrettyProxy::ProxyError
|
161
|
-
def proxify_hyperlink(hyperlink,
|
162
|
-
hyperlink = Addressable::URI.parse(hyperlink
|
163
|
-
|
164
|
-
|
165
|
-
# this is URI relative ('//duckduckgo.com', '/path', '../path')
|
166
|
-
if hyperlink.relative?
|
167
|
-
absolute_hyperlink = Addressable::URI.parse(unproxify_url(proxy_page_url))
|
168
|
-
.join(hyperlink)
|
169
|
-
if inside_proxy_control? absolute_hyperlink
|
170
|
-
# this is path relative ('../path', 'path', but not '//duckduckgo.com' or '/path')
|
171
|
-
if Pathname.new(hyperlink.path).relative?
|
172
|
-
if point_to_a_proxy_page?(absolute_hyperlink, proxy_page_url)
|
173
|
-
# in the case of a relative path in the original page who points
|
174
|
-
# to a proxy page, and the proxy page is inside the proxy control
|
175
|
-
# we have to use the absolute_hyperlink or the page will be double
|
176
|
-
# proxified. Example: ../proxy/content in http://example.com/proxy/content,
|
177
|
-
# with original_path as '/' is http://example.com/proxy/proxy/content
|
178
|
-
hyperlink = absolute_hyperlink
|
179
|
-
end
|
180
|
-
else
|
181
|
-
hyperlink.path = @proxy_path[0..-2] + absolute_hyperlink.path
|
182
|
-
hyperlink.host = proxy_page_url.host if hyperlink.host
|
183
|
-
hyperlink.port = proxy_page_url.port if hyperlink.port
|
184
|
-
end
|
185
|
-
else
|
186
|
-
hyperlink = absolute_hyperlink
|
187
|
-
end
|
188
|
-
else # the hyperlink is absolute
|
189
|
-
if inside_proxy_control? hyperlink
|
190
|
-
# if points to the proxy itself we don't double-proxify
|
191
|
-
unless point_to_a_proxy_page?(hyperlink, proxy_page_url)
|
192
|
-
hyperlink = proxify_uri(hyperlink, proxy_page_url)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
176
|
+
def proxify_hyperlink(hyperlink, proxy_site)
|
177
|
+
hyperlink = Addressable::URI.parse(hyperlink)
|
178
|
+
proxy_site = Addressable::URI.parse(proxy_site)
|
196
179
|
|
197
|
-
hyperlink
|
180
|
+
if inside_proxy_control?(hyperlink) &&
|
181
|
+
! point_to_a_proxy_page?(hyperlink, proxy_site)
|
182
|
+
proxify_uri(hyperlink, proxy_site).to_s
|
183
|
+
else
|
184
|
+
hyperlink.to_s
|
185
|
+
end
|
198
186
|
end
|
199
187
|
|
200
|
-
# Take a (X)HTML Document
|
201
|
-
# attribute of each 'a' element.
|
188
|
+
# Take a (X)HTML Document add a base tag (if none) and apply
|
189
|
+
# proxify_hyperlink to the 'href' attribute of each 'a' element.
|
190
|
+
# If the page has a base tag leave it unchanged.
|
191
|
+
# If a valid mime_type is passed as argument, but the html argument
|
192
|
+
# can't be parsed by this mime-type it simple returns the first argument
|
193
|
+
# unchanged.
|
202
194
|
# @param html [String] A (X)HTML document.
|
203
195
|
# @param proxy_url [String, URI::HTTP, URI::HTTPS] The url where the
|
204
196
|
# the proxified version of the page will be displayed.
|
205
|
-
# @
|
197
|
+
# @param mime_type [String] A string containing 'text/html' or
|
198
|
+
# 'application/xhtml+xml' (insensitive to case and any characters
|
199
|
+
# before or after the type). Define if the content will be parsed as xml or
|
200
|
+
# html. See this link for more info: http://www.w3.org/TR/xhtml-media-types/.
|
201
|
+
# Raise an exception if an invalid value is provided.
|
202
|
+
# @return [String] A copy of the document with the changes applied,
|
203
|
+
# or the original string, if the document can't be parsed.
|
206
204
|
# @raise PrettyProxy::ProxyError
|
207
|
-
def proxify_html(html, proxy_url)
|
208
|
-
parsed_html =
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
# Example: <meta name="description" content="not important" />
|
213
|
-
# becomes <meta name="description" content="not important" >
|
214
|
-
# To avoid this we parse a document who is XML valid as XML, and, otherwise as HTML
|
215
|
-
begin
|
216
|
-
# this also isn't a great way to do this
|
217
|
-
# the Nokogiri don't have exception classes, this way any StandardError will be silenced
|
218
|
-
options = Nokogiri::XML::ParseOptions::DEFAULT_XML &
|
219
|
-
Nokogiri::XML::ParseOptions::STRICT &
|
220
|
-
Nokogiri::XML::ParseOptions::DTDVALID
|
221
|
-
parsed_html = Nokogiri::XML::Document.parse(html, nil, nil, options)
|
222
|
-
rescue
|
223
|
-
parsed_html = Nokogiri::HTML(html)
|
205
|
+
def proxify_html(html, proxy_url, mime_type)
|
206
|
+
parsed_html = Utils.parse_html_or_xhtml(html, mime_type)
|
207
|
+
|
208
|
+
if parsed_html.nil?
|
209
|
+
return html
|
224
210
|
end
|
225
211
|
|
226
|
-
|
227
|
-
|
212
|
+
# This isn't in conformance with the following document
|
213
|
+
# http://www.w3.org/TR/html5/infrastructure.html#base-urls
|
214
|
+
# but support to frames is not a priority
|
215
|
+
document_original_url = unproxify_url(proxy_url)
|
216
|
+
# in theory base must have a href... but to avoid an exception by bad html
|
217
|
+
base_tag = parsed_html.at_css('base[href]')
|
218
|
+
base_url = nil
|
219
|
+
if base_tag
|
220
|
+
base_url = Addressable::URI.parse(document_original_url)
|
221
|
+
.join(base_tag['href']).to_s
|
222
|
+
else
|
223
|
+
base_url = document_original_url
|
224
|
+
end
|
225
|
+
|
226
|
+
# the href isn't a obrigatory attribute of an anchor element
|
227
|
+
parsed_html.css('a[href]').each do | hyperlink |
|
228
|
+
absolute_hyperlink = Addressable::URI.parse(base_url)
|
229
|
+
.join(hyperlink['href']).to_s
|
230
|
+
hyperlink['href'] = proxify_hyperlink(absolute_hyperlink, proxy_url)
|
231
|
+
end
|
232
|
+
|
233
|
+
unless base_tag
|
234
|
+
is_XML = %r{application/xhtml\+xml}.match(mime_type)
|
235
|
+
base_tag = "<base href='#{document_original_url}' #{is_XML ? '/' : ''}>"
|
236
|
+
parsed_html.at_css('head').first_element_child
|
237
|
+
.add_previous_sibling(base_tag)
|
228
238
|
end
|
229
239
|
|
230
240
|
parsed_html.to_s
|
@@ -312,7 +322,8 @@ class PrettyProxy < Rack::Proxy
|
|
312
322
|
fail ProxyError, 'unknown content-encoding, only encodings known are gzip, deflate and identity'
|
313
323
|
end
|
314
324
|
|
315
|
-
|
325
|
+
request_to_proxy = Rack::Request.new(requested_to_proxy_env)
|
326
|
+
page = proxify_html(page, request_to_proxy.url, content_type)
|
316
327
|
status, headers, page = sugared_rewrite_response([status, headers, page],
|
317
328
|
requested_to_proxy_env,
|
318
329
|
rewritten_env)
|
@@ -338,6 +349,8 @@ class PrettyProxy < Rack::Proxy
|
|
338
349
|
[status, headers, [page]]
|
339
350
|
end
|
340
351
|
|
352
|
+
# The simplest way to make use of this class is subclass this class and
|
353
|
+
# redefine this method.
|
341
354
|
# @abstract This method is called only over (X)HTML responses, after they are
|
342
355
|
# decompressed and the hyperlinks proxified, before they are compressed
|
343
356
|
# again and the new content-length calculated.
|
@@ -412,7 +425,7 @@ class PrettyProxy < Rack::Proxy
|
|
412
425
|
uri = absolute_uri.clone
|
413
426
|
|
414
427
|
uri.site = proxy_site.site
|
415
|
-
uri.path = @proxy_path + uri.path
|
428
|
+
uri.path = @proxy_path[0..-2] + uri.path
|
416
429
|
|
417
430
|
uri
|
418
431
|
end
|
@@ -424,9 +437,45 @@ class PrettyProxy < Rack::Proxy
|
|
424
437
|
def self.same_domain?(u1, u2)
|
425
438
|
u1.normalized_scheme == u2.normalized_scheme &&
|
426
439
|
u1.normalized_host == u2.normalized_host &&
|
427
|
-
u1.
|
440
|
+
u1.inferred_port == u2.inferred_port
|
428
441
|
end
|
429
442
|
|
443
|
+
def self.parse_html_or_xhtml(doc, mime_type)
|
444
|
+
# If you parse XHTML as HTML with Nokogiri, and use to_s after, the markup
|
445
|
+
# can be messed up, breaking the structural integrity of the xml
|
446
|
+
#
|
447
|
+
# Example: <meta name="description" content="not important" />
|
448
|
+
# becomes <meta name="description" content="not important" >
|
449
|
+
#
|
450
|
+
# In the other side if you parse HTML as a XML, and use to_s after, the
|
451
|
+
# Nokogiri make empty content tags self-close
|
452
|
+
#
|
453
|
+
# Example: <script type="text/javascript" src="/ballonizer.js"></script>
|
454
|
+
# becomes: <script type="text/javascript" src="/ballonizer.js" />
|
455
|
+
#
|
456
|
+
# What's even worse than the contrary (xml as html)
|
457
|
+
parsed_doc = nil
|
458
|
+
|
459
|
+
case mime_type
|
460
|
+
when /text\/html/i
|
461
|
+
parsed_doc = Nokogiri::HTML(doc)
|
462
|
+
when /application\/xhtml\+xml/i
|
463
|
+
options = Nokogiri::XML::ParseOptions::DEFAULT_XML &
|
464
|
+
Nokogiri::XML::ParseOptions::STRICT &
|
465
|
+
Nokogiri::XML::ParseOptions::NONET
|
466
|
+
begin
|
467
|
+
parsed_doc = Nokogiri::XML::Document.parse(doc, nil, nil, options)
|
468
|
+
rescue
|
469
|
+
return nil
|
470
|
+
end
|
471
|
+
else
|
472
|
+
fail ProxyError, "the only mime-types accepted are text/html and" +
|
473
|
+
" application/xhtml+xml, the passed argument was " +
|
474
|
+
"'#{mime_type}'"
|
475
|
+
end
|
476
|
+
|
477
|
+
parsed_doc
|
478
|
+
end
|
430
479
|
def self.validate_proxy_path(proxy_path)
|
431
480
|
fail ConfigError, "proxy_path argument don't start with a '/'" unless proxy_path.start_with? '/'
|
432
481
|
fail ConfigError, "proxy_path argument don't end with a '/'" unless proxy_path.end_with? '/'
|
data/spec/pretty_proxy_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pretty_proxy'
|
2
|
-
require 'equivalent-xml'
|
2
|
+
require 'equivalent-xml'
|
3
|
+
require 'rspec-html-matchers'
|
3
4
|
require 'zlib'
|
4
5
|
require 'uri'
|
5
6
|
|
@@ -22,12 +23,13 @@ end
|
|
22
23
|
|
23
24
|
describe PrettyProxy do
|
24
25
|
|
25
|
-
def generate_html_for_test(hyperlinks)
|
26
|
+
def generate_html_for_test(base_url, hyperlinks)
|
26
27
|
doc = <<-END
|
27
28
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
28
29
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
29
30
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
30
31
|
<head>
|
32
|
+
#{base_url ? "<base href='#{base_url}' />" : ''}
|
31
33
|
<title>A title</title>
|
32
34
|
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />
|
33
35
|
</head>
|
@@ -51,18 +53,43 @@ describe PrettyProxy do
|
|
51
53
|
doc
|
52
54
|
end
|
53
55
|
|
54
|
-
let(:
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
'../proxy/p1', '/p1']) }
|
56
|
+
let(:original_html_url) { 'http://site.net/p1' }
|
57
|
+
let(:requested_to_proxy_url) do
|
58
|
+
pp.proxify_hyperlink(original_html_url, 'http://site.net')
|
59
|
+
end
|
59
60
|
|
60
|
-
let(:
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
let (:link_examples) do
|
62
|
+
[ 'http://site.net/p2/p2_2/', 'http://othersite.net', '../p3',
|
63
|
+
'../p2/p2_2/', 'http://site.net/proxy/p1', '../proxy/p1', '/p1'
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
let(:html_base_href) { 'http://othersite.net/p1' }
|
68
|
+
let(:original_html_with_base) do
|
69
|
+
generate_html_for_test(html_base_href, link_examples)
|
70
|
+
end
|
71
|
+
let(:proxified_html_with_base) do
|
72
|
+
# in this case only the first link is proxified because all others are
|
73
|
+
# pointing for a site outside proxy control (or for the proxy itself)
|
74
|
+
generate_html_for_test(html_base_href, [
|
75
|
+
'http://site.net/proxy/p2/p2_2/', 'http://othersite.net',
|
76
|
+
'http://othersite.net/p3', 'http://othersite.net/p2/p2_2/',
|
77
|
+
'http://site.net/proxy/p1', 'http://othersite.net/proxy/p1',
|
78
|
+
'http://othersite.net/p1'
|
79
|
+
])
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:original_html) do
|
83
|
+
generate_html_for_test(nil, link_examples)
|
84
|
+
end
|
85
|
+
let(:proxified_html) do
|
86
|
+
generate_html_for_test(original_html_url, [
|
87
|
+
'http://site.net/proxy/p2/p2_2/', 'http://othersite.net',
|
88
|
+
'http://site.net/p3', 'http://site.net/proxy/p2/p2_2/',
|
89
|
+
'http://site.net/proxy/p1', 'http://site.net/proxy/p1',
|
90
|
+
'http://site.net/proxy/p1'
|
91
|
+
])
|
92
|
+
end
|
66
93
|
|
67
94
|
let (:correct_new_args_example) { ['/proxy/', 'http://myoriginalsite.com', '/content'] }
|
68
95
|
let (:pp) { described_class.new(*correct_new_args_example) }
|
@@ -84,7 +111,6 @@ describe PrettyProxy do
|
|
84
111
|
end
|
85
112
|
end
|
86
113
|
|
87
|
-
# TODO: Add specs for '/' in the start of the proxy_path
|
88
114
|
let (:right_args) { correct_new_args_example }
|
89
115
|
context "when proxy_path doesn't start with a '/'" do
|
90
116
|
it { expect {new.call('proxy/', right_args[1], right_args[2])}.to raise_error(PrettyProxy::ConfigError) }
|
@@ -169,7 +195,7 @@ describe PrettyProxy do
|
|
169
195
|
expect(pp.unproxify_url('http://myproxy.net/proxys/sitez/p1/#id')).to eq 'http://site.net/p1/#id'
|
170
196
|
end
|
171
197
|
it 'change the port to the original' do
|
172
|
-
expect(URI(pp.unproxify_url('http://myproxy.net:9292/proxys/sitez/p1/#id')).port).to eq 80
|
198
|
+
expect(URI.parse(pp.unproxify_url('http://myproxy.net:9292/proxys/sitez/p1/#id')).port).to eq 80
|
173
199
|
end
|
174
200
|
|
175
201
|
context 'when the url redirect to the own proxy' do
|
@@ -188,36 +214,26 @@ describe PrettyProxy do
|
|
188
214
|
describe '#proxify_hyperlink' do
|
189
215
|
let (:pp) { described_class.new('/proxy/', 'http://site.net', ['/p1', '/p2/p2_2/']) }
|
190
216
|
|
191
|
-
it
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
expect(pp.proxify_hyperlink(
|
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/'
|
217
|
+
it 'proxify urls that are inside the proxy control' do
|
218
|
+
original_link = 'http://site.net/p2/p2_2/'
|
219
|
+
url_proxy_page_with_the_link = 'http://theproxy.net/proxy/p1'
|
220
|
+
proxified_link = 'http://theproxy.net/proxy/p2/p2_2/'
|
221
|
+
expect(pp.proxify_hyperlink(original_link, url_proxy_page_with_the_link)).to eq proxified_link
|
199
222
|
end
|
200
|
-
it "don't
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
expect(pp.proxify_hyperlink('../p3', 'http://theproxy.net/proxy/p1')).to eq 'http://site.net/p3'
|
205
|
-
expect(pp.proxify_hyperlink('../p2/p2_2', 'http://theproxy.net/proxy/p1')).to eq 'http://site.net/p2/p2_2' # without the trailing '/'
|
206
|
-
end
|
207
|
-
it "don't change relative paths to inside the proxy control" do
|
208
|
-
expect(pp.proxify_hyperlink('../p2/p2_2/', 'http://theproxy.net/proxy/p1')).to eq '../p2/p2_2/'
|
223
|
+
it "don't proxify urls that are outside proxy control" do
|
224
|
+
outside_site = 'http://othersite.net'
|
225
|
+
proxy_url = 'http://theproxy.net/proxy/p1'
|
226
|
+
expect(pp.proxify_hyperlink(outside_site, proxy_url)).to eq outside_site
|
209
227
|
end
|
210
228
|
|
211
229
|
context 'when the proxy itself is inside the proxy control' do
|
212
230
|
let (:pp) { described_class.new('/proxy/', 'http://site.net', '/') }
|
213
231
|
|
214
|
-
it "
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
expect(pp.proxify_hyperlink('../proxy/p1', 'http://site.net/proxy/p1')).to eq 'http://site.net/proxy/p1'
|
220
|
-
expect(pp.proxify_hyperlink('../../proxy/p1', 'http://site.net/proxy/p2/p2_2/')).to eq 'http://site.net/proxy/p1'
|
232
|
+
it "preserve urls to the proxy itself (don't double proxify)" do
|
233
|
+
proxy_url = 'http://site.net/proxy/p1'
|
234
|
+
another_proxy_url = 'http://site.net/proxy/p2/p2_2/'
|
235
|
+
expect(pp.proxify_hyperlink(proxy_url, proxy_url)).to eq proxy_url
|
236
|
+
expect(pp.proxify_hyperlink(proxy_url, another_proxy_url)).to eq proxy_url
|
221
237
|
end
|
222
238
|
end
|
223
239
|
end
|
@@ -225,13 +241,44 @@ describe PrettyProxy do
|
|
225
241
|
describe '#proxify_html' do
|
226
242
|
let (:pp) { described_class.new('/proxy/', 'http://site.net', ['/p1', '/p2/p2_2/']) }
|
227
243
|
|
228
|
-
|
244
|
+
# valid mime_types are 'text/html' and 'application/xhtml+xml' (with any
|
245
|
+
# others characters before or after)
|
246
|
+
context 'when the mime_type is invalid' do
|
247
|
+
it { expect {pp.proxify_html(original_html, 'http://site.net/proxy/p1', 'not a valid mime-type')}.to raise_error(described_class::ProxyError) }
|
248
|
+
end
|
249
|
+
|
250
|
+
context "when the content can't be parsed" do
|
251
|
+
it 'return the original string' do
|
252
|
+
# without the </b> to make this xml invalid the test fail
|
253
|
+
# (the href is changed)
|
254
|
+
page = '<a href="http://site.net/p2/p2_2/">test</a></b>'
|
255
|
+
expect(pp.proxify_html(page, 'http://proxy.net/proxy/p1', 'application/xhtml+xml')).to equal(page)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'apply #proxify_hyperlink in all anchors in the page' do
|
229
260
|
# We aren't really testing with HTML, but with XHTML, what is a XML
|
230
261
|
# This is because we dont have a matcher to test HTML equivalence, only XML equivalence
|
231
262
|
# This test is not guaranteed to pass if the input is a HTML non-XHTML
|
232
263
|
# The parse and unparse of the HTML can output a value who is not XML equivalent to the input
|
233
264
|
# Maybe the way is use regex instead of Nokogiri to this work
|
234
|
-
expect(pp.proxify_html(original_html, '
|
265
|
+
expect(pp.proxify_html(original_html, requested_to_proxy_url, 'application/xhtml+xml')).to be_equivalent_to(proxified_html)
|
266
|
+
end
|
267
|
+
|
268
|
+
context 'when the page has a base tag' do
|
269
|
+
subject do
|
270
|
+
pp.proxify_html(
|
271
|
+
original_html_with_base,
|
272
|
+
requested_to_proxy_url,
|
273
|
+
'application/xhtml+xml'
|
274
|
+
)
|
275
|
+
end
|
276
|
+
it 'do not alter the base tag' do
|
277
|
+
should have_tag("base[href='#{html_base_href}']")
|
278
|
+
end
|
279
|
+
it 'use the base tag href as base url for relative links' do
|
280
|
+
should be_equivalent_to(proxified_html_with_base)
|
281
|
+
end
|
235
282
|
end
|
236
283
|
end
|
237
284
|
|
@@ -299,19 +346,25 @@ describe PrettyProxy do
|
|
299
346
|
describe '#rewrite_response' do
|
300
347
|
let (:pp) { described_class.new('/proxy/', 'http://site.net', ['/p1', '/p2/p2_2/']) }
|
301
348
|
# See http://rack.rubyforge.org/doc/SPEC.html for the rack env hash fields spec
|
302
|
-
let (:original_env)
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
349
|
+
let (:original_env) do
|
350
|
+
url = URI.parse(original_html_url)
|
351
|
+
{ 'HTTP_HOST' => url.host,
|
352
|
+
'SCRIPT_NAME' => '',
|
353
|
+
'PATH_INFO' => pp.proxy_path[0..-2] + url.path,
|
354
|
+
'QUERY_STRING' => '',
|
355
|
+
'SERVER_NAME' => url.host,
|
356
|
+
'SERVER_PORT' => url.port,
|
357
|
+
'rack.url_scheme' => url.scheme
|
358
|
+
}
|
359
|
+
end
|
309
360
|
let (:rewritten_env) { pp.rewrite_env(original_env) }
|
310
|
-
let (:response_example)
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
361
|
+
let (:response_example) do
|
362
|
+
original_content = [200, {
|
363
|
+
'content-type' => 'application/xhtml+xml',
|
364
|
+
'content-encoding' => 'identity',
|
365
|
+
'content-length' => original_html.bytesize.to_s
|
366
|
+
}, [original_html]]
|
367
|
+
end
|
315
368
|
|
316
369
|
context 'when the content-type is html or xhtml' do
|
317
370
|
let (:original_response) { response_example }
|
@@ -319,11 +372,11 @@ describe PrettyProxy do
|
|
319
372
|
|
320
373
|
let (:rewritten_headers) { subject[1] }
|
321
374
|
let (:rewritten_body) { subject[2].join }
|
322
|
-
let (:
|
375
|
+
let (:requested_to_proxy_url) { Rack::Request.new(original_env).url }
|
323
376
|
|
324
377
|
# NOTE: TESTING ONLY WITH XHTML, BY THE SAME MOTIVE EXPLAINED IN THE #proxify_html SPEC
|
325
378
|
it 'apply #proxify_html to the body' do
|
326
|
-
expect(rewritten_body).to be_equivalent_to pp.proxify_html(original_html,
|
379
|
+
expect(rewritten_body).to be_equivalent_to pp.proxify_html(original_html, requested_to_proxy_url, 'application/xhtml+xml')
|
327
380
|
end
|
328
381
|
|
329
382
|
it 'change the content-length header to the new size of the body' do
|
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:
|
4
|
+
version: 4.0.1
|
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-
|
11
|
+
date: 2013-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '10.0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rspec-html-matchers
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ~>
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.4.1
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ~>
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.4.1
|
153
167
|
description: If you want to replicate a site section with some change (like translation)
|
154
168
|
and mantain the url pretty maybe this is the right library.
|
155
169
|
email: henriquebecker91@gmail.com
|
@@ -184,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
198
|
version: '0'
|
185
199
|
requirements: []
|
186
200
|
rubyforge_project:
|
187
|
-
rubygems_version: 2.0.
|
201
|
+
rubygems_version: 2.0.3
|
188
202
|
signing_key:
|
189
203
|
specification_version: 4
|
190
204
|
summary: A Rack::Proxy child pretty url oriented
|