This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'json'
|
||||
|
||||
module Faraday
|
||||
class Response
|
||||
# Parse response bodies as JSON.
|
||||
class Json < Middleware
|
||||
def initialize(app = nil, parser_options: nil, content_type: /\bjson$/, preserve_raw: false)
|
||||
super(app)
|
||||
@parser_options = parser_options
|
||||
@content_types = Array(content_type)
|
||||
@preserve_raw = preserve_raw
|
||||
|
||||
process_parser_options
|
||||
end
|
||||
|
||||
def on_complete(env)
|
||||
process_response(env) if parse_response?(env)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def process_response(env)
|
||||
env[:raw_body] = env[:body] if @preserve_raw
|
||||
env[:body] = parse(env[:body])
|
||||
rescue StandardError, SyntaxError => e
|
||||
raise Faraday::ParsingError.new(e, env[:response])
|
||||
end
|
||||
|
||||
def parse(body)
|
||||
return if body.strip.empty?
|
||||
|
||||
decoder, method_name = @decoder_options
|
||||
|
||||
decoder.public_send(method_name, body, @parser_options || {})
|
||||
end
|
||||
|
||||
def parse_response?(env)
|
||||
process_response_type?(env) &&
|
||||
env[:body].respond_to?(:to_str)
|
||||
end
|
||||
|
||||
def process_response_type?(env)
|
||||
type = response_type(env)
|
||||
@content_types.empty? || @content_types.any? do |pattern|
|
||||
pattern.is_a?(Regexp) ? type.match?(pattern) : type == pattern
|
||||
end
|
||||
end
|
||||
|
||||
def response_type(env)
|
||||
type = env[:response_headers][CONTENT_TYPE].to_s
|
||||
type = type.split(';', 2).first if type.index(';')
|
||||
type
|
||||
end
|
||||
|
||||
def process_parser_options
|
||||
@decoder_options = @parser_options&.delete(:decoder)
|
||||
|
||||
@decoder_options =
|
||||
if @decoder_options.is_a?(Array) && @decoder_options.size >= 2
|
||||
@decoder_options.slice(0, 2)
|
||||
elsif @decoder_options.respond_to?(:load)
|
||||
[@decoder_options, :load]
|
||||
else
|
||||
[::JSON, :parse]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Response.register_middleware(json: Faraday::Response::Json)
|
||||
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'forwardable'
|
||||
require 'logger'
|
||||
require 'faraday/logging/formatter'
|
||||
|
||||
module Faraday
|
||||
class Response
|
||||
# Logger is a middleware that logs internal events in the HTTP request
|
||||
# lifecycle to a given Logger object. By default, this logs to STDOUT. See
|
||||
# Faraday::Logging::Formatter to see specifically what is logged.
|
||||
class Logger < Middleware
|
||||
def initialize(app, logger = nil, options = {})
|
||||
super(app)
|
||||
logger ||= ::Logger.new($stdout)
|
||||
formatter_class = options.delete(:formatter) || Logging::Formatter
|
||||
@formatter = formatter_class.new(logger: logger, options: options)
|
||||
yield @formatter if block_given?
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@formatter.request(env)
|
||||
super
|
||||
end
|
||||
|
||||
def on_complete(env)
|
||||
@formatter.response(env)
|
||||
end
|
||||
|
||||
def on_error(exc)
|
||||
@formatter.exception(exc) if @formatter.respond_to?(:exception)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Response.register_middleware(logger: Faraday::Response::Logger)
|
||||
@@ -0,0 +1,83 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Faraday
|
||||
class Response
|
||||
# RaiseError is a Faraday middleware that raises exceptions on common HTTP
|
||||
# client or server error responses.
|
||||
class RaiseError < Middleware
|
||||
# rubocop:disable Naming/ConstantName
|
||||
ClientErrorStatuses = (400...500)
|
||||
ServerErrorStatuses = (500...600)
|
||||
# rubocop:enable Naming/ConstantName
|
||||
|
||||
def on_complete(env)
|
||||
case env[:status]
|
||||
when 400
|
||||
raise Faraday::BadRequestError, response_values(env)
|
||||
when 401
|
||||
raise Faraday::UnauthorizedError, response_values(env)
|
||||
when 403
|
||||
raise Faraday::ForbiddenError, response_values(env)
|
||||
when 404
|
||||
raise Faraday::ResourceNotFound, response_values(env)
|
||||
when 407
|
||||
# mimic the behavior that we get with proxy requests with HTTPS
|
||||
msg = %(407 "Proxy Authentication Required")
|
||||
raise Faraday::ProxyAuthError.new(msg, response_values(env))
|
||||
when 408
|
||||
raise Faraday::RequestTimeoutError, response_values(env)
|
||||
when 409
|
||||
raise Faraday::ConflictError, response_values(env)
|
||||
when 422
|
||||
raise Faraday::UnprocessableEntityError, response_values(env)
|
||||
when 429
|
||||
raise Faraday::TooManyRequestsError, response_values(env)
|
||||
when ClientErrorStatuses
|
||||
raise Faraday::ClientError, response_values(env)
|
||||
when ServerErrorStatuses
|
||||
raise Faraday::ServerError, response_values(env)
|
||||
when nil
|
||||
raise Faraday::NilStatusError, response_values(env)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a hash of response data with the following keys:
|
||||
# - status
|
||||
# - headers
|
||||
# - body
|
||||
# - request
|
||||
#
|
||||
# The `request` key is omitted when the middleware is explicitly
|
||||
# configured with the option `include_request: false`.
|
||||
def response_values(env)
|
||||
response = {
|
||||
status: env.status,
|
||||
headers: env.response_headers,
|
||||
body: env.body
|
||||
}
|
||||
|
||||
# Include the request data by default. If the middleware was explicitly
|
||||
# configured to _not_ include request data, then omit it.
|
||||
return response unless options.fetch(:include_request, true)
|
||||
|
||||
response.merge(
|
||||
request: {
|
||||
method: env.method,
|
||||
url: env.url,
|
||||
url_path: env.url.path,
|
||||
params: query_params(env),
|
||||
headers: env.request_headers,
|
||||
body: env.request_body
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def query_params(env)
|
||||
env.request.params_encoder ||= Faraday::Utils.default_params_encoder
|
||||
env.params_encoder.decode(env.url.query)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Response.register_middleware(raise_error: Faraday::Response::RaiseError)
|
||||
Reference in New Issue
Block a user