danbooru::http: support automatically following redirects.

Replace http.rb's builtin redirect following option with our own
redirect follower. This fixes an issue with http.rb losing cookies after
following a redirect.
This commit is contained in:
evazion
2020-06-21 03:57:14 -05:00
parent 71b0bc6c0f
commit 05d7355ebb
3 changed files with 57 additions and 14 deletions

View File

@@ -1,5 +1,6 @@
require "danbooru/http/html_adapter"
require "danbooru/http/xml_adapter"
require "danbooru/http/redirector"
require "danbooru/http/retriable"
require "danbooru/http/session"
@@ -11,12 +12,24 @@ module Danbooru
DEFAULT_TIMEOUT = 10
MAX_REDIRECTS = 5
attr_writer :cache, :max_size, :http
attr_accessor :cache, :max_size, :http
class << self
delegate :get, :head, :put, :post, :delete, :cache, :follow, :max_size, :timeout, :auth, :basic_auth, :headers, :cookies, :use, :public_only, :download_media, to: :new
end
def initialize
@http ||=
::Danbooru::Http::ApplicationClient.new
.timeout(DEFAULT_TIMEOUT)
.headers(Danbooru.config.http_headers)
.headers("Accept-Encoding" => "gzip")
.use(:auto_inflate)
.use(:retriable)
.use(redirector: { max_redirects: MAX_REDIRECTS })
.use(:session)
end
def get(url, **options)
request(:get, url, **options)
end
@@ -147,16 +160,5 @@ module Danbooru
def fake_response(status, body)
::HTTP::Response.new(status: status, version: "1.1", body: ::HTTP::Response::Body.new(body))
end
def http
@http ||=
::Danbooru::Http::ApplicationClient.new
.follow(strict: false, max_hops: MAX_REDIRECTS)
.use(:session)
.timeout(DEFAULT_TIMEOUT)
.use(:auto_inflate)
.headers(Danbooru.config.http_headers)
.headers("Accept-Encoding" => "gzip")
end
end
end

View File

@@ -0,0 +1,40 @@
# A HTTP::Feature that automatically follows HTTP redirects.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
module Danbooru
class Http
class Redirector < HTTP::Feature
HTTP::Options.register_feature :redirector, self
attr_reader :max_redirects
def initialize(max_redirects: 5)
@max_redirects = max_redirects
end
def perform(request, &block)
response = yield request
redirects = max_redirects
while response.status.redirect?
raise HTTP::Redirector::TooManyRedirectsError if redirects <= 0
response = yield build_redirect(request, response)
redirects -= 1
end
response
end
def build_redirect(request, response)
location = response.headers["Location"].to_s
uri = HTTP::URI.parse(location)
verb = request.verb
verb = :get if response.status == 303 && !request.verb.in?([:get, :head])
request.redirect(uri, verb)
end
end
end
end

View File

@@ -5,10 +5,11 @@ class NicoSeigaApiClient
attr_reader :http
# XXX temp disable following redirects.
def initialize(work_id:, type:, http: Danbooru::Http.follow(nil))
def initialize(work_id:, type:)
@work_id = work_id
@work_type = type
@http = http
@http = Danbooru::Http.new
@http.http.default_options.features.reject! { |name, _| name == :redirector }
end
def image_ids