mirror of
https://github.com/lostisland/faraday.git
synced 2025-08-29 00:03:58 -04:00
merge
This commit is contained in:
commit
647c8fe6e1
@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["rick"]
|
||||
s.date = %q{2010-05-28}
|
||||
s.date = %q{2010-10-02}
|
||||
s.description = %q{HTTP/REST API client library with pluggable components}
|
||||
s.email = %q{technoweenie@gmail.com}
|
||||
s.extra_rdoc_files = [
|
||||
@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
||||
"VERSION",
|
||||
"faraday.gemspec",
|
||||
"lib/faraday.rb",
|
||||
"lib/faraday/adapter/action_dispatch.rb",
|
||||
"lib/faraday/adapter/net_http.rb",
|
||||
"lib/faraday/adapter/patron.rb",
|
||||
"lib/faraday/adapter/test.rb",
|
||||
@ -39,6 +40,7 @@ Gem::Specification.new do |s|
|
||||
"lib/faraday/response.rb",
|
||||
"lib/faraday/response/active_support_json.rb",
|
||||
"lib/faraday/response/yajl.rb",
|
||||
"lib/faraday/utils.rb",
|
||||
"test/adapters/live_test.rb",
|
||||
"test/adapters/test_middleware_test.rb",
|
||||
"test/adapters/typhoeus_test.rb",
|
||||
@ -53,7 +55,7 @@ Gem::Specification.new do |s|
|
||||
s.homepage = %q{http://github.com/technoweenie/faraday}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.3.6}
|
||||
s.rubygems_version = %q{1.3.7}
|
||||
s.summary = %q{HTTP/REST API client library}
|
||||
s.test_files = [
|
||||
"test/adapters/live_test.rb",
|
||||
@ -72,7 +74,7 @@ Gem::Specification.new do |s|
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<rack>, [">= 1.0.1"])
|
||||
s.add_runtime_dependency(%q<addressable>, [">= 2.1.1"])
|
||||
else
|
||||
|
@ -1,5 +1,3 @@
|
||||
require 'rack/utils'
|
||||
|
||||
module Faraday
|
||||
class << self
|
||||
attr_accessor :default_adapter
|
||||
@ -49,19 +47,21 @@ module Faraday
|
||||
|
||||
extend AutoloadHelper
|
||||
|
||||
autoload_all 'faraday',
|
||||
:Adapter => 'adapter',
|
||||
:Connection => 'connection',
|
||||
autoload_all 'faraday',
|
||||
:Middleware => 'middleware',
|
||||
:Builder => 'builder',
|
||||
:Request => 'request',
|
||||
:Response => 'response',
|
||||
:CompositeReadIO => 'upload_io',
|
||||
:UploadIO => 'upload_io',
|
||||
:Parts => 'upload_io',
|
||||
:Error => 'error'
|
||||
:Parts => 'upload_io'
|
||||
end
|
||||
|
||||
require 'faraday/utils'
|
||||
require 'faraday/connection'
|
||||
require 'faraday/adapter'
|
||||
require 'faraday/error'
|
||||
|
||||
# not pulling in active-support JUST for this method.
|
||||
class Object
|
||||
# Yields <code>x</code> to the block, and then returns <code>x</code>.
|
||||
|
@ -56,7 +56,7 @@ module Faraday
|
||||
|
||||
@app.call env
|
||||
rescue Errno::ECONNREFUSED
|
||||
raise Error::ConnectionFailed, "connection refused"
|
||||
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
|
||||
end
|
||||
|
||||
def net_http_class(env)
|
||||
|
@ -26,7 +26,7 @@ module Faraday
|
||||
|
||||
@app.call env
|
||||
rescue Errno::ECONNREFUSED
|
||||
raise Error::ConnectionFailed, "connection refused"
|
||||
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
|
||||
end
|
||||
|
||||
# TODO: build in support for multipart streaming if patron supports it.
|
||||
|
@ -19,7 +19,7 @@ module Faraday
|
||||
class Stubs
|
||||
def initialize
|
||||
# {:get => [Stub, Stub]}
|
||||
@stack = {}
|
||||
@stack, @consumed = {}, {}
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
@ -29,8 +29,15 @@ module Faraday
|
||||
|
||||
def match(request_method, path, body)
|
||||
return false if !@stack.key?(request_method)
|
||||
stub = @stack[request_method].detect { |stub| stub.matches?(path, body) }
|
||||
@stack[request_method].delete stub
|
||||
stack = @stack[request_method]
|
||||
consumed = (@consumed[request_method] ||= [])
|
||||
|
||||
if stub = matches?(stack, path, body)
|
||||
consumed << stack.delete(stub)
|
||||
stub
|
||||
else
|
||||
matches?(consumed, path, body)
|
||||
end
|
||||
end
|
||||
|
||||
def get(path, &block)
|
||||
@ -53,10 +60,6 @@ module Faraday
|
||||
new_stub(:delete, path, &block)
|
||||
end
|
||||
|
||||
def new_stub(request_method, path, body=nil, &block)
|
||||
(@stack[request_method] ||= []) << Stub.new(path, body, block)
|
||||
end
|
||||
|
||||
# Raises an error if any of the stubbed calls have not been made.
|
||||
def verify_stubbed_calls
|
||||
failed_stubs = []
|
||||
@ -69,6 +72,16 @@ module Faraday
|
||||
end
|
||||
raise failed_stubs.join(" ") unless failed_stubs.size == 0
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def new_stub(request_method, path, body=nil, &block)
|
||||
(@stack[request_method] ||= []) << Stub.new(path, body, block)
|
||||
end
|
||||
|
||||
def matches?(stack, path, body)
|
||||
stack.detect { |stub| stub.matches?(path, body) }
|
||||
end
|
||||
end
|
||||
|
||||
class Stub < Struct.new(:path, :body, :block)
|
||||
@ -91,17 +104,8 @@ module Faraday
|
||||
yield stubs
|
||||
end
|
||||
|
||||
def request_uri(url)
|
||||
(url.path != "" ? url.path : "/") +
|
||||
(url.query ? "?#{sort_query_params(url.query)}" : "")
|
||||
end
|
||||
|
||||
def sort_query_params(query)
|
||||
query.split('&').sort.join('&')
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if stub = stubs.match(env[:method], request_uri(env[:url]), env[:body])
|
||||
if stub = stubs.match(env[:method], Faraday::Utils.normalize_path(env[:url]), env[:body])
|
||||
status, headers, body = stub.block.call(env)
|
||||
env.update \
|
||||
:status => status,
|
||||
|
@ -43,7 +43,7 @@ module Faraday
|
||||
|
||||
@app.call env
|
||||
rescue Errno::ECONNREFUSED
|
||||
raise Error::ConnectionFailed, "connection refused"
|
||||
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
|
||||
end
|
||||
|
||||
def in_parallel(options = {})
|
||||
|
@ -4,20 +4,7 @@ require 'base64'
|
||||
|
||||
module Faraday
|
||||
class Connection
|
||||
include Addressable, Rack::Utils
|
||||
|
||||
HEADERS = Hash.new do |h, k|
|
||||
if k.respond_to?(:to_str)
|
||||
k
|
||||
else
|
||||
k.to_s.split('_'). # :user_agent => %w(user agent)
|
||||
each { |w| w.capitalize! }. # => %w(User Agent)
|
||||
join('-') # => "User-Agent"
|
||||
end
|
||||
end
|
||||
HEADERS.update \
|
||||
:etag => "ETag"
|
||||
HEADERS.values.each { |v| v.freeze }
|
||||
include Addressable, Faraday::Utils
|
||||
|
||||
METHODS = Set.new [:get, :post, :put, :delete, :head]
|
||||
METHODS_WITH_BODIES = Set.new [:post, :put]
|
||||
@ -226,33 +213,6 @@ module Faraday
|
||||
uri
|
||||
end
|
||||
|
||||
# turns param keys into strings
|
||||
def merge_params(existing_params, new_params)
|
||||
new_params.each do |key, value|
|
||||
existing_params[key.to_s] = value
|
||||
end
|
||||
end
|
||||
|
||||
# turns headers keys and values into strings. Look up symbol keys in the
|
||||
# the HEADERS hash.
|
||||
#
|
||||
# h = merge_headers(HeaderHash.new, :content_type => 'text/plain')
|
||||
# h['Content-Type'] # = 'text/plain'
|
||||
#
|
||||
def merge_headers(existing_headers, new_headers)
|
||||
new_headers.each do |key, value|
|
||||
existing_headers[HEADERS[key]] = value.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
|
||||
# as spaces.
|
||||
def escape(s)
|
||||
s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) do
|
||||
'%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
|
||||
end
|
||||
end
|
||||
|
||||
def proxy_arg_to_uri(arg)
|
||||
case arg
|
||||
when String then URI.parse(arg)
|
||||
|
@ -1,7 +1,31 @@
|
||||
module Faraday
|
||||
module Error
|
||||
class ClientError < StandardError; end
|
||||
class ClientError < StandardError
|
||||
def initialize(exception)
|
||||
@inner_exception = exception
|
||||
end
|
||||
|
||||
def message
|
||||
@inner_exception.message
|
||||
end
|
||||
|
||||
def backtrace
|
||||
@inner_exception.backtrace
|
||||
end
|
||||
|
||||
alias to_str message
|
||||
|
||||
def to_s
|
||||
@inner_exception.to_s
|
||||
end
|
||||
|
||||
def inspect
|
||||
@inner_exception.inspect
|
||||
end
|
||||
end
|
||||
|
||||
class ConnectionFailed < ClientError; end
|
||||
class ResourceNotFound < ClientError; end
|
||||
class ParsingError < ClientError; end
|
||||
end
|
||||
end
|
||||
|
@ -8,16 +8,23 @@ module Faraday
|
||||
|
||||
def self.register_on_complete(env)
|
||||
env[:response].on_complete do |finished_env|
|
||||
finished_env[:body] = ActiveSupport::JSON.decode(finished_env[:body])
|
||||
finished_env[:body] = parse(finished_env[:body])
|
||||
|
||||
end
|
||||
end
|
||||
rescue LoadError, NameError => e
|
||||
self.load_error = e
|
||||
end
|
||||
|
||||
|
||||
def initialize(app)
|
||||
super
|
||||
@parser = nil
|
||||
end
|
||||
|
||||
def self.parse(body)
|
||||
ActiveSupport::JSON.decode(body)
|
||||
rescue Object => err
|
||||
raise Faraday::Error::ParsingError.new(err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -5,16 +5,22 @@ module Faraday
|
||||
|
||||
def self.register_on_complete(env)
|
||||
env[:response].on_complete do |finished_env|
|
||||
finished_env[:body] = Yajl::Parser.parse(finished_env[:body])
|
||||
finished_env[:body] = parse(finished_env[:body])
|
||||
end
|
||||
end
|
||||
rescue LoadError, NameError => e
|
||||
self.load_error = e
|
||||
end
|
||||
|
||||
|
||||
def initialize(app)
|
||||
super
|
||||
@parser = nil
|
||||
end
|
||||
|
||||
def self.parse(body)
|
||||
Yajl::Parser.parse(body)
|
||||
rescue Object => err
|
||||
raise Faraday::Error::ParsingError.new(err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
64
lib/faraday/utils.rb
Normal file
64
lib/faraday/utils.rb
Normal file
@ -0,0 +1,64 @@
|
||||
require 'rack/utils'
|
||||
module Faraday
|
||||
module Utils
|
||||
include Rack::Utils
|
||||
|
||||
extend Rack::Utils
|
||||
extend self
|
||||
|
||||
HEADERS = Hash.new do |h, k|
|
||||
if k.respond_to?(:to_str)
|
||||
k
|
||||
else
|
||||
k.to_s.split('_'). # :user_agent => %w(user agent)
|
||||
each { |w| w.capitalize! }. # => %w(User Agent)
|
||||
join('-') # => "User-Agent"
|
||||
end
|
||||
end
|
||||
|
||||
HEADERS.merge! :etag => "ETag"
|
||||
HEADERS.values.each { |v| v.freeze }
|
||||
|
||||
# Make Rack::Utils build_query method public.
|
||||
public :build_query
|
||||
|
||||
# Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
|
||||
# as spaces.
|
||||
def escape(s)
|
||||
s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) do
|
||||
'%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
|
||||
end
|
||||
end
|
||||
|
||||
# Turns param keys into strings
|
||||
def merge_params(existing_params, new_params)
|
||||
new_params.each do |key, value|
|
||||
existing_params[key.to_s] = value
|
||||
end
|
||||
end
|
||||
|
||||
# Turns headers keys and values into strings. Look up symbol keys in the
|
||||
# the HEADERS hash.
|
||||
#
|
||||
# h = merge_headers(HeaderHash.new, :content_type => 'text/plain')
|
||||
# h['Content-Type'] # = 'text/plain'
|
||||
#
|
||||
def merge_headers(existing_headers, new_headers)
|
||||
new_headers.each do |key, value|
|
||||
existing_headers[HEADERS[key]] = value.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Receives a URL and returns just the path with the query string sorted.
|
||||
def normalize_path(url)
|
||||
(url.path != "" ? url.path : "/") +
|
||||
(url.query ? "?#{sort_query_params(url.query)}" : "")
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def sort_query_params(query)
|
||||
query.split('&').sort.join('&')
|
||||
end
|
||||
end
|
||||
end
|
@ -22,5 +22,16 @@ module Adapters
|
||||
def test_middleware_with_simple_path_sets_body
|
||||
assert_equal 'hello', @resp.body
|
||||
end
|
||||
|
||||
def test_middleware_can_be_called_several_times
|
||||
assert_equal 'hello', @conn.get("/hello").body
|
||||
end
|
||||
|
||||
def test_middleware_allow_different_outcomes_for_the_same_request
|
||||
@stubs.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'hello'] }
|
||||
@stubs.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'world'] }
|
||||
assert_equal 'hello', @conn.get("/hello").body
|
||||
assert_equal 'world', @conn.get("/hello").body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,9 +6,11 @@ class RequestMiddlewareTest < Faraday::TestCase
|
||||
next if !encoder.loaded?
|
||||
|
||||
define_method "test_encodes_json_with_#{key}" do
|
||||
raw_json = create_json_connection(encoder).post('echo_body', :a => 1).body
|
||||
resp = create_json_connection(encoder).post('echo_body', :a => 1)
|
||||
raw_json = resp.body
|
||||
raw_json.gsub! /: 1/, ':1' # sometimes rails_json adds a space
|
||||
assert_equal %({"a":1}), raw_json
|
||||
assert_match /json/, resp.headers['Content-Type']
|
||||
end
|
||||
end
|
||||
|
||||
@ -17,7 +19,12 @@ private
|
||||
Faraday::Connection.new do |b|
|
||||
b.use encoder
|
||||
b.adapter :test do |stub|
|
||||
stub.post('echo_body') { |env| [200, {'Content-Type' => 'text/html'}, env[:body]] }
|
||||
stub.post('echo_body') do |env|
|
||||
[200,
|
||||
{'Content-Type' => env[:request_headers]['Content-Type']},
|
||||
env[:body]
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,7 +4,7 @@ class ResponseMiddlewareTest < Faraday::TestCase
|
||||
[:yajl, :rails_json].each do |key|
|
||||
encoder = Faraday::Response.lookup_module(key)
|
||||
next if !encoder.loaded?
|
||||
|
||||
|
||||
define_method "test_uses_#{key}_to_parse_json_content" do
|
||||
response = create_json_connection(encoder).get('json')
|
||||
assert response.success?
|
||||
@ -22,6 +22,12 @@ class ResponseMiddlewareTest < Faraday::TestCase
|
||||
assert response.success?
|
||||
assert !response.body
|
||||
end
|
||||
|
||||
define_method "test_use_#{key}_to_raise_Faraday_Error_Parsing_with_no_json_content" do
|
||||
assert_raises Faraday::Error::ParsingError do
|
||||
response = create_json_connection(encoder).get('bad_json')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_json_connection(encoder)
|
||||
@ -30,6 +36,7 @@ class ResponseMiddlewareTest < Faraday::TestCase
|
||||
stub.get('json') { [200, {'Content-Type' => 'text/html'}, "[1,2,3]"] }
|
||||
stub.get('blank') { [200, {'Content-Type' => 'text/html'}, ''] }
|
||||
stub.get('nil') { [200, {'Content-Type' => 'text/html'}, nil] }
|
||||
stub.get("bad_json") {[200, {'Content-Type' => 'text/html'}, '<body></body>']}
|
||||
end
|
||||
b.use encoder
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user