Skip to content

Commit

Permalink
Merge pull request #7 from blambeau/client-injection
Browse files Browse the repository at this point in the history
Client dependency injection + Chainable is not chainable
  • Loading branch information
tarcieri committed Feb 13, 2012
2 parents 3b33264 + 18a939e commit e28042e
Show file tree
Hide file tree
Showing 15 changed files with 397 additions and 125 deletions.
3 changes: 1 addition & 2 deletions lib/http.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
require 'http/version'
require 'http/options'
require 'http/chainable'
require 'http/client'
require 'http/mime_type'
require 'http/parameters'
require 'http/response'
require 'http/event_callback'

# THIS IS ENTIRELY TEMPORARY, I ASSURE YOU
require 'net/https'
Expand Down
56 changes: 29 additions & 27 deletions lib/http/chainable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Http
module Chainable
# Request a get sans response body
def head(uri, options = {})
request :head, uri, {:response => :object}.merge(options)
request :head, uri, options
end

# Get a resource
Expand Down Expand Up @@ -47,34 +47,17 @@ def patch(uri, options = {})

# Make an HTTP request with the given verb
def request(verb, uri, options = {})
options[:response] ||= :parsed_body

if options[:headers]
headers = default_headers.merge options[:headers]
else
headers = default_headers
end

Client.new(uri).request verb, options.merge(:headers => headers, :callbacks => event_callbacks)
branch(options).request verb, uri
end

# Make a request invoking the given event callbacks
def on(event, &block)
unless [:request, :response].include?(event)
raise ArgumentError, "only :request and :response are valid events"
end
unless block_given?
raise ArgumentError, "no block specified for #{event} event"
end
unless block.arity == 1
raise ArgumentError, "block must accept only one argument"
end
EventCallback.new event, event_callbacks, &block
branch default_options.with_callback(event, block)
end

# Make a request with the given headers
def with_headers(headers)
Parameters.new default_headers.merge(headers)
branch default_options.with_headers(headers)
end
alias_method :with, :with_headers

Expand All @@ -89,20 +72,39 @@ def accept(type)
end
end

def default_options
@default_options ||= Options.new
end

def default_options=(opts)
@default_options = Options.new(opts)
end

def default_headers
@default_headers ||= {}
default_options.headers
end

def default_headers=(headers)
@default_headers = headers
@default_options = default_options.dup do |opts|
opts.headers = headers
end
end

def default_callbacks
default_options.callbacks
end

def event_callbacks
@event_callbacks ||= {}
def default_callbacks=(callbacks)
@default_options = default_options.dup do |opts|
opts.callbacks = callbacks
end
end

def event_callbacks=(callbacks)
@event_callbacks = callbacks
private

def branch(options)
Client.new(options)
end

end
end
75 changes: 14 additions & 61 deletions lib/http/client.rb
Original file line number Diff line number Diff line change
@@ -1,74 +1,25 @@
module Http
# We all know what HTTP clients are, right?
class Client
# I swear I'll document that nebulous options hash
def initialize(uri, options = {})
@uri = uri
@options = options
end
include Chainable

# Request a get sans response body
def head(options = {})
request :head, options
end
attr_reader :default_options

# Get a resource
def get(options = {})
request :get, options
end

# Post to a resource
def post(options = {})
request :post, options
end

# Put to a resource
def put(options = {})
request :put, options
end

# Delete a resource
def delete(options = {})
request :delete, options
end

# Echo the request back to the client
def trace(options = {})
request :trace, options
end

# Return the methods supported on the given URI
def options(options = {})
request :options, options
end

# Convert to a transparent TCP/IP tunnel
def connect(options = {})
request :connect, options
end

# Apply partial modifications to a resource
def patch(options = {})
request :patch, options
def initialize(default_options = {})
@default_options = Options.new(default_options)
end

# Make an HTTP request
def request(method, options = {})
options = @options.merge(options)

# prepare raw call arguments
uri = @uri
headers = options[:headers] || {}
form_data = options[:form]
callbacks = options[:callbacks] || {}
def request(method, uri, options = {})
opts = @default_options.merge(options)

# this will have to wait until we have an Http::Request object to yield
#callbacks[:request].each { |c| c.invoke(request) } if callbacks[:request]
#opts.callbacks[:request].each { |c| c.call(request) }

response = perform method, uri, headers, form_data
callbacks[:response].each { |c| c.invoke(response) } if callbacks[:response]
response = perform method, uri, opts.headers, opts.form
opts.callbacks[:response].each { |c| c.call(response) }

format_response response, options[:response]
format_response method, response, opts.response
end

#######
Expand Down Expand Up @@ -100,9 +51,11 @@ def perform(method, uri, headers, form_data = nil)
end
end

def format_response(response, option)
def format_response(method, response, option)
case option
when :object, NilClass
when :auto, NilClass
method == :head ? response : response.parse_body
when :object
response
when :parsed_body
response.parse_body
Expand Down
5 changes: 3 additions & 2 deletions lib/http/compat/curb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ def initialize(url = nil, method = nil, request_body = nil, headers = {})
end

def perform
client = Http::Client.new @url, :headers => @headers
response = client.send @method
client = Http::Client.new
options = {:response => :object, :headers => @headers}
response = client.request @method, @url, options
@response_code, @body_str = response.code, response.body
true
rescue SocketError => ex
Expand Down
16 changes: 0 additions & 16 deletions lib/http/event_callback.rb

This file was deleted.

109 changes: 109 additions & 0 deletions lib/http/options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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

# Form data to embed in the request
attr_accessor :form

# Before callbacks
attr_accessor :callbacks

protected :response=, :headers=, :form=, :callbacks=

def self.new(default = {})
return default if default.is_a?(Options)
super
end

def initialize(default = {})
@response = default[:response] || :auto
@headers = default[:headers] || {}
@form = default[:form] || nil
@callbacks = default[:callbacks] || {:request => [], :response => []}
end

def with_response(response)
unless [:auto, :object, :body, :parsed_body].include?(response)
argument_error! "invalid response type: #{response}"
end
dup do |opts|
opts.response = response
end
end

def with_headers(headers)
unless headers.respond_to?(:to_hash)
argument_error! "invalid headers: #{headers}"
end
dup do |opts|
opts.headers = self.headers.merge(headers.to_hash)
end
end

def with_form(form)
dup do |opts|
opts.form = form
end
end

def with_callback(event, callback)
unless callback.respond_to?(:call)
argument_error! "invalid callback: #{callback}"
end
unless callback.respond_to?(:arity) and callback.arity == 1
argument_error! "callback must accept only one argument"
end
unless [:request, :response].include?(event)
argument_error! "invalid callback event: #{event}"
end
dup do |opts|
opts.callbacks = callbacks.dup
opts.callbacks[event] = (callbacks[event].dup << callback)
end
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)
when :callbacks
v1.merge(v2){|event,l,r| (l+r).uniq}
else
v2
end
end
Options.new(merged)
end

def to_hash
{:response => response,
:headers => headers,
:form => form,
:callbacks => callbacks}
end

def dup
dupped = super
yield(dupped) if block_given?
dupped
end

private

def argument_error!(message)
raise ArgumentError, message, caller[1..-1]
end

end
end
17 changes: 0 additions & 17 deletions lib/http/parameters.rb

This file was deleted.

Loading

0 comments on commit e28042e

Please sign in to comment.