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:
@@ -1,5 +1,6 @@
|
|||||||
require "danbooru/http/html_adapter"
|
require "danbooru/http/html_adapter"
|
||||||
require "danbooru/http/xml_adapter"
|
require "danbooru/http/xml_adapter"
|
||||||
|
require "danbooru/http/redirector"
|
||||||
require "danbooru/http/retriable"
|
require "danbooru/http/retriable"
|
||||||
require "danbooru/http/session"
|
require "danbooru/http/session"
|
||||||
|
|
||||||
@@ -11,12 +12,24 @@ module Danbooru
|
|||||||
DEFAULT_TIMEOUT = 10
|
DEFAULT_TIMEOUT = 10
|
||||||
MAX_REDIRECTS = 5
|
MAX_REDIRECTS = 5
|
||||||
|
|
||||||
attr_writer :cache, :max_size, :http
|
attr_accessor :cache, :max_size, :http
|
||||||
|
|
||||||
class << self
|
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
|
delegate :get, :head, :put, :post, :delete, :cache, :follow, :max_size, :timeout, :auth, :basic_auth, :headers, :cookies, :use, :public_only, :download_media, to: :new
|
||||||
end
|
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)
|
def get(url, **options)
|
||||||
request(:get, url, **options)
|
request(:get, url, **options)
|
||||||
end
|
end
|
||||||
@@ -147,16 +160,5 @@ module Danbooru
|
|||||||
def fake_response(status, body)
|
def fake_response(status, body)
|
||||||
::HTTP::Response.new(status: status, version: "1.1", body: ::HTTP::Response::Body.new(body))
|
::HTTP::Response.new(status: status, version: "1.1", body: ::HTTP::Response::Body.new(body))
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
40
app/logical/danbooru/http/redirector.rb
Normal file
40
app/logical/danbooru/http/redirector.rb
Normal 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
|
||||||
@@ -5,10 +5,11 @@ class NicoSeigaApiClient
|
|||||||
attr_reader :http
|
attr_reader :http
|
||||||
|
|
||||||
# XXX temp disable following redirects.
|
# 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_id = work_id
|
||||||
@work_type = type
|
@work_type = type
|
||||||
@http = http
|
@http = Danbooru::Http.new
|
||||||
|
@http.http.default_options.features.reject! { |name, _| name == :redirector }
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_ids
|
def image_ids
|
||||||
|
|||||||
Reference in New Issue
Block a user