faraday-stack 0.1.0 → 0.1.2
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.
- data/README.md +11 -2
- data/lib/faraday_stack.rb +11 -2
- data/lib/faraday_stack/addressable_patch.rb +13 -11
- data/lib/faraday_stack/caching.rb +3 -6
- data/lib/faraday_stack/response_json.rb +18 -0
- data/test/factory_test.rb +28 -0
- data/test/response_middleware_test.rb +21 -0
- metadata +49 -29
data/README.md
CHANGED
@@ -38,7 +38,9 @@ Awesome example:
|
|
38
38
|
* raises exceptions on 4xx, 5xx responses
|
39
39
|
* follows redirects
|
40
40
|
|
41
|
-
|
41
|
+
To see how the default stack is built, see "[faraday_stack.rb][source]".
|
42
|
+
|
43
|
+
### Optional features:
|
42
44
|
|
43
45
|
* encode POST/PUT bodies as JSON:
|
44
46
|
|
@@ -55,7 +57,14 @@ Optional features:
|
|
55
57
|
:namespace => 'faraday', :expires_in => 3600
|
56
58
|
end
|
57
59
|
|
58
|
-
|
60
|
+
* mount [Rack::Cache][] through `RackCompatible` middleware for HTTP caching of responses
|
61
|
+
|
62
|
+
conn.builder.insert_after FaradayStack::FollowRedirects, FaradayStack::RackCompatible,
|
63
|
+
Rack::Cache::Context,
|
64
|
+
:metastore => "file:/var/cache/rack/meta",
|
65
|
+
:entitystore => "file:/var/cache/rack/body"
|
66
|
+
|
59
67
|
|
60
68
|
[faraday]: https://github.com/technoweenie/faraday
|
61
69
|
[source]: https://github.com/mislav/faraday-stack/blob/master/lib/faraday_stack.rb
|
70
|
+
[rack::cache]: http://rtomayko.github.com/rack-cache/
|
data/lib/faraday_stack.rb
CHANGED
@@ -28,13 +28,22 @@ module FaradayStack
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.build(url = nil, options = {})
|
31
|
-
|
31
|
+
klass = nil
|
32
|
+
if url.is_a?(Hash) then options = url.dup
|
33
|
+
elsif url.is_a?(Class) then klass = url
|
34
|
+
else options = options.merge(:url => url)
|
35
|
+
end
|
36
|
+
|
37
|
+
klass ||= options.delete(:class) || Faraday::Connection
|
38
|
+
|
39
|
+
klass.new(options) do |builder|
|
32
40
|
builder.request :url_encoded
|
33
41
|
builder.request :json
|
34
42
|
yield builder if block_given?
|
35
43
|
builder.use ResponseXML, :content_type => /[+\/]xml$/
|
36
44
|
builder.use ResponseHTML, :content_type => 'text/html'
|
37
|
-
builder.use ResponseJSON, :content_type =>
|
45
|
+
builder.use ResponseJSON, :content_type => /(application|text)\/json/
|
46
|
+
builder.use ResponseJSON::MimeTypeFix, :content_type => /text\/(plain|javascript)/
|
38
47
|
builder.use FollowRedirects
|
39
48
|
builder.response :raise_error
|
40
49
|
builder.adapter Faraday.default_adapter
|
@@ -1,18 +1,20 @@
|
|
1
1
|
require 'addressable/uri'
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# feature-detect the bug
|
4
|
+
unless Addressable::URI.parse('/?a=1&b=2') === '/?b=2&a=1'
|
5
|
+
# fix `normalized_query` by sorting query key-value pairs
|
6
|
+
# (rejected: https://github.com/sporkmonger/addressable/issues/28)
|
7
|
+
class Addressable::URI
|
8
|
+
alias normalized_query_without_ordering_fix normalized_query
|
8
9
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def normalized_query
|
11
|
+
fresh = @normalized_query.nil?
|
12
|
+
query = normalized_query_without_ordering_fix
|
13
|
+
if query && fresh
|
14
|
+
@normalized_query = query.split('&', -1).sort_by {|q| q[0..(q.index('=')||-1)] }.join('&')
|
15
|
+
else
|
16
|
+
query
|
14
17
|
end
|
15
|
-
normalized
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
@@ -24,14 +24,11 @@ module FaradayStack
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def cache_key(env)
|
27
|
-
url = env[:url]
|
28
|
-
if params_to_strip.any?
|
29
|
-
url = url.dup
|
27
|
+
url = env[:url].dup
|
28
|
+
if url.query && params_to_strip.any?
|
30
29
|
url.query_values = url.query_values.reject { |k,| params_to_strip.include? k }
|
31
|
-
url.normalize!
|
32
|
-
else
|
33
|
-
url = url.normalize
|
34
30
|
end
|
31
|
+
url.normalize!
|
35
32
|
url.request_uri
|
36
33
|
end
|
37
34
|
|
@@ -28,5 +28,23 @@ module FaradayStack
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
# writes the correct MIME-type if the payload looks like JSON
|
33
|
+
class MimeTypeFix < ResponseMiddleware
|
34
|
+
def on_complete(env)
|
35
|
+
if process_response_type?(response_type(env)) and looks_like_json?(env)
|
36
|
+
old_type = env[:response_headers][CONTENT_TYPE]
|
37
|
+
new_type = 'application/json'
|
38
|
+
new_type << ';' << old_type.split(';', 2).last if old_type.index(';')
|
39
|
+
env[:response_headers][CONTENT_TYPE] = new_type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
BRACKETS = %w- [ { -
|
44
|
+
|
45
|
+
def looks_like_json?(env)
|
46
|
+
parse_response?(env) and BRACKETS.include? env[:body][0,1]
|
47
|
+
end
|
48
|
+
end
|
31
49
|
end
|
32
50
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
class FactoryTest < Test::Unit::TestCase
|
5
|
+
extend Forwardable
|
6
|
+
def_delegator FaradayStack, :build
|
7
|
+
|
8
|
+
class CustomConnection < Faraday::Connection
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_default_connection
|
12
|
+
assert_instance_of Faraday::Connection, FaradayStack.default_connection
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_build_subclass
|
16
|
+
assert_instance_of CustomConnection, build(CustomConnection)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_build_url
|
20
|
+
conn = FaradayStack.build('http://example.com')
|
21
|
+
assert_equal 'example.com', conn.host
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_build_url_in_options
|
25
|
+
conn = FaradayStack.build(:url => 'http://example.com')
|
26
|
+
assert_equal 'example.com', conn.host
|
27
|
+
end
|
28
|
+
end
|
@@ -7,6 +7,8 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
|
|
7
7
|
b.use @json_handler
|
8
8
|
b.adapter :test do |stub|
|
9
9
|
stub.get('json') { [200, {'Content-Type' => 'application/json; charset=utf-8'}, "[1,2,3]"] }
|
10
|
+
stub.get('bad_mime') { [200, {'Content-Type' => 'text/javascript; charset=utf-8'}, "[1,2,3]"] }
|
11
|
+
stub.get('js') { [200, {'Content-Type' => 'text/javascript'}, "alert('hello')"] }
|
10
12
|
stub.get('blank') { [200, {'Content-Type' => 'application/json'}, ''] }
|
11
13
|
stub.get('nil') { [200, {'Content-Type' => 'application/json'}, nil] }
|
12
14
|
stub.get('bad_json') { [200, {'Content-Type' => 'application/json'}, '<body></body>']}
|
@@ -19,6 +21,10 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
|
|
19
21
|
@conn.builder.swap @json_handler, @json_handler, :content_type => types
|
20
22
|
end
|
21
23
|
|
24
|
+
def with_mime_type_fix(*types)
|
25
|
+
@conn.builder.insert_after @json_handler, FaradayStack::ResponseJSON::MimeTypeFix, :content_type => types
|
26
|
+
end
|
27
|
+
|
22
28
|
def test_uses_json_to_parse_json_content
|
23
29
|
response = @conn.get('json')
|
24
30
|
assert response.success?
|
@@ -69,4 +75,19 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
|
|
69
75
|
assert_equal 'text/html', response.headers['Content-Type']
|
70
76
|
assert_equal '<body></body>', response.body
|
71
77
|
end
|
78
|
+
|
79
|
+
def test_mime_type_fix
|
80
|
+
process_only('application/json')
|
81
|
+
with_mime_type_fix
|
82
|
+
response = @conn.get('bad_mime')
|
83
|
+
assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
|
84
|
+
assert_equal [1,2,3], response.body
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_mime_type_fix_conditional
|
88
|
+
process_only('application/json')
|
89
|
+
with_mime_type_fix
|
90
|
+
response = @conn.get('js')
|
91
|
+
assert_equal 'text/javascript', response.headers['Content-Type']
|
92
|
+
end
|
72
93
|
end
|
metadata
CHANGED
@@ -1,34 +1,45 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday-stack
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
- Mislav
|
11
|
+
authors:
|
12
|
+
- "Mislav Marohni\xC4\x87"
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
|
-
|
16
|
+
|
17
|
+
date: 2011-06-13 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
16
21
|
name: faraday
|
17
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
24
|
none: false
|
19
|
-
requirements:
|
25
|
+
requirements:
|
20
26
|
- - ~>
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 6
|
31
|
+
version: "0.6"
|
23
32
|
type: :runtime
|
24
|
-
|
25
|
-
version_requirements: *2164745380
|
33
|
+
version_requirements: *id001
|
26
34
|
description:
|
27
35
|
email: mislav.marohnic@gmail.com
|
28
36
|
executables: []
|
37
|
+
|
29
38
|
extensions: []
|
39
|
+
|
30
40
|
extra_rdoc_files: []
|
31
|
-
|
41
|
+
|
42
|
+
files:
|
32
43
|
- lib/faraday-stack.rb
|
33
44
|
- lib/faraday_stack/addressable_patch.rb
|
34
45
|
- lib/faraday_stack/caching.rb
|
@@ -41,33 +52,42 @@ files:
|
|
41
52
|
- lib/faraday_stack/response_xml.rb
|
42
53
|
- lib/faraday_stack.rb
|
43
54
|
- test/caching_test.rb
|
55
|
+
- test/factory_test.rb
|
44
56
|
- test/follow_redirects_test.rb
|
45
57
|
- test/response_middleware_test.rb
|
46
58
|
- test/test_helper.rb
|
47
59
|
- README.md
|
48
|
-
has_rdoc:
|
60
|
+
has_rdoc: true
|
49
61
|
homepage: https://github.com/mislav/faraday-stack
|
50
62
|
licenses: []
|
63
|
+
|
51
64
|
post_install_message:
|
52
65
|
rdoc_options: []
|
53
|
-
|
66
|
+
|
67
|
+
require_paths:
|
54
68
|
- lib
|
55
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
70
|
none: false
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
|
61
|
-
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
78
|
none: false
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
67
85
|
requirements: []
|
86
|
+
|
68
87
|
rubyforge_project:
|
69
|
-
rubygems_version: 1.
|
88
|
+
rubygems_version: 1.3.7
|
70
89
|
signing_key:
|
71
90
|
specification_version: 3
|
72
91
|
summary: Great Faraday stack for consuming all kinds of APIs
|
73
92
|
test_files: []
|
93
|
+
|