mirror of
https://github.com/discourse/discourse.git
synced 2024-12-15 15:53:41 +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
|
||||
|
||||
attr_reader :status
|
||||
attr_reader :cookie
|
||||
|
||||
def initialize(url, opts=nil)
|
||||
@uri = URI(url) rescue nil
|
||||
|
@ -21,6 +22,11 @@ class FinalDestination
|
|||
end
|
||||
@limit = @opts[:max_redirects]
|
||||
@status = :ready
|
||||
@cookie = nil
|
||||
end
|
||||
|
||||
def self.connection_timeout
|
||||
20
|
||||
end
|
||||
|
||||
def redirected?
|
||||
|
@ -28,9 +34,27 @@ class FinalDestination
|
|||
end
|
||||
|
||||
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",
|
||||
"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
|
||||
|
||||
def resolve
|
||||
|
@ -41,17 +65,41 @@ class FinalDestination
|
|||
|
||||
return nil unless validate_uri
|
||||
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
|
||||
return @uri if head.status == 405
|
||||
location = nil
|
||||
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
|
||||
return @uri
|
||||
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
|
||||
location = "#{@uri.scheme}://#{@uri.host}#{location}" if location[0] == "/"
|
||||
@uri = URI(location) rescue nil
|
||||
|
@ -127,11 +175,4 @@ class FinalDestination
|
|||
IPSocket::getaddress(host)
|
||||
end
|
||||
|
||||
def self.header_for(head, name)
|
||||
header = head.headers.detect do |k, _|
|
||||
name == k.downcase
|
||||
end
|
||||
header[1] if header
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -120,6 +120,45 @@ describe FinalDestination do
|
|||
expect(final.status).to eq(:invalid_address)
|
||||
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
|
||||
|
||||
describe '.validate_uri' do
|
||||
|
|
Loading…
Reference in New Issue
Block a user