shin-faraday 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ module Faraday
2
+ module Error
3
+ class ClientError < StandardError; end
4
+ class ConnectionFailed < ClientError; end
5
+ class ResourceNotFound < ClientError; end
6
+ class ParsingError < ClientError; end
7
+ end
8
+ end
@@ -0,0 +1,54 @@
1
+ module Faraday
2
+ class Middleware
3
+ include Rack::Utils
4
+
5
+ class << self
6
+ attr_accessor :load_error, :supports_parallel_requests
7
+ alias supports_parallel_requests? supports_parallel_requests
8
+
9
+ # valid parallel managers should respond to #run with no parameters.
10
+ # otherwise, return a short wrapper around it.
11
+ def setup_parallel_manager(options = {})
12
+ nil
13
+ end
14
+ end
15
+
16
+ def self.loaded?
17
+ @load_error.nil?
18
+ end
19
+
20
+ def initialize(app = nil)
21
+ @app = app
22
+ end
23
+
24
+ # assume that query and fragment are already encoded properly
25
+ def full_path_for(path, query = nil, fragment = nil)
26
+ full_path = path.dup
27
+ if query && !query.empty?
28
+ full_path << "?#{query}"
29
+ end
30
+ if fragment && !fragment.empty?
31
+ full_path << "##{fragment}"
32
+ end
33
+ full_path
34
+ end
35
+
36
+ def process_body_for_request(env)
37
+ # if it's a string, pass it through
38
+ return if env[:body].nil? || env[:body].empty? || !env[:body].respond_to?(:each_key)
39
+ env[:request_headers]['Content-Type'] ||= 'application/x-www-form-urlencoded'
40
+ env[:body] = create_form_params(env[:body])
41
+ end
42
+
43
+ def create_form_params(params, base = nil)
44
+ [].tap do |result|
45
+ params.each_key do |key|
46
+ key_str = base ? "#{base}[#{key}]" : key
47
+ value = params[key]
48
+ wee = (value.kind_of?(Hash) ? create_form_params(value, key_str) : "#{key_str}=#{escape(value.to_s)}")
49
+ result << wee
50
+ end
51
+ end.join("&")
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,87 @@
1
+ module Faraday
2
+ # Used to setup urls, params, headers, and the request body in a sane manner.
3
+ #
4
+ # @connection.post do |req|
5
+ # req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1'
6
+ # req.headers['b'] = '2' # header
7
+ # req['b'] = '2' # header
8
+ # req.body = 'abc'
9
+ # end
10
+ #
11
+ class Request < Struct.new(:path, :params, :headers, :body)
12
+ extend AutoloadHelper
13
+ autoload_all 'faraday/request',
14
+ :Yajl => 'yajl',
15
+ :ActiveSupportJson => 'active_support_json'
16
+
17
+ register_lookup_modules \
18
+ :yajl => :Yajl,
19
+ :activesupport_json => :ActiveSupportJson,
20
+ :rails_json => :ActiveSupportJson,
21
+ :active_support_json => :ActiveSupportJson
22
+
23
+ def self.run(connection, request_method)
24
+ req = create
25
+ yield req if block_given?
26
+ req.run(connection, request_method)
27
+ end
28
+
29
+ def self.create
30
+ req = new(nil, {}, {}, nil)
31
+ yield req if block_given?
32
+ req
33
+ end
34
+
35
+ def url(path, params = {})
36
+ self.path = path
37
+ self.params = params
38
+ end
39
+
40
+ def [](key)
41
+ headers[key]
42
+ end
43
+
44
+ def []=(key, value)
45
+ headers[key] = value
46
+ end
47
+
48
+ # ENV Keys
49
+ # :method - a symbolized request method (:get, :post)
50
+ # :body - the request body that will eventually be converted to a string.
51
+ # :url - Addressable::URI instance of the URI for the current request.
52
+ # :status - HTTP response status code
53
+ # :request_headers - hash of HTTP Headers to be sent to the server
54
+ # :response_headers - Hash of HTTP headers from the server
55
+ # :parallel_manager - sent if the connection is in parallel mode
56
+ # :response - the actual response object that stores the rack response
57
+ # :request - Hash of options for configuring the request.
58
+ # :timeout - open/read timeout Integer in seconds
59
+ # :open_timeout - read timeout Integer in seconds
60
+ # :proxy - Hash of proxy options
61
+ # :uri - Proxy Server URI
62
+ # :user - Proxy server username
63
+ # :password - Proxy server password
64
+ # :ssl - Hash of options for configuring SSL requests.
65
+ def to_env_hash(connection, request_method)
66
+ env_headers = connection.headers.dup
67
+ env_params = connection.params.dup
68
+ connection.merge_headers(env_headers, headers)
69
+ connection.merge_params(env_params, params)
70
+
71
+ { :method => request_method,
72
+ :body => body,
73
+ :url => connection.build_url(path, env_params),
74
+ :request_headers => env_headers.update(headers),
75
+ :parallel_manager => connection.parallel_manager,
76
+ :response => Response.new,
77
+ :request => connection.options.merge(:proxy => connection.proxy),
78
+ :ssl => connection.ssl}
79
+ end
80
+
81
+ def run(connection, request_method)
82
+ app = connection.to_app
83
+ env = to_env_hash(connection, request_method)
84
+ app.call(env)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,21 @@
1
+ module Faraday
2
+ class Request::ActiveSupportJson < Faraday::Middleware
3
+ begin
4
+ if !defined?(ActiveSupport::JSON)
5
+ require 'active_support'
6
+ ActiveSupport::JSON
7
+ end
8
+
9
+ rescue LoadError, NameError => e
10
+ self.load_error = e
11
+ end
12
+
13
+ def call(env)
14
+ env[:request_headers]['Content-Type'] = 'application/json'
15
+ if env[:body] && !env[:body].respond_to?(:to_str)
16
+ env[:body] = ActiveSupport::JSON.encode(env[:body])
17
+ end
18
+ @app.call env
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Faraday
2
+ class Request::Yajl < Faraday::Middleware
3
+ begin
4
+ require 'yajl'
5
+
6
+ rescue LoadError, NameError => e
7
+ self.load_error = e
8
+ end
9
+
10
+ def call(env)
11
+ env[:request_headers]['Content-Type'] = 'application/json'
12
+ if env[:body] && !env[:body].respond_to?(:to_str)
13
+ env[:body] = Yajl::Encoder.encode(env[:body])
14
+ end
15
+ @app.call env
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,56 @@
1
+ module Faraday
2
+ class Response
3
+ class Middleware < Faraday::Middleware
4
+ self.load_error = :abstract
5
+
6
+ # Use a response callback in case the request is parallelized.
7
+ #
8
+ # env[:response].on_complete do |finished_env|
9
+ # finished_env[:body] = do_stuff_to(finished_env[:body])
10
+ # end
11
+ #
12
+ def self.register_on_complete(env)
13
+ end
14
+
15
+ def call(env)
16
+ self.class.register_on_complete(env)
17
+ @app.call env
18
+ end
19
+ end
20
+
21
+ extend AutoloadHelper
22
+
23
+ autoload_all 'faraday/response',
24
+ :Yajl => 'yajl',
25
+ :Nokogiri => 'nokogiri',
26
+ :ActiveSupportJson => 'active_support_json'
27
+
28
+ register_lookup_modules \
29
+ :yajl => :Yajl,
30
+ :nokogiri => :Nokogiri,
31
+ :activesupport_json => :ActiveSupportJson,
32
+ :rails_json => :ActiveSupportJson,
33
+ :active_support_json => :ActiveSupportJson
34
+ attr_accessor :status, :headers, :body
35
+
36
+ def initialize
37
+ @status, @headers, @body = nil, nil, nil
38
+ @on_complete_callbacks = []
39
+ end
40
+
41
+ def on_complete(&block)
42
+ @on_complete_callbacks << block
43
+ end
44
+
45
+ def finish(env)
46
+ env[:body] ||= ''
47
+ @on_complete_callbacks.each { |c| c.call(env) }
48
+ @status, @headers, @body = env[:status], env[:response_headers], env[:body]
49
+ self
50
+ end
51
+
52
+ def success?
53
+ status == 200
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,31 @@
1
+ module Faraday
2
+ class Response::ActiveSupportJson < Response::Middleware
3
+ begin
4
+ if !defined?(ActiveSupport::JSON)
5
+ require 'active_support'
6
+ ActiveSupport::JSON
7
+ end
8
+
9
+ def self.register_on_complete(env)
10
+ env[:response].on_complete do |finished_env|
11
+ finished_env[:body] = parse(finished_env[:body])
12
+
13
+ end
14
+ end
15
+ rescue LoadError, NameError => e
16
+ self.load_error = e
17
+ end
18
+
19
+ def initialize(app)
20
+ super
21
+ @parser = nil
22
+ end
23
+
24
+ def self.parse(body)
25
+ ActiveSupport::JSON.decode(body)
26
+ # TODO: Maybe rescue Exception can be better ...
27
+ rescue Yajl::ParseError => e
28
+ raise Faraday::Error::ParsingError
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Faraday
2
+ class Response::Nokogiri < Faraday::Response::Middleware
3
+ begin
4
+ require 'nokogiri'
5
+
6
+ def self.register_on_complete(env)
7
+ env[:response].on_complete do |finished_env|
8
+ finished_env[:body] = ::Nokogiri::XML(finished_env[:body])
9
+ end
10
+ end
11
+ rescue LoadError, NameError => e
12
+ self.load_error = e
13
+ raise e
14
+ end
15
+
16
+ def initialize(app)
17
+ super
18
+ @parser = nil
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ module Faraday
2
+ class Response::Yajl < Response::Middleware
3
+ begin
4
+ require 'yajl'
5
+
6
+ def self.register_on_complete(env)
7
+ env[:response].on_complete do |finished_env|
8
+ finished_env[:body] = parse(finished_env[:body])
9
+ end
10
+ end
11
+ rescue LoadError, NameError => e
12
+ self.load_error = e
13
+ end
14
+
15
+ def initialize(app)
16
+ super
17
+ @parser = nil
18
+ end
19
+
20
+ def self.parse(body)
21
+ Yajl::Parser.parse(body)
22
+ rescue Yajl::ParseError => e
23
+ raise Faraday::Error::ParsingError
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
2
+
3
+ if Faraday::TestCase::LIVE_SERVER
4
+ module Adapters
5
+ class LiveTest < Faraday::TestCase
6
+ (Faraday::Adapter.all_loaded_constants + [:default]).each do |adapter|
7
+ define_method "test_#{adapter}_GET_retrieves_the_response_body" do
8
+ assert_equal 'hello world', create_connection(adapter).get('hello_world').body
9
+ end
10
+
11
+ define_method "test_#{adapter}_GET_send_url_encoded_params" do
12
+ resp = create_connection(adapter).get do |req|
13
+ req.url 'hello', 'name' => 'zack'
14
+ end
15
+ assert_equal('hello zack', resp.body)
16
+ end
17
+
18
+ define_method "test_#{adapter}_GET_retrieves_the_response_headers" do
19
+ assert_equal 'text/html', create_connection(adapter).get('hello_world').headers['content-type']
20
+ end
21
+
22
+ define_method "test_#{adapter}_POST_send_url_encoded_params" do
23
+ resp = create_connection(adapter).post do |req|
24
+ req.url 'echo_name'
25
+ req.body = {'name' => 'zack'}
26
+ end
27
+ assert_equal %("zack"), resp.body
28
+ end
29
+
30
+ define_method "test_#{adapter}_POST_send_url_encoded_nested_params" do
31
+ resp = create_connection(adapter).post do |req|
32
+ req.url 'echo_name'
33
+ req.body = {'name' => {'first' => 'zack'}}
34
+ end
35
+ assert_equal %({"first"=>"zack"}), resp.body
36
+ end
37
+
38
+ define_method "test_#{adapter}_POST_retrieves_the_response_headers" do
39
+ assert_equal 'text/html', create_connection(adapter).post('echo_name').headers['content-type']
40
+ end
41
+
42
+ # http://github.com/toland/patron/issues/#issue/9
43
+ if ENV['FORCE'] || adapter != Faraday::Adapter::Patron
44
+ define_method "test_#{adapter}_PUT_send_url_encoded_params" do
45
+ resp = create_connection(adapter).put do |req|
46
+ req.url 'echo_name'
47
+ req.body = {'name' => 'zack'}
48
+ end
49
+ assert_equal %("zack"), resp.body
50
+ end
51
+
52
+ define_method "test_#{adapter}_PUT_send_url_encoded_nested_params" do
53
+ resp = create_connection(adapter).put do |req|
54
+ req.url 'echo_name'
55
+ req.body = {'name' => {'first' => 'zack'}}
56
+ end
57
+ assert_equal %({"first"=>"zack"}), resp.body
58
+ end
59
+
60
+ define_method "test_#{adapter}_PUT_retrieves_the_response_headers" do
61
+ assert_equal 'text/html', create_connection(adapter).put('echo_name').headers['content-type']
62
+ end
63
+ end
64
+
65
+ # http://github.com/pauldix/typhoeus/issues#issue/7
66
+ if ENV['FORCE'] || adapter != Faraday::Adapter::Typhoeus
67
+ define_method "test_#{adapter}_HEAD_send_url_encoded_params" do
68
+ resp = create_connection(adapter).head do |req|
69
+ req.url 'hello', 'name' => 'zack'
70
+ end
71
+ assert_equal 'text/html', resp.headers['content-type']
72
+ end
73
+
74
+ define_method "test_#{adapter}_HEAD_retrieves_no_response_body" do
75
+ assert_equal '', create_connection(adapter).head('hello_world').body.to_s
76
+ end
77
+
78
+ define_method "test_#{adapter}_HEAD_retrieves_the_response_headers" do
79
+ assert_equal 'text/html', create_connection(adapter).head('hello_world').headers['content-type']
80
+ end
81
+ end
82
+
83
+ define_method "test_#{adapter}_DELETE_retrieves_the_response_headers" do
84
+ assert_equal 'text/html', create_connection(adapter).delete('delete_with_json').headers['content-type']
85
+ end
86
+
87
+ define_method "test_#{adapter}_DELETE_retrieves_the_body" do
88
+ assert_match /deleted/, create_connection(adapter).delete('delete_with_json').body
89
+ end
90
+
91
+ define_method "test_#{adapter}_async_requests_clear_parallel_manager_after_running_a_single_request" do
92
+ connection = create_connection(adapter)
93
+ assert !connection.in_parallel?
94
+ resp = connection.get('hello_world')
95
+ assert !connection.in_parallel?
96
+ assert_equal 'hello world', connection.get('hello_world').body
97
+ end
98
+
99
+ define_method "test_#{adapter}_async_requests_uses_parallel_manager_to_run_multiple_json_requests" do
100
+ resp1, resp2 = nil, nil
101
+
102
+ connection = create_connection(adapter)
103
+ adapter = real_adapter_for(adapter)
104
+
105
+ connection.in_parallel(adapter.setup_parallel_manager) do
106
+ resp1 = connection.get('json')
107
+ resp2 = connection.get('json')
108
+ if adapter.supports_parallel_requests?
109
+ assert connection.in_parallel?
110
+ assert_nil resp1.body
111
+ assert_nil resp2.body
112
+ end
113
+ end
114
+ assert !connection.in_parallel?
115
+ assert_equal '[1,2,3]', resp1.body
116
+ assert_equal '[1,2,3]', resp2.body
117
+ end
118
+ end
119
+
120
+ def create_connection(adapter)
121
+ if adapter == :default
122
+ conn = Faraday.default_connection
123
+ conn.url_prefix = LIVE_SERVER
124
+ conn
125
+ else
126
+ Faraday::Connection.new LIVE_SERVER do |b|
127
+ b.use adapter
128
+ end
129
+ end
130
+ end
131
+
132
+ def real_adapter_for(adapter)
133
+ if adapter == :default
134
+ Faraday::Adapter.lookup_module(Faraday.default_adapter)
135
+ else
136
+ adapter
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end