Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle HTTP 302 without Location #1302

Merged
merged 1 commit into from Jan 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
101 changes: 101 additions & 0 deletions nanoc/spec/nanoc/checking/checks/external_links_spec.rb
@@ -0,0 +1,101 @@
# frozen_string_literal: true

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