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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
require 'puppet_forge/connection/connection_failure'
require 'faraday'
require 'faraday/follow_redirects'
module PuppetForge
# Provide a common mixin for adding a HTTP connection to classes.
#
# This module provides a common method for creating HTTP connections as well
# as reusing a single connection object between multiple classes. Including
# classes can invoke #conn to get a reasonably configured HTTP connection.
# Connection objects can be passed with the #conn= method.
#
# @example
# class HTTPThing
# include PuppetForge::Connection
# end
# thing = HTTPThing.new
# thing.conn = thing.make_connection('https://non-standard-forge.site')
#
# @api private
module Connection
attr_writer :conn
AUTHORIZATION_TOKEN_REGEX = /^[a-f0-9]{64}$/
USER_AGENT = "#{PuppetForge.user_agent} PuppetForge.gem/#{PuppetForge::VERSION} Faraday/#{Faraday::VERSION} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})".strip
def self.authorization=(token)
@authorization = token
# RK-229 Specific Workaround
# Capture instance specific proxy setting if defined.
if defined?(PuppetForge::V3::Base)
if old_conn = PuppetForge::V3::Base.instance_variable_get(:@conn)
self.proxy = old_conn.proxy.uri.to_s if old_conn.proxy
end
end
end
def self.authorization
@authorization
end
def self.proxy=(url)
url = nil if url.respond_to?(:empty?) && url.empty?
@proxy = url
end
def self.proxy
@proxy
end
def self.accept_language=(lang)
lang = nil if lang.respond_to?(:empty?) && lang.empty?
@accept_language = lang
end
def self.accept_language
@accept_language
end
# @param reset_connection [Boolean] flag to create a new connection every time this is called
# @param opts [Hash] Hash of connection options for Faraday
# @return [Faraday::Connection] An existing Faraday connection if one was
# already set, otherwise a new Faraday connection.
def conn(reset_connection = nil, opts = {})
new_auth = @conn && @conn.headers['Authorization'] != PuppetForge::Connection.authorization
new_proxy = @conn && ((@conn.proxy.nil? && PuppetForge::Connection.proxy) || (@conn.proxy && @conn.proxy.uri.to_s != PuppetForge::Connection.proxy))
new_lang = @conn && @conn.headers['Accept-Language'] != PuppetForge::Connection.accept_language
if reset_connection || new_auth || new_proxy || new_lang
default_connection(opts)
else
@conn ||= default_connection(opts)
end
end
# @param opts [Hash] Hash of connection options for Faraday
def default_connection(opts = {})
begin
# Use Typhoeus if available.
Gem::Specification.find_by_name('typhoeus', '~> 1.4')
require 'typhoeus/adapters/faraday'
adapter = :typhoeus
rescue Gem::LoadError
adapter = Faraday.default_adapter
end
make_connection(PuppetForge.host, [adapter], opts)
end
module_function :default_connection
# Generate a new Faraday connection for the given URL.
#
# @param url [String] the base URL for this connection
# @param opts [Hash] Hash of connection options for Faraday
# @return [Faraday::Connection]
def make_connection(url, adapter_args = nil, opts = {})
adapter_args ||= [Faraday.default_adapter]
options = { :headers => { :user_agent => USER_AGENT } }.merge(opts)
if token = PuppetForge::Connection.authorization
options[:headers][:authorization] = token =~ AUTHORIZATION_TOKEN_REGEX ? "Bearer #{token}" : token
end
if lang = PuppetForge::Connection.accept_language
options[:headers]['Accept-Language'] = lang
end
if proxy = PuppetForge::Connection.proxy
options[:proxy] = proxy
end
Faraday.new(url, options) do |builder|
builder.use Faraday::FollowRedirects::Middleware
builder.response(:json, :content_type => /\bjson$/, :parser_options => { :symbolize_names => true })
builder.response(:raise_error)
builder.use(:connection_failure)
builder.adapter(*adapter_args)
end
end
module_function :make_connection
end
end
|