mirror of
https://github.com/discourse/discourse.git
synced 2024-12-16 06:03:46 +08:00
FIX: If HEAD is not supported, try GET. Also set cookies
This commit is contained in:
parent
a4be79d297
commit
502bca2c0d
|
@ -7,6 +7,7 @@ require 'rate_limiter'
|
||||||
class FinalDestination
|
class FinalDestination
|
||||||
|
|
||||||
attr_reader :status
|
attr_reader :status
|
||||||
|
attr_reader :cookie
|
||||||
|
|
||||||
def initialize(url, opts=nil)
|
def initialize(url, opts=nil)
|
||||||
@uri = URI(url) rescue nil
|
@uri = URI(url) rescue nil
|
||||||
|
@ -21,6 +22,11 @@ class FinalDestination
|
||||||
end
|
end
|
||||||
@limit = @opts[:max_redirects]
|
@limit = @opts[:max_redirects]
|
||||||
@status = :ready
|
@status = :ready
|
||||||
|
@cookie = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.connection_timeout
|
||||||
|
20
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirected?
|
def redirected?
|
||||||
|
@ -28,9 +34,27 @@ class FinalDestination
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_headers
|
def request_headers
|
||||||
{ "User-Agent" => "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
|
result = {
|
||||||
|
"User-Agent" => "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
|
||||||
"Accept" => "text/html",
|
"Accept" => "text/html",
|
||||||
"Host" => @uri.hostname }
|
"Host" => @uri.hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
result['cookie'] = @cookie if @cookie
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def small_get(headers)
|
||||||
|
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.is_a?(URI::HTTPS)) do |http|
|
||||||
|
http.open_timeout = FinalDestination.connection_timeout
|
||||||
|
http.read_timeout = FinalDestination.connection_timeout
|
||||||
|
|
||||||
|
request = Net::HTTP::Get.new(@uri.request_uri, headers)
|
||||||
|
http.request(request) do |response|
|
||||||
|
return response
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve
|
def resolve
|
||||||
|
@ -41,17 +65,41 @@ class FinalDestination
|
||||||
|
|
||||||
return nil unless validate_uri
|
return nil unless validate_uri
|
||||||
headers = request_headers
|
headers = request_headers
|
||||||
head = Excon.head(@uri.to_s, read_timeout: 20, headers: headers)
|
response = Excon.head(
|
||||||
|
@uri.to_s,
|
||||||
|
read_timeout: FinalDestination.connection_timeout,
|
||||||
|
headers: headers
|
||||||
|
)
|
||||||
|
|
||||||
# If the site does not allow HEAD, just try the url
|
location = nil
|
||||||
return @uri if head.status == 405
|
case response.status
|
||||||
|
when 200
|
||||||
|
@status = :resolved
|
||||||
|
return @uri
|
||||||
|
when 405, 501
|
||||||
|
get_response = small_get(headers)
|
||||||
|
|
||||||
if head.status == 200
|
if get_response.code.to_i == 200
|
||||||
@status = :resolved
|
@status = :resolved
|
||||||
return @uri
|
return @uri
|
||||||
end
|
end
|
||||||
|
|
||||||
location = FinalDestination.header_for(head, 'location')
|
if cookie_val = get_response.get_fields('set-cookie')
|
||||||
|
@cookie = cookie_val.join
|
||||||
|
end
|
||||||
|
|
||||||
|
if location_val = get_response.get_fields('location')
|
||||||
|
location = location_val.join
|
||||||
|
end
|
||||||
|
else
|
||||||
|
response.headers.each do |k, v|
|
||||||
|
case k.downcase
|
||||||
|
when 'set-cookie' then @cookie = v
|
||||||
|
when 'location' then location = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if location
|
if location
|
||||||
location = "#{@uri.scheme}://#{@uri.host}#{location}" if location[0] == "/"
|
location = "#{@uri.scheme}://#{@uri.host}#{location}" if location[0] == "/"
|
||||||
@uri = URI(location) rescue nil
|
@uri = URI(location) rescue nil
|
||||||
|
@ -127,11 +175,4 @@ class FinalDestination
|
||||||
IPSocket::getaddress(host)
|
IPSocket::getaddress(host)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.header_for(head, name)
|
|
||||||
header = head.headers.detect do |k, _|
|
|
||||||
name == k.downcase
|
|
||||||
end
|
|
||||||
header[1] if header
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,6 +120,45 @@ describe FinalDestination do
|
||||||
expect(final.status).to eq(:invalid_address)
|
expect(final.status).to eq(:invalid_address)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "HEAD not supported" do
|
||||||
|
before do
|
||||||
|
stub_request(:get, 'https://eviltrout.com').to_return(
|
||||||
|
status: 301,
|
||||||
|
headers: {
|
||||||
|
"Location" => 'https://discourse.org',
|
||||||
|
'Set-Cookie' => 'evil=trout'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
stub_request(:head, 'https://discourse.org').to_return(status: 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the status code is 405" do
|
||||||
|
before do
|
||||||
|
stub_request(:head, 'https://eviltrout.com').to_return(status: 405)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "will try a GET" do
|
||||||
|
final = FinalDestination.new('https://eviltrout.com', opts)
|
||||||
|
expect(final.resolve.to_s).to eq('https://discourse.org')
|
||||||
|
expect(final.status).to eq(:resolved)
|
||||||
|
expect(final.cookie).to eq('evil=trout')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the status code is 501" do
|
||||||
|
before do
|
||||||
|
stub_request(:head, 'https://eviltrout.com').to_return(status: 501)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "will try a GET" do
|
||||||
|
final = FinalDestination.new('https://eviltrout.com', opts)
|
||||||
|
expect(final.resolve.to_s).to eq('https://discourse.org')
|
||||||
|
expect(final.status).to eq(:resolved)
|
||||||
|
expect(final.cookie).to eq('evil=trout')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.validate_uri' do
|
describe '.validate_uri' do
|
||||||
|
|
Loading…
Reference in New Issue
Block a user