From 62366a2c691ebbd337319fe6a4198a2719faa123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 01:22:51 +0200 Subject: [PATCH 1/3] Extract and expose common URI methods in Faraday::Utils. --- lib/faraday.rb | 3 +- lib/faraday/adapter/test.rb | 11 +------ lib/faraday/connection.rb | 42 +------------------------ lib/faraday/utils.rb | 63 +++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 52 deletions(-) create mode 100644 lib/faraday/utils.rb diff --git a/lib/faraday.rb b/lib/faraday.rb index 92fced17..c18c794d 100644 --- a/lib/faraday.rb +++ b/lib/faraday.rb @@ -54,7 +54,8 @@ module Faraday :Builder => 'builder', :Request => 'request', :Response => 'response', - :Error => 'error' + :Error => 'error', + :Utils => 'utils' module Adapter extend AutoloadHelper diff --git a/lib/faraday/adapter/test.rb b/lib/faraday/adapter/test.rb index eb6b47cd..50531cda 100644 --- a/lib/faraday/adapter/test.rb +++ b/lib/faraday/adapter/test.rb @@ -91,17 +91,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, diff --git a/lib/faraday/connection.rb b/lib/faraday/connection.rb index adb4f7a6..79ad6b10 100644 --- a/lib/faraday/connection.rb +++ b/lib/faraday/connection.rb @@ -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) diff --git a/lib/faraday/utils.rb b/lib/faraday/utils.rb new file mode 100644 index 00000000..8da06b3a --- /dev/null +++ b/lib/faraday/utils.rb @@ -0,0 +1,63 @@ +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 \ No newline at end of file From 5bd3b864a68d0309b70501c078386ac7f04b1f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 01:23:12 +0200 Subject: [PATCH 2/3] Update gemspec. --- faraday.gemspec | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/faraday.gemspec b/faraday.gemspec index 498fd843..46d0a6c6 100644 --- a/faraday.gemspec +++ b/faraday.gemspec @@ -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, [">= 1.0.1"]) s.add_runtime_dependency(%q, [">= 2.1.1"]) else From 5918164275b9a9afd29ab11f7eac65b45db4c8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 01:35:50 +0200 Subject: [PATCH 3/3] Stubs in test mode can be called more than one time. --- lib/faraday/adapter/test.rb | 27 ++++++++++++++++++++------- test/adapters/test_middleware_test.rb | 11 +++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/faraday/adapter/test.rb b/lib/faraday/adapter/test.rb index 50531cda..fa5df8ce 100644 --- a/lib/faraday/adapter/test.rb +++ b/lib/faraday/adapter/test.rb @@ -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) diff --git a/test/adapters/test_middleware_test.rb b/test/adapters/test_middleware_test.rb index 7ef89dae..71b37309 100644 --- a/test/adapters/test_middleware_test.rb +++ b/test/adapters/test_middleware_test.rb @@ -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