1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
# frozen_string_literal: true
module Excon
module Middleware
class RedirectFollower < Excon::Middleware::Base
def self.valid_parameter_keys
[
:redirects_remaining,
:redirect_limit
]
end
def request_call(datum)
datum[:redirects_remaining] ||= datum[:redirect_limit] ||
Excon::DEFAULT_REDIRECT_LIMIT
@stack.request_call(datum)
end
def get_header(datum, header)
_, header_value = datum[:response][:headers].detect do |key, _|
key.casecmp(header) == 0
end
header_value
end
def response_call(datum)
if datum.has_key?(:response)
case datum[:response][:status]
when 301, 302, 303, 307, 308
if datum[:redirects_remaining] <= 0
raise Excon::Errors::TooManyRedirects
end
datum[:redirects_remaining] -= 1
uri_parser = datum[:uri_parser] || Excon.defaults[:uri_parser]
location = get_header(datum, 'Location')
base_uri = Excon::Utils.request_uri(datum)
uri = uri_parser.join(base_uri, location)
# delete old/redirect response and remote_ip
response = datum.delete(:response)
datum.delete(:remote_ip)
params = datum.dup
params.delete(:connection)
params.delete(:password)
params.delete(:stack)
params.delete(:user)
if [301, 302, 303].include?(response[:status])
params[:method] = :get
params.delete(:body)
params[:headers].delete('Content-Length')
end
params[:headers] = datum[:headers].dup
params[:headers].delete('Authorization')
params[:headers].delete('Proxy-Connection')
params[:headers].delete('Proxy-Authorization')
params[:headers].delete('Host')
params.merge!(
:scheme => uri.scheme || datum[:scheme],
:host => uri.host || datum[:host],
:hostname => uri.hostname || datum[:hostname],
:port => uri.port || datum[:port],
:path => uri.path,
:query => uri.query
)
params.merge!(:user => Utils.unescape_uri(uri.user)) if uri.user
params.merge!(:password => Utils.unescape_uri(uri.password)) if uri.password
response = Excon::Connection.new(params).request
datum.merge!({
:remote_ip => response.remote_ip,
:response => response.data
})
else
@stack.response_call(datum)
end
else
@stack.response_call(datum)
end
end
end
end
end
|