131 lines
3.2 KiB
Ruby
131 lines
3.2 KiB
Ruby
require 'http/headers'
|
|
require 'openssl'
|
|
require 'socket'
|
|
|
|
module HTTP
|
|
class Options
|
|
# How to format the response [:object, :body, :parse_body]
|
|
attr_accessor :response
|
|
|
|
# HTTP headers to include in the request
|
|
attr_accessor :headers
|
|
|
|
# Query string params to add to the url
|
|
attr_accessor :params
|
|
|
|
# Form data to embed in the request
|
|
attr_accessor :form
|
|
|
|
# JSON data to embed in the request
|
|
attr_accessor :json
|
|
|
|
# Explicit request body of the request
|
|
attr_accessor :body
|
|
|
|
# HTTP proxy to route request
|
|
attr_accessor :proxy
|
|
|
|
# Socket classes
|
|
attr_accessor :socket_class, :ssl_socket_class
|
|
|
|
# SSL context
|
|
attr_accessor :ssl_context
|
|
|
|
# Follow redirects
|
|
attr_accessor :follow
|
|
|
|
protected :response=, :headers=, :proxy=, :params=, :form=, :json=, :follow=
|
|
|
|
@default_socket_class = TCPSocket
|
|
@default_ssl_socket_class = OpenSSL::SSL::SSLSocket
|
|
|
|
class << self
|
|
attr_accessor :default_socket_class, :default_ssl_socket_class
|
|
|
|
def new(options = {})
|
|
return options if options.is_a?(self)
|
|
super
|
|
end
|
|
end
|
|
|
|
def initialize(options = {})
|
|
@response = options[:response] || :auto
|
|
@proxy = options[:proxy] || {}
|
|
@body = options[:body]
|
|
@params = options[:params]
|
|
@form = options[:form]
|
|
@json = options[:json]
|
|
@follow = options[:follow]
|
|
|
|
@headers = HTTP::Headers.coerce(options[:headers] || {})
|
|
|
|
@socket_class = options[:socket_class] || self.class.default_socket_class
|
|
@ssl_socket_class = options[:ssl_socket_class] || self.class.default_ssl_socket_class
|
|
@ssl_context = options[:ssl_context]
|
|
end
|
|
|
|
def with_headers(headers)
|
|
dup do |opts|
|
|
opts.headers = self.headers.merge(headers)
|
|
end
|
|
end
|
|
|
|
%w[proxy params form json body follow].each do |method_name|
|
|
class_eval <<-RUBY, __FILE__, __LINE__
|
|
def with_#{method_name}(value)
|
|
dup { |opts| opts.#{method_name} = value }
|
|
end
|
|
RUBY
|
|
end
|
|
|
|
def [](option)
|
|
send(option) rescue nil
|
|
end
|
|
|
|
def merge(other)
|
|
h1, h2 = to_hash, other.to_hash
|
|
merged = h1.merge(h2) do |k, v1, v2|
|
|
case k
|
|
when :headers
|
|
v1.merge(v2)
|
|
else
|
|
v2
|
|
end
|
|
end
|
|
|
|
self.class.new(merged)
|
|
end
|
|
|
|
def to_hash
|
|
# FIXME: hardcoding these fields blows! We should have a declarative
|
|
# way of specifying all the options fields, and ensure they *all*
|
|
# get serialized here, rather than manually having to add them each time
|
|
{
|
|
:response => response,
|
|
:headers => headers.to_h,
|
|
:proxy => proxy,
|
|
:params => params,
|
|
:form => form,
|
|
:json => json,
|
|
:body => body,
|
|
:follow => follow,
|
|
:socket_class => socket_class,
|
|
:ssl_socket_class => ssl_socket_class,
|
|
:ssl_context => ssl_context
|
|
}
|
|
end
|
|
|
|
def dup
|
|
dupped = super
|
|
yield(dupped) if block_given?
|
|
dupped
|
|
end
|
|
|
|
private
|
|
|
|
def argument_error!(message)
|
|
fail(Error, message, caller[1..-1])
|
|
end
|
|
end
|
|
end
|