This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Faraday
|
||||
class Request
|
||||
# Request middleware for the Authorization HTTP header
|
||||
class Authorization < Faraday::Middleware
|
||||
KEY = 'Authorization'
|
||||
|
||||
# @param app [#call]
|
||||
# @param type [String, Symbol] Type of Authorization
|
||||
# @param params [Array<String, Proc, #call>] parameters to build the Authorization header.
|
||||
# If the type is `:basic`, then these can be a login and password pair.
|
||||
# Otherwise, a single value is expected that will be appended after the type.
|
||||
# This value can be a proc or an object responding to `.call`, in which case
|
||||
# it will be invoked on each request.
|
||||
def initialize(app, type, *params)
|
||||
@type = type
|
||||
@params = params
|
||||
super(app)
|
||||
end
|
||||
|
||||
# @param env [Faraday::Env]
|
||||
def on_request(env)
|
||||
return if env.request_headers[KEY]
|
||||
|
||||
env.request_headers[KEY] = header_from(@type, env, *@params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @param type [String, Symbol]
|
||||
# @param env [Faraday::Env]
|
||||
# @param params [Array]
|
||||
# @return [String] a header value
|
||||
def header_from(type, env, *params)
|
||||
if type.to_s.casecmp('basic').zero? && params.size == 2
|
||||
Utils.basic_header_from(*params)
|
||||
elsif params.size != 1
|
||||
raise ArgumentError, "Unexpected params received (got #{params.size} instead of 1)"
|
||||
else
|
||||
value = params.first
|
||||
if (value.is_a?(Proc) && value.arity == 1) || (value.respond_to?(:call) && value.method(:call).arity == 1)
|
||||
value = value.call(env)
|
||||
elsif value.is_a?(Proc) || value.respond_to?(:call)
|
||||
value = value.call
|
||||
end
|
||||
"#{type} #{value}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Request.register_middleware(authorization: Faraday::Request::Authorization)
|
||||
@@ -0,0 +1,58 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Faraday
|
||||
class Request
|
||||
# Middleware for instrumenting Requests.
|
||||
class Instrumentation < Faraday::Middleware
|
||||
# Options class used in Request::Instrumentation class.
|
||||
Options = Faraday::Options.new(:name, :instrumenter) do
|
||||
remove_method :name
|
||||
# @return [String]
|
||||
def name
|
||||
self[:name] ||= 'request.faraday'
|
||||
end
|
||||
|
||||
remove_method :instrumenter
|
||||
# @return [Class]
|
||||
def instrumenter
|
||||
self[:instrumenter] ||= ActiveSupport::Notifications
|
||||
end
|
||||
end
|
||||
|
||||
# Instruments requests using Active Support.
|
||||
#
|
||||
# Measures time spent only for synchronous requests.
|
||||
#
|
||||
# @example Using ActiveSupport::Notifications to measure time spent
|
||||
# for Faraday requests.
|
||||
# ActiveSupport::Notifications
|
||||
# .subscribe('request.faraday') do |name, starts, ends, _, env|
|
||||
# url = env[:url]
|
||||
# http_method = env[:method].to_s.upcase
|
||||
# duration = ends - starts
|
||||
# $stderr.puts '[%s] %s %s (%.3f s)' %
|
||||
# [url.host, http_method, url.request_uri, duration]
|
||||
# end
|
||||
# @param app [#call]
|
||||
# @param options [nil, Hash] Options hash
|
||||
# @option options [String] :name ('request.faraday')
|
||||
# Name of the instrumenter
|
||||
# @option options [Class] :instrumenter (ActiveSupport::Notifications)
|
||||
# Active Support instrumenter class.
|
||||
def initialize(app, options = nil)
|
||||
super(app)
|
||||
@name, @instrumenter = Options.from(options)
|
||||
.values_at(:name, :instrumenter)
|
||||
end
|
||||
|
||||
# @param env [Faraday::Env]
|
||||
def call(env)
|
||||
@instrumenter.instrument(@name, env) do
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Request.register_middleware(instrumentation: Faraday::Request::Instrumentation)
|
||||
@@ -0,0 +1,70 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'json'
|
||||
|
||||
module Faraday
|
||||
class Request
|
||||
# Request middleware that encodes the body as JSON.
|
||||
#
|
||||
# Processes only requests with matching Content-type or those without a type.
|
||||
# If a request doesn't have a type but has a body, it sets the Content-type
|
||||
# to JSON MIME-type.
|
||||
#
|
||||
# Doesn't try to encode bodies that already are in string form.
|
||||
class Json < Middleware
|
||||
MIME_TYPE = 'application/json'
|
||||
MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?json$}
|
||||
|
||||
def on_request(env)
|
||||
match_content_type(env) do |data|
|
||||
env[:body] = encode(data)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def encode(data)
|
||||
if options[:encoder].is_a?(Array) && options[:encoder].size >= 2
|
||||
options[:encoder][0].public_send(options[:encoder][1], data)
|
||||
elsif options[:encoder].respond_to?(:dump)
|
||||
options[:encoder].dump(data)
|
||||
else
|
||||
::JSON.generate(data)
|
||||
end
|
||||
end
|
||||
|
||||
def match_content_type(env)
|
||||
return unless process_request?(env)
|
||||
|
||||
env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
|
||||
yield env[:body] unless env[:body].respond_to?(:to_str)
|
||||
end
|
||||
|
||||
def process_request?(env)
|
||||
type = request_type(env)
|
||||
body?(env) && (type.empty? || type.match?(MIME_TYPE_REGEX))
|
||||
end
|
||||
|
||||
def body?(env)
|
||||
body = env[:body]
|
||||
case body
|
||||
when true, false
|
||||
true
|
||||
when nil
|
||||
# NOTE: nil can be converted to `"null"`, but this middleware doesn't process `nil` for the compatibility.
|
||||
false
|
||||
else
|
||||
!(body.respond_to?(:to_str) && body.empty?)
|
||||
end
|
||||
end
|
||||
|
||||
def request_type(env)
|
||||
type = env[:request_headers][CONTENT_TYPE].to_s
|
||||
type = type.split(';', 2).first if type.index(';')
|
||||
type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Request.register_middleware(json: Faraday::Request::Json)
|
||||
@@ -0,0 +1,60 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Faraday
|
||||
class Request
|
||||
# Middleware for supporting urlencoded requests.
|
||||
class UrlEncoded < Faraday::Middleware
|
||||
unless defined?(::Faraday::Request::UrlEncoded::CONTENT_TYPE)
|
||||
CONTENT_TYPE = 'Content-Type'
|
||||
end
|
||||
|
||||
class << self
|
||||
attr_accessor :mime_type
|
||||
end
|
||||
self.mime_type = 'application/x-www-form-urlencoded'
|
||||
|
||||
# Encodes as "application/x-www-form-urlencoded" if not already encoded or
|
||||
# of another type.
|
||||
#
|
||||
# @param env [Faraday::Env]
|
||||
def call(env)
|
||||
match_content_type(env) do |data|
|
||||
params = Faraday::Utils::ParamsHash[data]
|
||||
env.body = params.to_query(env.params_encoder)
|
||||
end
|
||||
@app.call env
|
||||
end
|
||||
|
||||
# @param env [Faraday::Env]
|
||||
# @yield [request_body] Body of the request
|
||||
def match_content_type(env)
|
||||
return unless process_request?(env)
|
||||
|
||||
env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
|
||||
return if env.body.respond_to?(:to_str) || env.body.respond_to?(:read)
|
||||
|
||||
yield(env.body)
|
||||
end
|
||||
|
||||
# @param env [Faraday::Env]
|
||||
#
|
||||
# @return [Boolean] True if the request has a body and its Content-Type is
|
||||
# urlencoded.
|
||||
def process_request?(env)
|
||||
type = request_type(env)
|
||||
env.body && (type.empty? || (type == self.class.mime_type))
|
||||
end
|
||||
|
||||
# @param env [Faraday::Env]
|
||||
#
|
||||
# @return [String]
|
||||
def request_type(env)
|
||||
type = env.request_headers[CONTENT_TYPE].to_s
|
||||
type = type.split(';', 2).first if type.index(';')
|
||||
type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Request.register_middleware(url_encoded: Faraday::Request::UrlEncoded)
|
||||
Reference in New Issue
Block a user