flexirest 1.9.18 → 1.10.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/docs/authentication.md +24 -0
- data/docs/filtering-result-lists.md +1 -1
- data/docs/json-api.md +16 -4
- data/docs/plain-requests.md +1 -1
- data/docs/proxying-apis.md +1 -1
- data/docs/raw-requests.md +2 -2
- data/docs/root-elements.md +41 -6
- data/docs/using-callbacks.md +28 -1
- data/flexirest.gemspec +1 -9
- data/lib/flexirest/base_without_validation.rb +16 -0
- data/lib/flexirest/configuration.rb +44 -0
- data/lib/flexirest/json_api_proxy.rb +1 -4
- data/lib/flexirest/lazy_association_loader.rb +4 -0
- data/lib/flexirest/request.rb +80 -17
- data/lib/flexirest/result_iterator.rb +2 -0
- data/lib/flexirest/version.rb +1 -1
- data/spec/lib/base_without_validation_spec.rb +30 -0
- data/spec/lib/json_api_spec.rb +40 -6
- data/spec/lib/request_spec.rb +204 -5
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a072753fe6a84d8f13ae90d26cdff777e78fc129d4555b5188ae0c0be35ad78
|
4
|
+
data.tar.gz: 7e6ecfe247cc9f021a3e35f9cf4d3b28a6743694b53a2ca32c0ea988a2113276
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 561fdb72c84a9bd3d0a353f46d4761179df66f3e45967bec4b4b620c6f818dca0058388b5f83c2d2455da1f21fa90a72ec0f73ab056fbf086dab522cc8f48fd7
|
7
|
+
data.tar.gz: 95d6f2852392a23c82a5ae0e157a9ad1bc391c4846e79946eab75236c1c3b409c8193a3550e42b9e19676b94a3cccda28e6f0ddf438e47b3e77de9c66669006a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.10.4
|
4
|
+
|
5
|
+
Enhancement:
|
6
|
+
|
7
|
+
- Implement support for in-header Basic Auth (thanks to François Ferrandis for the PR)
|
8
|
+
|
9
|
+
## 1.10.3
|
10
|
+
|
11
|
+
Enhancement:
|
12
|
+
|
13
|
+
- Ignore/wrap root functionality available for all routes, rather than just route specifically (thanks to Sampat Badhe for the PR)
|
14
|
+
|
15
|
+
## 1.10.2
|
16
|
+
|
17
|
+
Bugfix:
|
18
|
+
|
19
|
+
- JSON-API calls do not include linked resources when no other parameter is passed (thanks to Stevo-S for the bug report and François Ferrandis for the PR)
|
20
|
+
|
21
|
+
## 1.10.1
|
22
|
+
|
23
|
+
Enhancement:
|
24
|
+
|
25
|
+
- Nested objects now report their dirty/changed status up to the parent (thanks to Matthias Hähnel for the bug report)
|
26
|
+
|
27
|
+
## 1.10.0
|
28
|
+
|
29
|
+
Enhancement:
|
30
|
+
|
31
|
+
- Add specific exceptions for the most common 5xx server-side errors
|
32
|
+
|
3
33
|
## 1.9.18
|
4
34
|
|
5
35
|
Security:
|
data/docs/authentication.md
CHANGED
@@ -40,6 +40,30 @@ Or if it's called from a class context:
|
|
40
40
|
Person.find(id: 1234)
|
41
41
|
```
|
42
42
|
|
43
|
+
### Basic authentication method
|
44
|
+
|
45
|
+
Flexirest provides two methods for HTTP Basic Auth. The default method is `:url`:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class Person < Flexirest::Base
|
49
|
+
basic_auth_method :url
|
50
|
+
end
|
51
|
+
# Includes the credentials in the URL:
|
52
|
+
# https://my_username:my_password@example.com/
|
53
|
+
```
|
54
|
+
|
55
|
+
But you might want to keep the credentials out of your logs and use the `:header` method:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class Person < Flexirest::Base
|
59
|
+
basic_auth_method :header
|
60
|
+
end
|
61
|
+
# Clean URL:
|
62
|
+
# https://example.com/
|
63
|
+
# with the base64 encoded credentials:
|
64
|
+
# Authorization: Basic YXBpOmViNjkzZWMtODI1MmMtZDYzMDEtMDJmZDAtZDBmYjctYzM0ODU=
|
65
|
+
```
|
66
|
+
|
43
67
|
## Api-Auth
|
44
68
|
|
45
69
|
Using the [Api-Auth](https://github.com/mgomes/api_auth) integration it is very easy to sign requests. Include the Api-Auth gem in your `Gemfile` and then add it to your application. Then simply configure Api-Auth one time in your app and all requests will be signed from then on.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# *Flexirest:* Filtering result lists
|
2
2
|
|
3
|
-
If the API returns a JSON list of items, this is
|
3
|
+
If the API returns a JSON list of items, this is returned to you as a `Flexirest::ResultIterator` object. A `ResultIterator` sorts simple filtering of the list using a `where` method based on values matching a specified criteria (or matching using regular expressions):
|
4
4
|
|
5
5
|
```ruby
|
6
6
|
class Article < Flexirest::Base
|
data/docs/json-api.md
CHANGED
@@ -12,17 +12,26 @@ This proxy translates requests according to the JSON API specifications, parses
|
|
12
12
|
|
13
13
|
It supports lazy loading by default. Unless a compound document is returned from the connected JSON API service, it will make another request to the service for the specified linked resource.
|
14
14
|
|
15
|
+
|
16
|
+
## Including associations
|
17
|
+
|
15
18
|
To reduce the number of requests to the service, you can ask the service to include the linked resources in the response. Such responses are called "compound documents". To do this, use the `includes` method:
|
16
19
|
|
17
20
|
```ruby
|
18
|
-
# Makes a call to /articles
|
21
|
+
# Makes a call to: /articles?include=images
|
19
22
|
Article.includes(:images).all
|
20
23
|
|
21
|
-
#
|
24
|
+
# Fetch nested resources: /articles?include=images.tags,images.photographer
|
22
25
|
Article.includes(:images => [:tags, :photographer]).all
|
26
|
+
|
27
|
+
# Note: the `includes` method takes precedence over the passed `:include` parameter.
|
28
|
+
# This will result in query: /articles?include=images
|
29
|
+
Article.includes(:images).all(include: "author")
|
23
30
|
```
|
24
31
|
|
25
|
-
|
32
|
+
## Resource type
|
33
|
+
|
34
|
+
The `type` value is guessed from the class name, but it can be set specifically with `alias_type`:
|
26
35
|
|
27
36
|
```ruby
|
28
37
|
class Photographer < Flexirest::Base
|
@@ -34,7 +43,10 @@ class Photographer < Flexirest::Base
|
|
34
43
|
end
|
35
44
|
```
|
36
45
|
|
37
|
-
|
46
|
+
|
47
|
+
## Notes
|
48
|
+
|
49
|
+
Updating relationships is not yet supported.
|
38
50
|
|
39
51
|
|
40
52
|
-----
|
data/docs/plain-requests.md
CHANGED
@@ -7,7 +7,7 @@ class Person < Flexirest::Base
|
|
7
7
|
end
|
8
8
|
|
9
9
|
people = Person._plain_request('http://api.example.com/v1/people') # Defaults to get with no parameters
|
10
|
-
# people is a
|
10
|
+
# people is a string containing the response
|
11
11
|
|
12
12
|
Person._plain_request('http://api.example.com/v1/people', :post, {id:1234,name:"John"}) # Post with parameters
|
13
13
|
```
|
data/docs/proxying-apis.md
CHANGED
@@ -40,7 +40,7 @@ Article.all.first_name == "Billy"
|
|
40
40
|
This example does two things:
|
41
41
|
|
42
42
|
1. It rewrites the incoming URL for any requests matching "_/all_" to "/all_people"
|
43
|
-
2. It uses the `translate` method to move the "fname" attribute from the response body to be called "first_name". The translate method must return the new object at the end (either the existing object
|
43
|
+
2. It uses the `translate` method to move the "fname" attribute from the response body to be called "first_name". The translate method must return the new object at the end (either the existing object altered, or a new object to replace it with)
|
44
44
|
|
45
45
|
As the comment shows, you can use `url value` to set the request URL to a particular value, or you can call `gsub!` on the url to replace parts of it using more complicated regular expressions.
|
46
46
|
|
data/docs/raw-requests.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# *Flexirest:* Raw requests
|
2
2
|
|
3
|
-
Sometimes you have
|
3
|
+
Sometimes you have a URL that you just want to force through, but have the response handled in the same way as normal objects or you want to have the callbacks run (say for authentication). The easiest way to do that is to call `_request` on the class:
|
4
4
|
|
5
5
|
```ruby
|
6
6
|
class Person < Flexirest::Base
|
@@ -12,7 +12,7 @@ people = Person._request('http://api.example.com/v1/people') # Defaults to get w
|
|
12
12
|
Person._request('http://api.example.com/v1/people', :post, {id:1234,name:"John"}) # Post with parameters
|
13
13
|
```
|
14
14
|
|
15
|
-
When you need to specify custom headers (for example for authentication) you can do this with a fourth option to the `_request` method. If you are using the default
|
15
|
+
When you need to specify custom headers (for example for authentication) you can do this with a fourth option to the `_request` method. If you are using the default parameters you'll need to specify them. For example:
|
16
16
|
|
17
17
|
```ruby
|
18
18
|
Person._request("http://api.example.com/v1/people", :get, {}, {headers:{"X-Something": "foo/bar"}})
|
data/docs/root-elements.md
CHANGED
@@ -2,13 +2,32 @@
|
|
2
2
|
|
3
3
|
If your response comes back with a root node and you'd like to ignore it, you can define the mapping as:
|
4
4
|
|
5
|
+
```ruby
|
6
|
+
Flexirest::Base.ignore_root = "data"
|
7
|
+
```
|
8
|
+
|
9
|
+
Any `ignore_root` setting in specific class overrides this declared default.
|
10
|
+
|
5
11
|
```ruby
|
6
12
|
class Feed < Flexirest::Base
|
7
|
-
|
13
|
+
ignore_root: "feed"
|
14
|
+
|
15
|
+
post :list, "/feed"
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
And any `ignore_root` setting in specific request overrides the both default and class specific setting.
|
20
|
+
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class Feed < Flexirest::Base
|
24
|
+
ignore_root: 'feed'
|
25
|
+
|
26
|
+
post :list, "/feed", ignore_root: "result"
|
8
27
|
end
|
9
28
|
```
|
10
29
|
|
11
|
-
|
30
|
+
You can also assign an array to `ignore_root` if you'd want to remove a tree of root nodes.
|
12
31
|
|
13
32
|
```ruby
|
14
33
|
class Feed < Flexirest::Base
|
@@ -26,16 +45,32 @@ Alternatively if you want to wrap your JSON request body in a root element, e.g.
|
|
26
45
|
}
|
27
46
|
```
|
28
47
|
|
29
|
-
You can do it
|
48
|
+
You can do it using `wrap_root`:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
Flexirest::Base.wrap_root = "data"
|
52
|
+
```
|
53
|
+
|
54
|
+
Any `wrap_root` setting in specific class overrides this declared default.
|
30
55
|
|
31
56
|
```ruby
|
32
57
|
class Feed < Flexirest::Base
|
33
|
-
|
34
|
-
end
|
58
|
+
wrap_root: "feed"
|
35
59
|
|
36
|
-
|
60
|
+
post :list, "/feed"
|
61
|
+
end
|
37
62
|
```
|
38
63
|
|
64
|
+
And any `wrap_root` setting in specific request overrides the both default and class specific setting.
|
65
|
+
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class Feed < Flexirest::Base
|
69
|
+
wrap_root: 'feed'
|
70
|
+
|
71
|
+
post :list, "/feed", wrap_root: "data"
|
72
|
+
end
|
73
|
+
```
|
39
74
|
|
40
75
|
-----
|
41
76
|
|
data/docs/using-callbacks.md
CHANGED
@@ -66,6 +66,7 @@ After callbacks work in exactly the same way:
|
|
66
66
|
```ruby
|
67
67
|
class Person < Flexirest::Base
|
68
68
|
get :all, "/people"
|
69
|
+
get :all, "/people"
|
69
70
|
|
70
71
|
after_request :fix_empty_content
|
71
72
|
after_request :cache_all_people
|
@@ -88,6 +89,32 @@ end
|
|
88
89
|
|
89
90
|
**Note:** since v1.3.21 the empty response trick above isn't necessary, empty responses for 204 are accepted normally (the method returns `true`), but this is here to show an example of an `after_request` callback adjusting the body. The `cache_all_people` example shows how to cache a response even if the server doesn't send the correct headers.
|
90
91
|
|
92
|
+
If you manually set caching responses like the above, you may want to invalidate that cache when you make a create, update, delete etc request for the resource, for example:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
class Animal < Flexirest::Base
|
96
|
+
after_request :cache
|
97
|
+
before_request :cache_cleanup
|
98
|
+
|
99
|
+
get :get, '/animals/:id'
|
100
|
+
post :update, '/animals/:id'
|
101
|
+
delete :delete, '/animals/:id'
|
102
|
+
|
103
|
+
def cache_cleanup(name, request)
|
104
|
+
if name == :update || name == :delete
|
105
|
+
Flexirest::Logger.info(" \033[1;4;32m#{Flexirest.name}\033[0m Invalidating cache for #{self.class.name} #{request.url}")
|
106
|
+
Rails.cache.delete("#{self.class.name}:#{request.url}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def cache(name, response)
|
111
|
+
if name == :get
|
112
|
+
response.response_headers["Expires"] = 1.hour.from_now.iso8601
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
91
118
|
If you want to trap an error in an `after_request` callback and retry the request, this can be done - but retries will only happen once for each request (so we'd recommend checking all conditions in a single `after_request` and then retrying after fixing them all). You achieve this by raising a `Flexirest::CallbackRetryRequestException` from the callback.
|
92
119
|
|
93
120
|
```ruby
|
@@ -100,7 +127,7 @@ class Person < Flexirest::Base
|
|
100
127
|
|
101
128
|
def fix_invalid_request(name, response)
|
102
129
|
if response.status == 401
|
103
|
-
# Do something to fix the state of caches/variables used in the
|
130
|
+
# Do something to fix the state of caches/variables used in the
|
104
131
|
# before_request, etc
|
105
132
|
raise Flexirest::CallbackRetryRequestException.new
|
106
133
|
end
|
data/flexirest.gemspec
CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_development_dependency "api-auth", ">= 1.3.1", "< 2.4"
|
40
40
|
spec.add_development_dependency 'typhoeus'
|
41
41
|
spec.add_development_dependency 'activemodel'
|
42
|
-
spec.add_development_dependency 'rest-client'
|
42
|
+
spec.add_development_dependency 'rest-client'
|
43
43
|
|
44
44
|
spec.add_runtime_dependency "mime-types"
|
45
45
|
spec.add_runtime_dependency "multi_json"
|
@@ -53,12 +53,4 @@ Gem::Specification.new do |spec|
|
|
53
53
|
else
|
54
54
|
spec.add_runtime_dependency "activesupport", "< 5.0.0"
|
55
55
|
end
|
56
|
-
# JSON is an implicit dependency of something, but JSON v2+ requires Ruby 2+
|
57
|
-
# Same with "tins" which is a dependency of coveralls
|
58
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
|
59
|
-
spec.add_runtime_dependency "json", "< 2.0.0"
|
60
|
-
spec.add_runtime_dependency "tins", "~> 1.6.0"
|
61
|
-
spec.add_runtime_dependency "term-ansicolor", "~> 1.3.2"
|
62
|
-
spec.add_runtime_dependency "public_suffix", "~> 1.4.6"
|
63
|
-
end
|
64
56
|
end
|
@@ -11,6 +11,8 @@ module Flexirest
|
|
11
11
|
attr_accessor :_status
|
12
12
|
attr_accessor :_etag
|
13
13
|
attr_accessor :_headers
|
14
|
+
attr_accessor :_parent
|
15
|
+
attr_accessor :_parent_attribute_name
|
14
16
|
|
15
17
|
instance_methods.each do |m|
|
16
18
|
next unless %w{display presence load require untrust trust freeze method enable_warnings with_warnings suppress capture silence quietly debugger breakpoint}.map(&:to_sym).include? m
|
@@ -41,6 +43,13 @@ module Flexirest
|
|
41
43
|
def _copy_from(result)
|
42
44
|
@attributes = result._attributes
|
43
45
|
@_status = result._status
|
46
|
+
self._parent = result._parent
|
47
|
+
self._parent_attribute_name = result._parent_attribute_name
|
48
|
+
@attributes.each do |k,v|
|
49
|
+
if v.respond_to?(:_parent) && v._parent.present?
|
50
|
+
@attributes[k]._parent = self
|
51
|
+
end
|
52
|
+
end
|
44
53
|
_clean!
|
45
54
|
end
|
46
55
|
|
@@ -184,6 +193,10 @@ module Flexirest
|
|
184
193
|
output.to_json
|
185
194
|
end
|
186
195
|
|
196
|
+
def _set_dirty(key)
|
197
|
+
@dirty_attributes[key.to_sym] = true
|
198
|
+
end
|
199
|
+
|
187
200
|
private
|
188
201
|
|
189
202
|
def _set_attribute(key, value)
|
@@ -191,6 +204,9 @@ module Flexirest
|
|
191
204
|
old_value = @attributes[key.to_sym] unless old_value
|
192
205
|
old_value = old_value[0] if old_value and old_value.is_a? Array
|
193
206
|
@dirty_attributes[key.to_sym] = [old_value, value] if old_value != value
|
207
|
+
if _parent
|
208
|
+
_parent._set_dirty(_parent_attribute_name)
|
209
|
+
end
|
194
210
|
@attributes[key.to_sym] = value
|
195
211
|
end
|
196
212
|
|
@@ -13,6 +13,32 @@ module Flexirest
|
|
13
13
|
@api_auth_access_id = nil
|
14
14
|
@api_auth_secret_key = nil
|
15
15
|
@api_auth_options = {}
|
16
|
+
@ignore_root = nil
|
17
|
+
@wrap_root = nil
|
18
|
+
|
19
|
+
def ignore_root(value=nil)
|
20
|
+
if value.nil?
|
21
|
+
value = if @ignore_root.nil? && superclass.respond_to?(:ignore_root)
|
22
|
+
superclass.ignore_root
|
23
|
+
else
|
24
|
+
@ignore_root
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@ignore_root = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def wrap_root(value=nil)
|
32
|
+
if value.nil?
|
33
|
+
value = if @wrap_root.nil? && superclass.respond_to?(:wrap_root)
|
34
|
+
superclass.wrap_root
|
35
|
+
else
|
36
|
+
@wrap_root
|
37
|
+
end
|
38
|
+
else
|
39
|
+
@wrap_root = value
|
40
|
+
end
|
41
|
+
end
|
16
42
|
|
17
43
|
def base_url(value = nil)
|
18
44
|
@base_url ||= nil
|
@@ -109,6 +135,23 @@ module Flexirest
|
|
109
135
|
@@password = value
|
110
136
|
end
|
111
137
|
|
138
|
+
DEFAULT_BASIC_URL_METHOD = :url
|
139
|
+
|
140
|
+
def basic_auth_method(value = nil)
|
141
|
+
if value.nil? # Used as a getter method
|
142
|
+
if @basic_auth_method.nil? && superclass.respond_to?(:basic_auth_method)
|
143
|
+
superclass.basic_auth_method
|
144
|
+
else
|
145
|
+
@basic_auth_method || DEFAULT_BASIC_URL_METHOD
|
146
|
+
end
|
147
|
+
else # Used as a setter method
|
148
|
+
unless [:header, :url].include?(value)
|
149
|
+
raise %(Invalid basic_auth_method #{value.inspect}. Valid methods are :url (default) and :header.)
|
150
|
+
end
|
151
|
+
@basic_auth_method = value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
112
155
|
def alias_type(value = nil)
|
113
156
|
@alias_type ||= nil
|
114
157
|
if value.nil?
|
@@ -285,6 +328,7 @@ module Flexirest
|
|
285
328
|
@adapter = Faraday.default_adapter
|
286
329
|
@api_auth_access_id = nil
|
287
330
|
@api_auth_secret_key = nil
|
331
|
+
@basic_auth_method = :url
|
288
332
|
end
|
289
333
|
|
290
334
|
private
|
@@ -50,11 +50,8 @@ module Flexirest
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def translate(params, include_associations)
|
53
|
-
# Return to caller if nothing is to be done
|
54
|
-
return params unless params.present? && include_associations.present?
|
55
|
-
|
56
53
|
# Format the linked resources array, and assign to include key
|
57
|
-
params[:include] = format_include_params(include_associations)
|
54
|
+
params[:include] = format_include_params(include_associations) if include_associations.present?
|
58
55
|
end
|
59
56
|
|
60
57
|
private
|
@@ -94,6 +94,10 @@ module Flexirest
|
|
94
94
|
request = Flexirest::Request.new(method, @request.object)
|
95
95
|
request.url = request.forced_url = @url
|
96
96
|
@object = request.call
|
97
|
+
if @object.respond_to?(:_parent=)
|
98
|
+
@object._parent = @options[:parent]
|
99
|
+
@object._parent_attribute_name = @options[:parent_attribute_name]
|
100
|
+
end
|
97
101
|
end
|
98
102
|
end
|
99
103
|
end
|
data/lib/flexirest/request.rb
CHANGED
@@ -32,6 +32,10 @@ module Flexirest
|
|
32
32
|
!@object.respond_to?(:dirty?)
|
33
33
|
end
|
34
34
|
|
35
|
+
def model_class
|
36
|
+
object_is_class? ? @object : @object.class
|
37
|
+
end
|
38
|
+
|
35
39
|
def class_name
|
36
40
|
if object_is_class?
|
37
41
|
@object.name
|
@@ -124,6 +128,18 @@ module Flexirest
|
|
124
128
|
ret
|
125
129
|
end
|
126
130
|
|
131
|
+
def inject_basic_auth_in_url(url)
|
132
|
+
url.gsub!(%r{//(.)}, "//#{username}:#{password}@\\1") if !url[%r{//[^/]*:[^/]*@}]
|
133
|
+
end
|
134
|
+
|
135
|
+
def using_basic_auth?
|
136
|
+
!!username
|
137
|
+
end
|
138
|
+
|
139
|
+
def basic_auth_digest
|
140
|
+
Base64.strict_encode64("#{username}:#{password}")
|
141
|
+
end
|
142
|
+
|
127
143
|
def request_body_type
|
128
144
|
if @method[:options][:request_body_type]
|
129
145
|
@method[:options][:request_body_type]
|
@@ -136,6 +152,30 @@ module Flexirest
|
|
136
152
|
end
|
137
153
|
end
|
138
154
|
|
155
|
+
def ignore_root
|
156
|
+
if @method[:options][:ignore_root]
|
157
|
+
@method[:options][:ignore_root]
|
158
|
+
elsif @object.nil?
|
159
|
+
nil
|
160
|
+
elsif object_is_class?
|
161
|
+
@object.ignore_root
|
162
|
+
else
|
163
|
+
@object.class.ignore_root
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def wrap_root
|
168
|
+
if @method[:options][:wrap_root]
|
169
|
+
@method[:options][:wrap_root]
|
170
|
+
elsif @object.nil?
|
171
|
+
nil
|
172
|
+
elsif object_is_class?
|
173
|
+
@object.wrap_root
|
174
|
+
else
|
175
|
+
@object.class.wrap_root
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
139
179
|
def verbose?
|
140
180
|
if object_is_class?
|
141
181
|
@object.verbose
|
@@ -438,8 +478,8 @@ module Flexirest
|
|
438
478
|
@post_params
|
439
479
|
else
|
440
480
|
p = (params || @post_params || {})
|
441
|
-
if
|
442
|
-
p = {
|
481
|
+
if wrap_root.present?
|
482
|
+
p = {wrap_root => p}
|
443
483
|
end
|
444
484
|
p.to_query
|
445
485
|
end
|
@@ -452,8 +492,8 @@ module Flexirest
|
|
452
492
|
@post_params
|
453
493
|
else
|
454
494
|
p = (params || @post_params || {})
|
455
|
-
if
|
456
|
-
p = {
|
495
|
+
if wrap_root.present?
|
496
|
+
p = {wrap_root => p}
|
457
497
|
end
|
458
498
|
data, mp_headers = Flexirest::Multipart::Post.prepare_query(p)
|
459
499
|
mp_headers.each do |k,v|
|
@@ -467,8 +507,8 @@ module Flexirest
|
|
467
507
|
elsif @post_params.is_a?(String)
|
468
508
|
@post_params
|
469
509
|
else
|
470
|
-
if
|
471
|
-
{
|
510
|
+
if wrap_root.present?
|
511
|
+
{wrap_root => (params || @post_params || {})}.to_json
|
472
512
|
else
|
473
513
|
(params || @post_params || {}).to_json
|
474
514
|
end
|
@@ -503,7 +543,9 @@ module Flexirest
|
|
503
543
|
else
|
504
544
|
_, @base_url, @url = parts
|
505
545
|
end
|
506
|
-
|
546
|
+
if using_basic_auth? && model_class.basic_auth_method == :url
|
547
|
+
inject_basic_auth_in_url(base_url)
|
548
|
+
end
|
507
549
|
connection = Flexirest::ConnectionManager.get_connection(base_url)
|
508
550
|
end
|
509
551
|
else
|
@@ -516,7 +558,9 @@ module Flexirest
|
|
516
558
|
else
|
517
559
|
base_url = parts[0]
|
518
560
|
end
|
519
|
-
|
561
|
+
if using_basic_auth? && model_class.basic_auth_method == :url
|
562
|
+
inject_basic_auth_in_url(base_url)
|
563
|
+
end
|
520
564
|
connection = Flexirest::ConnectionManager.get_connection(base_url)
|
521
565
|
end
|
522
566
|
if @method[:options][:direct]
|
@@ -542,6 +586,8 @@ module Flexirest
|
|
542
586
|
:api_auth_secret_key => api_auth_secret_key,
|
543
587
|
:api_auth_options => api_auth_options
|
544
588
|
}
|
589
|
+
elsif using_basic_auth? && model_class.basic_auth_method == :header
|
590
|
+
http_headers["Authorization"] = "Basic #{basic_auth_digest}"
|
545
591
|
end
|
546
592
|
if @method[:options][:timeout]
|
547
593
|
request_options[:timeout] = @method[:options][:timeout]
|
@@ -601,7 +647,7 @@ module Flexirest
|
|
601
647
|
else
|
602
648
|
Flexirest::Logger.debug " \033[1;4;32m#{Flexirest.name}\033[0m #{@instrumentation_name} - Response received #{@response.body.size} bytes"
|
603
649
|
end
|
604
|
-
result = generate_new_object(ignore_root:
|
650
|
+
result = generate_new_object(ignore_root: ignore_root, ignore_xml_root: @method[:options][:ignore_xml_root])
|
605
651
|
# TODO: Cleanup when ignore_xml_root is removed
|
606
652
|
else
|
607
653
|
raise ResponseParseException.new(status:status, body:@response.body, headers: @response.headers)
|
@@ -630,6 +676,16 @@ module Flexirest
|
|
630
676
|
raise HTTPConflictClientException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
631
677
|
elsif status == 429
|
632
678
|
raise HTTPTooManyRequestsClientException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
679
|
+
elsif status == 500
|
680
|
+
raise HTTPInternalServerException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
681
|
+
elsif status == 501
|
682
|
+
raise HTTPNotImplementedServerException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
683
|
+
elsif status == 502
|
684
|
+
raise HTTPBadGatewayServerException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
685
|
+
elsif status == 503
|
686
|
+
raise HTTPServiceUnavailableServerException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
687
|
+
elsif status == 504
|
688
|
+
raise HTTPGatewayTimeoutServerException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
633
689
|
elsif (400..499).include? status
|
634
690
|
raise HTTPClientException.new(status:status, result:error_response, raw_response: @response.body, url:@url, method: http_method)
|
635
691
|
elsif (500..599).include? status
|
@@ -641,7 +697,7 @@ module Flexirest
|
|
641
697
|
result
|
642
698
|
end
|
643
699
|
|
644
|
-
def new_object(attributes, name = nil)
|
700
|
+
def new_object(attributes, name = nil, parent = nil, parent_attribute_name = nil)
|
645
701
|
@method[:options][:has_many] ||= {}
|
646
702
|
name = name.to_sym rescue nil
|
647
703
|
if @method[:options][:has_many][name]
|
@@ -654,6 +710,9 @@ module Flexirest
|
|
654
710
|
object = create_object_instance
|
655
711
|
end
|
656
712
|
|
713
|
+
object._parent = parent
|
714
|
+
object._parent_attribute_name = parent_attribute_name
|
715
|
+
|
657
716
|
if hal_response? && name.nil?
|
658
717
|
attributes = handle_hal_links_embedded(object, attributes)
|
659
718
|
end
|
@@ -681,9 +740,9 @@ module Flexirest
|
|
681
740
|
v = value
|
682
741
|
assignable_hash = value_from_object ? object._attributes : {}
|
683
742
|
if value_from_object && @method[:options][:lazy].include?(k)
|
684
|
-
assignable_hash[k] = Flexirest::LazyAssociationLoader.new(overridden_name, v, self, overridden_name:(overridden_name))
|
743
|
+
assignable_hash[k] = Flexirest::LazyAssociationLoader.new(overridden_name, v, self, overridden_name:(overridden_name), parent: object, parent_attribute_name: k)
|
685
744
|
elsif v.is_a? Hash
|
686
|
-
assignable_hash[k] = new_object(v, overridden_name )
|
745
|
+
assignable_hash[k] = new_object(v, overridden_name, object, k)
|
687
746
|
elsif v.is_a? Array
|
688
747
|
if @method[:options][:array].include?(k)
|
689
748
|
assignable_hash[k] = Array.new
|
@@ -801,15 +860,15 @@ module Flexirest
|
|
801
860
|
body = JsonAPIProxy::Response.parse(body, @object)
|
802
861
|
end
|
803
862
|
|
804
|
-
if
|
805
|
-
[
|
863
|
+
if ignore_root
|
864
|
+
[ignore_root].flatten.each do |key|
|
806
865
|
body = body[key.to_s]
|
807
866
|
end
|
808
867
|
end
|
809
868
|
elsif is_xml_response?
|
810
869
|
body = @response.body.blank? ? {} : Crack::XML.parse(@response.body)
|
811
|
-
if
|
812
|
-
[
|
870
|
+
if ignore_root
|
871
|
+
[ignore_root].flatten.each do |key|
|
813
872
|
body = body[key.to_s]
|
814
873
|
end
|
815
874
|
elsif options[:ignore_xml_root]
|
@@ -901,5 +960,9 @@ module Flexirest
|
|
901
960
|
class HTTPNotFoundClientException < HTTPClientException ; end
|
902
961
|
class HTTPTooManyRequestsClientException < HTTPClientException ; end
|
903
962
|
class HTTPServerException < HTTPException ; end
|
904
|
-
|
963
|
+
class HTTPInternalServerException < HTTPServerException ; end
|
964
|
+
class HTTPNotImplementedServerException < HTTPServerException ; end
|
965
|
+
class HTTPBadGatewayServerException < HTTPServerException ; end
|
966
|
+
class HTTPServiceUnavailableServerException < HTTPServerException ; end
|
967
|
+
class HTTPGatewayTimeoutServerException < HTTPServerException ; end
|
905
968
|
end
|
data/lib/flexirest/version.rb
CHANGED
@@ -12,6 +12,11 @@ class TranslatorExample
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
class NestedExample < Flexirest::BaseWithoutValidation
|
16
|
+
get :all, "/all", fake:"{\"person\":{\"name\": \"Billy\"}}"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
15
20
|
class AlteringClientExample < Flexirest::BaseWithoutValidation
|
16
21
|
translator TranslatorExample
|
17
22
|
base_url "http://www.example.com"
|
@@ -140,6 +145,31 @@ describe Flexirest::BaseWithoutValidation do
|
|
140
145
|
expect(client).to be_dirty
|
141
146
|
end
|
142
147
|
|
148
|
+
it "should store attribute changes on nested objects and mark them as dirty in the parent" do
|
149
|
+
client = NestedExample.all
|
150
|
+
client.person.name = "John"
|
151
|
+
expect(client.person.name.to_s).to eq("John")
|
152
|
+
|
153
|
+
expect(client).to be_dirty
|
154
|
+
expect(client.changes.keys).to include(:person)
|
155
|
+
|
156
|
+
expect(client.person).to be_dirty
|
157
|
+
expect(client.person.changes.keys).to include(:name)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should store attribute changes on nested objects loaded via instance methods and mark them as dirty in the parent" do
|
161
|
+
client = NestedExample.new()
|
162
|
+
client.all
|
163
|
+
client.person.name = "John"
|
164
|
+
expect(client.person.name.to_s).to eq("John")
|
165
|
+
|
166
|
+
expect(client).to be_dirty
|
167
|
+
expect(client.changes.keys).to include(:person)
|
168
|
+
|
169
|
+
expect(client.person).to be_dirty
|
170
|
+
expect(client.person.changes.keys).to include(:name)
|
171
|
+
end
|
172
|
+
|
143
173
|
it "should track changed attributes and provide access to previous values (similar to ActiveRecord/Mongoid)" do
|
144
174
|
client = EmptyExample.new()
|
145
175
|
client["test"] = "Something"
|
data/spec/lib/json_api_spec.rb
CHANGED
@@ -303,7 +303,7 @@ describe 'JSON API' do
|
|
303
303
|
let(:tags) { JsonAPIExample::Tag }
|
304
304
|
let(:author) { JsonAPIExample::Author }
|
305
305
|
|
306
|
-
|
306
|
+
describe 'responses' do
|
307
307
|
it 'should return the data object if the response contains only one data instance' do
|
308
308
|
expect(subject.find(1)).to be_an_instance_of(JsonAPIExampleArticle)
|
309
309
|
end
|
@@ -370,17 +370,17 @@ describe 'JSON API' do
|
|
370
370
|
end
|
371
371
|
end
|
372
372
|
|
373
|
-
|
373
|
+
describe 'attributes' do
|
374
374
|
it 'should return the attributes as part of the data instance' do
|
375
|
-
expect(subject.find(1).item).
|
375
|
+
expect(subject.find(1).item).to eq("item one")
|
376
376
|
end
|
377
377
|
|
378
378
|
it 'should return the association\'s attributes as part of the association instance' do
|
379
|
-
expect(subject.includes(:author).find_single_author(1).author.item).
|
379
|
+
expect(subject.includes(:author).find_single_author(1).author.item).to eq("item two")
|
380
380
|
end
|
381
381
|
end
|
382
382
|
|
383
|
-
|
383
|
+
describe 'associations' do
|
384
384
|
it 'should retrieve the resource\'s associations via its relationships object' do
|
385
385
|
expect(subject.includes(:tags).find(1).tags.size).to eq(2)
|
386
386
|
end
|
@@ -415,6 +415,40 @@ describe 'JSON API' do
|
|
415
415
|
end
|
416
416
|
end
|
417
417
|
|
418
|
+
describe 'requests' do
|
419
|
+
describe 'the `include=` parameter' do
|
420
|
+
before { stub_request(:get, %r{example\.com/articles}) }
|
421
|
+
|
422
|
+
context 'when using `.includes(:tags)`' do
|
423
|
+
it 'equal "tags"' do
|
424
|
+
JsonAPIExample::Article.includes(:tags).real_index
|
425
|
+
expect(WebMock).to have_requested(:get, 'http://www.example.com/articles?include=tags')
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
context 'when using `.includes(tags: [:authors, :articles])`' do
|
430
|
+
it 'equal "tags.authors,tags.articles"' do
|
431
|
+
JsonAPIExample::Article.includes(tags: [:authors, :articles]).real_index
|
432
|
+
expect(WebMock).to have_requested(:get, 'http://www.example.com/articles?include=tags.authors,tags.articles')
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
context 'when using both `.includes(:tags)` and other params in the final call' do
|
437
|
+
it 'uses the values passed to the `includes() method`' do
|
438
|
+
JsonAPIExample::Article.includes(:tags).real_index(filter: { author_id: 4 })
|
439
|
+
expect(WebMock).to have_requested(:get, 'http://www.example.com/articles?filter%5Bauthor_id%5D=4&include=tags')
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
context 'when using both `.includes(:tags)` and the :include param in final call' do
|
444
|
+
it 'uses the values passed to the `includes() method`' do
|
445
|
+
JsonAPIExample::Article.includes(:tags).real_index(include: "author")
|
446
|
+
expect(WebMock).to have_requested(:get, 'http://www.example.com/articles?include=tags')
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
418
452
|
context 'lazy loading' do
|
419
453
|
it 'should fetch association lazily' do
|
420
454
|
stub_request(:get, /www.example.com\/articles\/1\/tags/)
|
@@ -434,7 +468,7 @@ describe 'JSON API' do
|
|
434
468
|
end
|
435
469
|
end
|
436
470
|
|
437
|
-
|
471
|
+
describe 'client' do
|
438
472
|
it 'should request with json api format, and expect a json api response' do
|
439
473
|
expect_any_instance_of(Flexirest::Connection).to receive(:post) { |_, _, _, options|
|
440
474
|
expect(options[:headers]).to include('Content-Type' => 'application/vnd.api+json')
|
data/spec/lib/request_spec.rb
CHANGED
@@ -81,6 +81,26 @@ describe Flexirest::Request do
|
|
81
81
|
get :all, "/"
|
82
82
|
end
|
83
83
|
|
84
|
+
class AuthenticatedBasicHeaderExampleClient < Flexirest::Base
|
85
|
+
base_url "http://www.example.com"
|
86
|
+
username "john"
|
87
|
+
password "smith"
|
88
|
+
basic_auth_method :header
|
89
|
+
get :all, "/"
|
90
|
+
end
|
91
|
+
|
92
|
+
class AuthenticatedBasicHeaderExampleClientChildClass < AuthenticatedBasicHeaderExampleClient
|
93
|
+
get :child_method, "/"
|
94
|
+
end
|
95
|
+
|
96
|
+
class AuthenticatedBasicUrlExampleClient < Flexirest::Base
|
97
|
+
base_url "http://www.example.com"
|
98
|
+
username "john"
|
99
|
+
password "smith"
|
100
|
+
basic_auth_method :url
|
101
|
+
get :all, "/"
|
102
|
+
end
|
103
|
+
|
84
104
|
class AuthenticatedProcExampleClient < Flexirest::Base
|
85
105
|
base_url "http://www.example.com"
|
86
106
|
username Proc.new { |obj| obj ? "bill-#{obj.id}" : "bill" }
|
@@ -199,6 +219,89 @@ describe Flexirest::Request do
|
|
199
219
|
}
|
200
220
|
end
|
201
221
|
|
222
|
+
class LocalIgnoredRootExampleClient < ExampleClient
|
223
|
+
ignore_root "feed"
|
224
|
+
|
225
|
+
get :root, "/root", fake: %Q{
|
226
|
+
{
|
227
|
+
"feed": {
|
228
|
+
"title": "Example Feed"
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
234
|
+
class LocalIgnoredMultiLevelRootExampleClient < ExampleClient
|
235
|
+
ignore_root [:response, "data", "object"]
|
236
|
+
|
237
|
+
get :multi_level_root, "/multi-level-root", fake: %Q{
|
238
|
+
{
|
239
|
+
"response": {
|
240
|
+
"data": {
|
241
|
+
"object": {
|
242
|
+
"title": "Example Multi Level Feed"
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
}
|
247
|
+
}
|
248
|
+
end
|
249
|
+
|
250
|
+
class BaseIgnoredRootExampleClient < Flexirest::Base
|
251
|
+
base_url "http://www.example.com"
|
252
|
+
ignore_root "feed"
|
253
|
+
end
|
254
|
+
|
255
|
+
class GlobalIgnoredRootExampleClient < BaseIgnoredRootExampleClient
|
256
|
+
get :root, "/root", fake: %Q{
|
257
|
+
{
|
258
|
+
"feed": {
|
259
|
+
"title": "Example Feed"
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
end
|
264
|
+
|
265
|
+
class OverrideGlobalIgnoredRootForFileExampleClient < BaseIgnoredRootExampleClient
|
266
|
+
ignore_root "data"
|
267
|
+
|
268
|
+
get :root, "/root", fake: %Q{
|
269
|
+
{
|
270
|
+
"data": {
|
271
|
+
"title": "Example Feed"
|
272
|
+
}
|
273
|
+
}
|
274
|
+
}
|
275
|
+
end
|
276
|
+
|
277
|
+
class OverrideGlobalIgnoredRootForRequestExampleClient < BaseIgnoredRootExampleClient
|
278
|
+
get :root, "/root", ignore_root: "data", fake: %Q{
|
279
|
+
{
|
280
|
+
"data": {
|
281
|
+
"title": "Example Feed"
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
end
|
286
|
+
|
287
|
+
class BaseWrappedRootExampleClient < Flexirest::Base
|
288
|
+
base_url "http://www.example.com"
|
289
|
+
wrap_root "base_data"
|
290
|
+
end
|
291
|
+
|
292
|
+
class GlobalWrappedRootExampleClient < BaseWrappedRootExampleClient
|
293
|
+
put :wrapped, "/put/:id"
|
294
|
+
end
|
295
|
+
|
296
|
+
class OverrideGlobalWrappedRootForFileExampleClient < BaseWrappedRootExampleClient
|
297
|
+
wrap_root "class_specific_data"
|
298
|
+
put :wrapped, "/put/:id"
|
299
|
+
end
|
300
|
+
|
301
|
+
class OverrideGlobalWrappedRootForRequestExampleClient < BaseWrappedRootExampleClient
|
302
|
+
put :wrapped, "/put/:id", wrap_root: "request_specific_data"
|
303
|
+
end
|
304
|
+
|
202
305
|
class WhitelistedDateClient < Flexirest::Base
|
203
306
|
base_url "http://www.example.com"
|
204
307
|
put :conversion, "/put/:id"
|
@@ -231,13 +334,53 @@ describe Flexirest::Request do
|
|
231
334
|
expect(servers.uniq.count).to eq(2)
|
232
335
|
end
|
233
336
|
|
234
|
-
it "should
|
337
|
+
it "should use the URL method for Basic HTTP Auth when no basic_auth_method is set" do
|
338
|
+
mocked_response = ::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{}))
|
339
|
+
|
235
340
|
connection = double(Flexirest::Connection).as_null_object
|
236
341
|
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://john:smith@www.example.com").and_return(connection)
|
237
|
-
expect(connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(
|
342
|
+
expect(connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(mocked_response)
|
238
343
|
AuthenticatedExampleClient.all
|
239
344
|
end
|
240
345
|
|
346
|
+
it "should use the headers method for Basic auth when basic_auth_method is set to :header" do
|
347
|
+
mocked_response = ::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{}))
|
348
|
+
headers_including_auth = hash_including({ "Authorization" => "Basic am9objpzbWl0aA==" })
|
349
|
+
|
350
|
+
connection = double(Flexirest::Connection).as_null_object
|
351
|
+
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://www.example.com").and_return(connection)
|
352
|
+
expect(connection).to receive(:get).with("/", hash_including(headers: headers_including_auth)).and_return(mocked_response)
|
353
|
+
AuthenticatedBasicHeaderExampleClient.all
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should raise an error if Basic HTTP method is not :header or :url" do
|
357
|
+
expect do
|
358
|
+
AuthenticatedExampleClient.class_eval do
|
359
|
+
basic_auth_method :some_invalid_value
|
360
|
+
end
|
361
|
+
end.to raise_error(RuntimeError, "Invalid basic_auth_method :some_invalid_value. Valid methods are :url (default) and :header.")
|
362
|
+
end
|
363
|
+
|
364
|
+
it "should use the setting set on the parent class" do
|
365
|
+
mocked_response = ::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{}))
|
366
|
+
headers_including_auth = hash_including({ "Authorization" => "Basic am9objpzbWl0aA==" })
|
367
|
+
|
368
|
+
connection = double(Flexirest::Connection).as_null_object
|
369
|
+
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://www.example.com").and_return(connection)
|
370
|
+
expect(connection).to receive(:get).with("/", hash_including(headers: headers_including_auth)).and_return(mocked_response)
|
371
|
+
AuthenticatedBasicHeaderExampleClientChildClass.child_method
|
372
|
+
end
|
373
|
+
|
374
|
+
it "should use the URL method for Basic auth when basic_auth_method is set to :url (and not include Authorization header)" do
|
375
|
+
mocked_response = ::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{}))
|
376
|
+
headers_not_including_auth = hash_excluding("Authorization")
|
377
|
+
|
378
|
+
connection = double(Flexirest::Connection).as_null_object
|
379
|
+
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://john:smith@www.example.com").and_return(connection)
|
380
|
+
expect(connection).to receive(:get).with("/", headers: headers_not_including_auth).and_return(mocked_response)
|
381
|
+
AuthenticatedBasicUrlExampleClient.all
|
382
|
+
end
|
383
|
+
|
241
384
|
it "should get an HTTP connection with basic authentication using procs when called in a class context" do
|
242
385
|
connection = double(Flexirest::Connection).as_null_object
|
243
386
|
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://bill:jones@www.example.com").and_return(connection)
|
@@ -1005,7 +1148,7 @@ describe Flexirest::Request do
|
|
1005
1148
|
rescue Flexirest::HTTPServerException => e
|
1006
1149
|
e
|
1007
1150
|
end
|
1008
|
-
expect(e).to be_instance_of(Flexirest::
|
1151
|
+
expect(e).to be_instance_of(Flexirest::HTTPInternalServerException)
|
1009
1152
|
expect(e.status).to eq(500)
|
1010
1153
|
expect(e.result.first_name).to eq("John")
|
1011
1154
|
end
|
@@ -1021,7 +1164,7 @@ describe Flexirest::Request do
|
|
1021
1164
|
rescue Flexirest::HTTPServerException => e
|
1022
1165
|
e
|
1023
1166
|
end
|
1024
|
-
expect(e.message).to eq(%q{The POST to '/create' returned a 500 status, which raised a Flexirest::
|
1167
|
+
expect(e.message).to eq(%q{The POST to '/create' returned a 500 status, which raised a Flexirest::HTTPInternalServerException with a body of: \{"first_name":"John", "id":1234\}})
|
1025
1168
|
end
|
1026
1169
|
|
1027
1170
|
it "should raise a parse exception for invalid JSON returns" do
|
@@ -1036,7 +1179,7 @@ describe Flexirest::Request do
|
|
1036
1179
|
rescue => e
|
1037
1180
|
e
|
1038
1181
|
end
|
1039
|
-
expect(e).to be_instance_of(Flexirest::
|
1182
|
+
expect(e).to be_instance_of(Flexirest::HTTPInternalServerException)
|
1040
1183
|
expect(e.status).to eq(500)
|
1041
1184
|
expect(e.result).to eq(error_content)
|
1042
1185
|
end
|
@@ -1355,6 +1498,62 @@ describe Flexirest::Request do
|
|
1355
1498
|
expect(IgnoredMultiLevelRootExampleClient.multi_level_root.title).to eq("Example Multi Level Feed")
|
1356
1499
|
end
|
1357
1500
|
|
1501
|
+
it "should ignore a specified root element" do
|
1502
|
+
expect(LocalIgnoredRootExampleClient.root.title).to eq("Example Feed")
|
1503
|
+
end
|
1504
|
+
|
1505
|
+
it "should ignore a specified multi-level root element" do
|
1506
|
+
expect(LocalIgnoredMultiLevelRootExampleClient.multi_level_root.title).to eq("Example Multi Level Feed")
|
1507
|
+
end
|
1508
|
+
|
1509
|
+
it "should ignore a specified root element" do
|
1510
|
+
expect(GlobalIgnoredRootExampleClient.root.title).to eq("Example Feed")
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
it "should ignore a specified root element" do
|
1514
|
+
expect(OverrideGlobalIgnoredRootForFileExampleClient.root.title).to eq("Example Feed")
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
it "should ignore a specified root element" do
|
1518
|
+
expect(OverrideGlobalIgnoredRootForRequestExampleClient.root.title).to eq("Example Feed")
|
1519
|
+
end
|
1520
|
+
|
1521
|
+
it "should wrap elements if specified, in form-encoded format" do
|
1522
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q(base_data%5Bdebug%5D=true&base_data%5Btest%5D=foo), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1523
|
+
GlobalWrappedRootExampleClient.request_body_type :form_encoded
|
1524
|
+
GlobalWrappedRootExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
it "should wrap elements if specified, in form-encoded format" do
|
1528
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q(class_specific_data%5Bdebug%5D=true&class_specific_data%5Btest%5D=foo), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1529
|
+
OverrideGlobalWrappedRootForFileExampleClient.request_body_type :form_encoded
|
1530
|
+
OverrideGlobalWrappedRootForFileExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
it "should wrap elements if specified, in form-encoded format" do
|
1534
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q(request_specific_data%5Bdebug%5D=true&request_specific_data%5Btest%5D=foo), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1535
|
+
OverrideGlobalWrappedRootForRequestExampleClient.request_body_type :form_encoded
|
1536
|
+
OverrideGlobalWrappedRootForRequestExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1537
|
+
end
|
1538
|
+
|
1539
|
+
it "should encode the body wrapped in a root element in a JSON format if specified" do
|
1540
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q({"base_data":{"debug":true,"test":"foo"}}), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1541
|
+
GlobalWrappedRootExampleClient.request_body_type :json
|
1542
|
+
GlobalWrappedRootExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
it "should encode the body wrapped in a root element in a JSON format if specified" do
|
1546
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q({"class_specific_data":{"debug":true,"test":"foo"}}), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1547
|
+
OverrideGlobalWrappedRootForFileExampleClient.request_body_type :json
|
1548
|
+
OverrideGlobalWrappedRootForFileExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
it "should encode the body wrapped in a root element in a JSON format if specified" do
|
1552
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q({"request_specific_data":{"debug":true,"test":"foo"}}), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
|
1553
|
+
OverrideGlobalWrappedRootForRequestExampleClient.request_body_type :json
|
1554
|
+
OverrideGlobalWrappedRootForRequestExampleClient.wrapped id:1234, debug:true, test:'foo'
|
1555
|
+
end
|
1556
|
+
|
1358
1557
|
context "Parameter preparation" do
|
1359
1558
|
method = {url: "http://www.example.com", method: :get}
|
1360
1559
|
object = nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexirest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -176,14 +176,14 @@ dependencies:
|
|
176
176
|
requirements:
|
177
177
|
- - ">="
|
178
178
|
- !ruby/object:Gem::Version
|
179
|
-
version:
|
179
|
+
version: '0'
|
180
180
|
type: :development
|
181
181
|
prerelease: false
|
182
182
|
version_requirements: !ruby/object:Gem::Requirement
|
183
183
|
requirements:
|
184
184
|
- - ">="
|
185
185
|
- !ruby/object:Gem::Version
|
186
|
-
version:
|
186
|
+
version: '0'
|
187
187
|
- !ruby/object:Gem::Dependency
|
188
188
|
name: mime-types
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|