Skip to content

Commit

Permalink
Handle HTTP 302 without Location
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdefreyne committed Jan 26, 2018
1 parent fdb5aaa commit 8457721
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 9 deletions.
28 changes: 19 additions & 9 deletions nanoc/lib/nanoc/checking/checks/external_links.rb
Expand Up @@ -74,15 +74,8 @@ def validate(href)
return Result.new(href, 'too many redirects')
end

# Find proper location
location = res['Location']
if location !~ /^https?:\/\//
base_url = url.dup
base_url.path = (location =~ /^\// ? '' : '/')
base_url.query = nil
base_url.fragment = nil
location = base_url.to_s + location
end
location = extract_location(res, url)
return Result.new(href, 'redirection without a target location') if location.nil?

url = URI.parse(location)
elsif res.code == '200'
Expand All @@ -98,6 +91,23 @@ def validate(href)
end
end

def extract_location(res, url)
location = res['Location']

case location
when nil
nil
when /^https?:\/\//
location
else
base_url = url.dup
base_url.path = (location =~ /^\// ? '' : '/')
base_url.query = nil
base_url.fragment = nil
base_url.to_s + location
end
end

def path_for_url(url)
path =
if url.path.nil? || url.path.empty?
Expand Down
99 changes: 99 additions & 0 deletions nanoc/spec/nanoc/checking/checks/external_links_spec.rb
@@ -0,0 +1,99 @@
describe ::Nanoc::Checking::Checks::ExternalLinks do
let(:check) do
Nanoc::Checking::Checks::ExternalLinks.create(site).tap do |c|
def c.request_url_once(url)
Net::HTTPResponse.new('1.1', '200', 'okay')
end
end
end

let(:site) do
Nanoc::Int::Site.new(
config: config,
code_snippets: code_snippets,
data_source: Nanoc::Int::InMemDataSource.new(items, layouts),
)
end

let(:config) { Nanoc::Int::Configuration.new.with_defaults }
let(:code_snippets) { [] }
let(:items) { Nanoc::Int::ItemCollection.new(config, []) }
let(:layouts) { Nanoc::Int::LayoutCollection.new(config, []) }

before do
FileUtils.mkdir_p('output')
File.write('output/hi.html', '<a href="http://example.com/x">stuff</a>')
File.write('Rules', 'passthrough "/**/*"')
end

context 'found' do
let(:check) do
Nanoc::Checking::Checks::ExternalLinks.create(site).tap do |c|
def c.request_url_once(url)
Net::HTTPResponse.new('1.1', '200', 'okay')
end
end
end

it 'has no issues' do
check.run
expect(check.issues).to be_empty
end
end

context 'not found' do
let(:check) do
Nanoc::Checking::Checks::ExternalLinks.create(site).tap do |c|
def c.request_url_once(url)
Net::HTTPResponse.new('1.1', '404', 'okay')
end
end
end

it 'has issues' do
check.run
expect(check.issues.size).to eq(1)
end
end

context 'redirect' do
let(:check) do
Nanoc::Checking::Checks::ExternalLinks.create(site).tap do |c|
def c.request_url_once(url)
@enum ||= Enumerator.new do |y|
y << Net::HTTPResponse.new('1.1', '302', 'look elsewhere').tap do |h|
h['Location'] = 'http://elsewhere.example.com/'
end
y << Net::HTTPResponse.new('1.1', '200', 'okay')
end
@enum.next
end
end
end

it 'has no issues' do
check.run
expect(check.issues).to be_empty
end
end

context 'redirect without location' do
let(:check) do
Nanoc::Checking::Checks::ExternalLinks.create(site).tap do |c|
def c.request_url_once(url)
@enum ||= Enumerator.new do |y|
y << Net::HTTPResponse.new('1.1', '302', 'look elsewhere')
end
@enum.next
end
end
end

it 'has issues' do
check.run
expect(check.issues.size).to eq(1)
expect(check.issues.first.description)
.to eq('broken reference to http://example.com/x: redirection without a target location')
end
end
end

0 comments on commit 8457721

Please sign in to comment.