shin-faraday 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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