require "logger"
require "httpi/version"
require "httpi/request"
require "httpi/adapter"
# = HTTPI
#
# Executes HTTP requests using a predefined adapter.
# All request methods accept an HTTPI::Request and an optional adapter.
# They may also offer shortcut methods for executing basic requests.
# Also they all return an HTTPI::Response.
#
# == GET
#
# request = HTTPI::Request.new :url => "http://example.com"
# HTTPI.get request, :httpclient
#
# === Shortcuts
#
# HTTPI.get "http://example.com", :curb
#
# == POST
#
# request = HTTPI::Request.new
# request.url = "http://example.com"
# request.body = "xml"
#
# HTTPI.post request, :httpclient
#
# === Shortcuts
#
# HTTPI.post "http://example.com", "xml", :curb
#
# == HEAD
#
# request = HTTPI::Request.new :url => "http://example.com"
# HTTPI.head request, :httpclient
#
# === Shortcuts
#
# HTTPI.head "http://example.com", :curb
#
# == PUT
#
# request = HTTPI::Request.new
# request.url = "http://example.com"
# request.body = "xml"
#
# HTTPI.put request, :httpclient
#
# === Shortcuts
#
# HTTPI.put "http://example.com", "xml", :curb
#
# == DELETE
#
# request = HTTPI::Request.new :url => "http://example.com"
# HTTPI.delete request, :httpclient
#
# === Shortcuts
#
# HTTPI.delete "http://example.com", :curb
#
# == More control
#
# If you need more control over your request, you can access the HTTP client
# instance represented by your adapter in a block.
#
# HTTPI.get request do |http|
# http.follow_redirect_count = 3 # HTTPClient example
# end
module HTTPI
REQUEST_METHODS = [:get, :post, :head, :put, :delete]
DEFAULT_LOG_LEVEL = :warn
class << self
# Executes an HTTP GET request.
def get(request, adapter = nil)
request = Request.new :url => request if request.kind_of? String
with_adapter :get, request, adapter do |adapter|
yield adapter.client if block_given?
adapter.get request
end
end
# Executes an HTTP POST request.
def post(*args)
request, adapter = request_and_adapter_from(args)
with_adapter :post, request, adapter do |adapter|
yield adapter.client if block_given?
adapter.post request
end
end
# Executes an HTTP HEAD request.
def head(request, adapter = nil)
request = Request.new :url => request if request.kind_of? String
with_adapter :head, request, adapter do |adapter|
yield adapter.client if block_given?
adapter.head request
end
end
# Executes an HTTP PUT request.
def put(*args)
request, adapter = request_and_adapter_from(args)
with_adapter :put, request, adapter do |adapter|
yield adapter.client if block_given?
adapter.put request
end
end
# Executes an HTTP DELETE request.
def delete(request, adapter = nil)
request = Request.new :url => request if request.kind_of? String
with_adapter :delete, request, adapter do |adapter|
yield adapter.client if block_given?
adapter.delete request
end
end
# Executes an HTTP request for the given +method+.
def request(method, request, adapter = nil)
raise ArgumentError, "Invalid request method: #{method}" unless REQUEST_METHODS.include? method
send method, request, adapter
end
# Sets whether to log HTTP requests.
attr_writer :log
# Returns whether to log HTTP requests. Defaults to +true+.
def log?
@log != false
end
# Sets the logger to use.
attr_writer :logger
# Returns the logger. Defaults to an instance of +Logger+ writing to STDOUT.
def logger
@logger ||= ::Logger.new STDOUT
end
# Sets the log level.
attr_writer :log_level
# Returns the log level. Defaults to :debug.
def log_level
@log_level ||= DEFAULT_LOG_LEVEL
end
# Logs given +messages+.
def log(*messages)
logger.send log_level, messages.join(" ") if log?
end
# Reset the default config.
def reset_config!
@log = nil
@logger = nil
@log_level = nil
end
private
# Checks whether +args+ contains of an HTTPI::Request or a URL
# and a request body plus an optional adapter and returns an Array with
# an HTTPI::Request and (if given) an adapter.
def request_and_adapter_from(args)
return args if args[0].kind_of? Request
[Request.new(:url => args[0], :body => args[1]), args[2]]
end
# Expects a request +method+, a +request+ and an +adapter+ (defaults to
# Adapter.use) and yields an instance of the adapter to a given block.
def with_adapter(method, request, adapter)
adapter ||= Adapter.use
adapter, adapter_class = Adapter.find adapter
HTTPI.logger.debug "HTTPI executes HTTP #{method.to_s.upcase} using the #{adapter} adapter"
yield adapter_class.new(request)
end
end
end