active_rest_client 1.1.12 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc5afe34d70f60f5233cff03578fe4a768aa7270
4
- data.tar.gz: 8dda814fdaccf4329fbe0314a72e274607a2eaf7
3
+ metadata.gz: aa1076e05dc54a578810a49033b1cfc0502b1292
4
+ data.tar.gz: 6f191932544fa702a4924b52baa9dc938a7a026e
5
5
  SHA512:
6
- metadata.gz: f2978f90bc9d9cbf9008c0567511b0f9eeb77ac6db7305437eb65456fe7e71f983e72fa6c03c17e44aa49e7290638c9537451a221fcffce6b1e0f12ff288c9fd
7
- data.tar.gz: df05700d52bff47bd9ff118f5da673e3b0c4a5a208f6cf3641d62d7e2815131e75c142aa0574d6709f5862f43ff38a21ad0a9edec073036e396ee3813a75a27f
6
+ metadata.gz: 0cd5f8c5c5e9cd899c2d079e0daaa16afe0529eb9dbbf07612cbba5d9086ccf0d1114ba93991c1c6294039b5366e99a1a560b997b82bbfa32ca79a9745131a2b
7
+ data.tar.gz: fb8400a0f3c11bc3fbb5ce3a531119dc8af08f5700ebcf286dc4399a320286f4cc80a84e4e5892d23fb46cd808522ea3938a9409c43395f74ab648cb032690c6
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ ## 1.2.0
4
+
5
+ Features:
6
+
7
+ - Allows for beta-support for XML APIs as well as JSON ones.
8
+
9
+ Bugfixes:
10
+
11
+ - In order to allow JRuby to work with ActiveRestClient, the hard-coded dependency on Patron has been removed.
12
+
13
+ ## 1.1.10 - 1.1.12
14
+
15
+ Features:
16
+
17
+ - Parallel requests can now be made
18
+
19
+ Bugfixes
20
+
21
+ - Some work around Faraday's weird method naming
22
+ - Start of XML support
23
+ - URL encoding username and password
24
+
25
+ ## 1.0.9
26
+
27
+ Bugfixes
28
+
29
+ - Correctly handling invalid cache expiry times
30
+
31
+ ## 1.0.8
32
+
33
+ Features:
34
+
35
+ - Added Api-Auth for authentication against APIs that use it
36
+ - Supporting array parameter types
37
+ - Relationships for 'has_one' can now be used
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![Coverage Status](https://coveralls.io/repos/whichdigital/active-rest-client/badge.png)](https://coveralls.io/r/whichdigital/active-rest-client)
5
5
  [![Code Climate](https://codeclimate.com/github/whichdigital/active-rest-client.png)](https://codeclimate.com/github/whichdigital/active-rest-client)
6
6
  [![Gem Version](https://badge.fury.io/rb/active_rest_client.png)](http://badge.fury.io/rb/active_rest_client)
7
+ [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/whichdigital/active-rest-client.svg)](http://isitmaintained.com/project/whichdigital/active-rest-client "Average time to resolve an issue")
8
+ [![Percentage of issues still open](http://isitmaintained.com/badge/open/whichdigital/active-rest-client.svg)](http://isitmaintained.com/project/whichdigital/active-rest-client "Percentage of issues still open")
7
9
 
8
10
  This gem is for accessing REST services in an ActiveRecord style. ActiveResource already exists for this, but it doesn't work where the resource naming doesn't follow Rails conventions, it doesn't have in-built caching and it's not as flexible in general.
9
11
 
@@ -125,13 +127,17 @@ puts @person.to_json
125
127
 
126
128
  ### Faraday Configuration
127
129
 
128
- ActiveRestClient uses Faraday to allow switching HTTP backends, the default is Patron. To change the used backend just set it in the class by setting `adapter` to a Faraday supported adapter symbol.
130
+ ActiveRestClient uses Faraday to allow switching HTTP backends, the default is to just use Faraday's default. To change the used backend just set it in the class by setting `adapter` to a Faraday supported adapter symbol.
129
131
 
130
132
  ```ruby
131
133
  ActiveRestClient::Base.adapter = :net_http
134
+ # or ...
135
+ ActiveRestClient::Base.adapter = :patron
132
136
  ```
133
137
 
134
- If you want more control you can pass a complete configuration block. For available config variables look into the Faraday documentation.
138
+ In versions before 1.2.0 the adapter was hardcoded to `:patron`, so if you want to ensure it still uses Patron, you should set this setting.
139
+
140
+ If you want more control you can pass a **complete** configuration block ("complete" means that the block does not *override* [the default configuration](https://github.com/whichdigital/active-rest-client/blob/5b1953d89e26c02ca74f74464ccb7cd4c9439dcc/lib/active_rest_client/configuration.rb#L184-L201), but rather *replaces* it). For available config variables look into the Faraday documentation.
135
141
 
136
142
  ```ruby
137
143
  ActiveRestClient::Base.faraday_config do |faraday|
@@ -139,7 +145,7 @@ ActiveRestClient::Base.faraday_config do |faraday|
139
145
  faraday.options.timeout = 10
140
146
  faraday.headers['User-Agent'] = "ActiveRestClient/#{ActiveRestClient::VERSION}"
141
147
  end
142
- ````
148
+ ```
143
149
  ### Associations
144
150
 
145
151
  There are two types of association. One assumes when you call a method you actually want it to call the method on a separate class (as that class has other methods that are useful). The other is lazy loading related classes from a separate URL.
@@ -205,9 +211,9 @@ And use it like this:
205
211
 
206
212
  #### Association Type 3 - HAL Auto-loaded Resources
207
213
 
208
- You don't need to define lazy attributes if they are defined using [HAL](http://stateless.co/hal_specification.html) (with an optional embedded representation). If your resource has an _links item (and optionally an _embedded item) then it will automatically treat the linked resources (with the _embedded cache) as if they were defined using `:lazy` as per type 2 above.
214
+ You don't need to define lazy attributes if they are defined using [HAL](http://stateless.co/hal_specification.html) (with an optional embedded representation). If your resource has an `_links` item (and optionally an `_embedded` item) then it will automatically treat the linked resources (with the `_embedded` cache) as if they were defined using `:lazy` as per type 2 above.
209
215
 
210
- If you need to, you can access properties of the HAL association. By default just using the HAL association gets the embedded resource (or requests the remote resource if not available in the _embedded list).
216
+ If you need to, you can access properties of the HAL association. By default just using the HAL association gets the embedded resource (or requests the remote resource if not available in the `_embedded` list).
211
217
 
212
218
  ```ruby
213
219
  @person = Person.find(1)
@@ -464,6 +470,13 @@ require 'api-auth'
464
470
  ActiveRestClient::Base.api_auth_credentials(@access_id, @secret_key)
465
471
  ```
466
472
 
473
+ You can also specify different credentials for different models just like configuring base_url
474
+ ```ruby
475
+ class Person < ActiveRestClient::Base
476
+ api_auth_credentials('123456', 'abcdef')
477
+ end
478
+ ```
479
+
467
480
  For more information on how to generate an access id and secret key please read the [Api-Auth](https://github.com/mgomes/api_auth) documentation.
468
481
 
469
482
  ### Body Types
@@ -577,7 +590,7 @@ people = Person._plain_request('http://api.example.com/v1/people') # Defaults to
577
590
  Person._plain_request('http://api.example.com/v1/people', :post, {id:1234,name:"John"}) # Post with parameters
578
591
  ```
579
592
 
580
- The parameters are the same as for _request, but it does no parsing on the response
593
+ The parameters are the same as for `_request`, but it does no parsing on the response
581
594
 
582
595
  ### Proxying APIs
583
596
 
@@ -814,6 +827,14 @@ puts @atom.feed.link.href
814
827
  end
815
828
  ```
816
829
 
830
+ If your XML object comes back with a root node and you'd like to ignore it, you can define the mapping as:
831
+
832
+ ```ruby
833
+ class Feed < ActiveRestClient::Base
834
+ get :atom, "/atom", ignore_xml_root: "feed"
835
+ end
836
+ ```
837
+
817
838
  For testing purposes, if you are using a `fake` content response when defining your endpoint, you should also provide `fake_content_type: "application/xml"` so that the parser knows to use XML parsing.
818
839
 
819
840
  ## Contributing
@@ -822,4 +843,4 @@ For testing purposes, if you are using a `fake` content response when defining y
822
843
  2. Create your feature branch (`git checkout -b my-new-feature`)
823
844
  3. Commit your changes (`git commit -am 'Add some feature'`)
824
845
  4. Push to the branch (`git push origin my-new-feature`)
825
- 5. Create new Pull Request
846
+ 5. Create new Pull Request
@@ -36,5 +36,4 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency "crack"
37
37
  spec.add_runtime_dependency "activesupport"
38
38
  spec.add_runtime_dependency "faraday"
39
- spec.add_runtime_dependency "patron", ">= 0.4.9" # 0.4.18 breaks against Curl v0.7.15 but works with webmock
40
39
  end
@@ -24,10 +24,10 @@ module ActiveRestClient
24
24
 
25
25
  attrs.each do |attribute_name, attribute_value|
26
26
  attribute_name = attribute_name.to_sym
27
- if attribute_value.to_s[/\d{4}\-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})/]
28
- @attributes[attribute_name] = DateTime.parse(attribute_value)
29
- elsif attribute_value.to_s =~ /^\d{4}\-\d{2}-\d{2}$/
27
+ if attribute_value.to_s[/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6]))))$/]
30
28
  @attributes[attribute_name] = Date.parse(attribute_value)
29
+ elsif attribute_value.to_s[/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/]
30
+ @attributes[attribute_name] = DateTime.parse(attribute_value)
31
31
  else
32
32
  @attributes[attribute_name] = attribute_value
33
33
  end
@@ -8,8 +8,8 @@ module ActiveRestClient
8
8
  @@password = nil
9
9
  @@request_body_type = :form_encoded
10
10
  @lazy_load = false
11
- @@api_auth_access_id = nil
12
- @@api_auth_secret_key = nil
11
+ @api_auth_access_id = nil
12
+ @api_auth_secret_key = nil
13
13
 
14
14
  def base_url(value = nil)
15
15
  if value.nil?
@@ -91,7 +91,7 @@ module ActiveRestClient
91
91
  end
92
92
 
93
93
  def adapter
94
- @adapter ||= :patron
94
+ @adapter ||= Faraday.default_adapter
95
95
  end
96
96
 
97
97
  def faraday_config(&block)
@@ -121,20 +121,32 @@ module ActiveRestClient
121
121
  raise MissingOptionalLibraryError.new("You must include the gem 'api-auth' in your Gemfile to set api-auth credentials.")
122
122
  end
123
123
 
124
- @@api_auth_access_id = access_id
125
- @@api_auth_secret_key = secret_key
124
+ @api_auth_access_id = access_id
125
+ @api_auth_secret_key = secret_key
126
126
  end
127
127
 
128
128
  def using_api_auth?
129
- !@@api_auth_access_id.nil? && !@@api_auth_secret_key.nil?
129
+ !self.api_auth_access_id.nil? && !self.api_auth_secret_key.nil?
130
130
  end
131
131
 
132
132
  def api_auth_access_id
133
- @@api_auth_access_id
133
+ if !@api_auth_access_id.nil?
134
+ return @api_auth_access_id
135
+ elsif self.superclass.respond_to?(:api_auth_access_id)
136
+ return self.superclass.api_auth_access_id
137
+ end
138
+
139
+ return nil
134
140
  end
135
141
 
136
142
  def api_auth_secret_key
137
- @@api_auth_secret_key
143
+ if !@api_auth_secret_key.nil?
144
+ return @api_auth_secret_key
145
+ elsif self.superclass.respond_to?(:api_auth_secret_key)
146
+ return self.superclass.api_auth_secret_key
147
+ end
148
+
149
+ return nil
138
150
  end
139
151
 
140
152
  def verbose!
@@ -162,9 +174,9 @@ module ActiveRestClient
162
174
  @whiny_missing = nil
163
175
  @lazy_load = false
164
176
  @faraday_config = default_faraday_config
165
- @adapter = :patron
166
- @@api_auth_access_id = nil
167
- @@api_auth_secret_key = nil
177
+ @adapter = Faraday.default_adapter
178
+ @api_auth_access_id = nil
179
+ @api_auth_secret_key = nil
168
180
  end
169
181
 
170
182
  private
@@ -34,40 +34,44 @@ module ActiveRestClient
34
34
  end
35
35
  end
36
36
 
37
- def get(path, headers={})
37
+ def get(path, options={})
38
+ set_defaults(options)
38
39
  make_safe_request(path) do
39
40
  @session.get(path) do |req|
40
- req.headers = req.headers.merge(headers)
41
- sign_request(req)
41
+ req.headers = req.headers.merge(options[:headers])
42
+ sign_request(req, options[:api_auth])
42
43
  end
43
44
  end
44
45
  end
45
46
 
46
- def put(path, data, headers={})
47
+ def put(path, data, options={})
48
+ set_defaults(options)
47
49
  make_safe_request(path) do
48
50
  @session.put(path) do |req|
49
- req.headers = req.headers.merge(headers)
51
+ req.headers = req.headers.merge(options[:headers])
50
52
  req.body = data
51
- sign_request(req)
53
+ sign_request(req, options[:api_auth])
52
54
  end
53
55
  end
54
56
  end
55
57
 
56
- def post(path, data, headers={})
58
+ def post(path, data, options={})
59
+ set_defaults(options)
57
60
  make_safe_request(path) do
58
61
  @session.post(path) do |req|
59
- req.headers = req.headers.merge(headers)
62
+ req.headers = req.headers.merge(options[:headers])
60
63
  req.body = data
61
- sign_request(req)
64
+ sign_request(req, options[:api_auth])
62
65
  end
63
66
  end
64
67
  end
65
68
 
66
- def delete(path, headers={})
69
+ def delete(path, options={})
70
+ set_defaults(options)
67
71
  make_safe_request(path) do
68
72
  @session.delete(path) do |req|
69
- req.headers = req.headers.merge(headers)
70
- sign_request(req)
73
+ req.headers = req.headers.merge(options[:headers])
74
+ sign_request(req, options[:api_auth])
71
75
  end
72
76
  end
73
77
  end
@@ -82,12 +86,18 @@ module ActiveRestClient
82
86
  @session.build_url(path).to_s
83
87
  end
84
88
 
85
- def sign_request(request)
86
- return if !ActiveRestClient::Base.using_api_auth?
89
+ def set_defaults(options)
90
+ options[:headers] ||= {}
91
+ options[:api_auth] ||= {}
92
+ return options
93
+ end
94
+
95
+ def sign_request(request, api_auth)
96
+ return if api_auth[:api_auth_access_id].nil? || api_auth[:api_auth_secret_key].nil?
87
97
  ApiAuth.sign!(
88
98
  request,
89
- ActiveRestClient::Base.api_auth_access_id,
90
- ActiveRestClient::Base.api_auth_secret_key)
99
+ api_auth[:api_auth_access_id],
100
+ api_auth[:api_auth_secret_key])
91
101
  end
92
102
  end
93
103
  end
@@ -1,3 +1,7 @@
1
- class Faraday::Env
2
- alias_method :headers, :response_headers
1
+ require 'faraday'
2
+
3
+ if defined?("Faraday::Env")
4
+ class Faraday::Env
5
+ alias_method :headers, :response_headers
6
+ end
3
7
  end
@@ -66,11 +66,24 @@ module ActiveRestClient
66
66
  @original_handler.call(@request)
67
67
  end
68
68
 
69
+ def result_is_json_or_unspecified?(result)
70
+ result.headers['Content-Type'].include?('json')
71
+ rescue
72
+ true
73
+ end
74
+
69
75
  def translate(result, options = {})
70
- result.headers["content-type"] = "application/hal+json"
76
+ incoming_content_type = result.headers['Content-Type']
77
+ if result_is_json_or_unspecified?(result)
78
+ result.headers["content-type"] = "application/hal+json"
79
+ end
71
80
  result = FaradayResponseProxy.new(OpenStruct.new(status:result.status, response_headers:result.headers, body:result.body))
72
81
  if result.body.present?
73
- result.body = yield MultiJson.load(result.body)
82
+ if incoming_content_type && incoming_content_type["xml"]
83
+ result.body = yield Crack::XML.parse(result.body)
84
+ else
85
+ result.body = yield MultiJson.load(result.body)
86
+ end
74
87
  end
75
88
  result
76
89
  end
@@ -48,6 +48,30 @@ module ActiveRestClient
48
48
  end
49
49
  end
50
50
 
51
+ def using_api_auth?
52
+ if object_is_class?
53
+ @object.using_api_auth?
54
+ else
55
+ @object.class.using_api_auth?
56
+ end
57
+ end
58
+
59
+ def api_auth_access_id
60
+ if object_is_class?
61
+ @object.api_auth_access_id
62
+ else
63
+ @object.class.api_auth_access_id
64
+ end
65
+ end
66
+
67
+ def api_auth_secret_key
68
+ if object_is_class?
69
+ @object.api_auth_secret_key
70
+ else
71
+ @object.class.api_auth_secret_key
72
+ end
73
+ end
74
+
51
75
  def username
52
76
  if object_is_class?
53
77
  @object.username
@@ -283,15 +307,23 @@ module ActiveRestClient
283
307
  ActiveRestClient::Logger.debug " >> Body:\n#{@body}"
284
308
  end
285
309
 
310
+ request_options = {:headers => http_headers}
311
+ if using_api_auth?
312
+ request_options[:api_auth] = {
313
+ :api_auth_access_id => api_auth_access_id,
314
+ :api_auth_secret_key => api_auth_secret_key
315
+ }
316
+ end
317
+
286
318
  case http_method
287
319
  when :get
288
- response = connection.get(@url, http_headers)
320
+ response = connection.get(@url, request_options)
289
321
  when :put
290
- response = connection.put(@url, @body, http_headers)
322
+ response = connection.put(@url, @body, request_options)
291
323
  when :post
292
- response = connection.post(@url, @body, http_headers)
324
+ response = connection.post(@url, @body, request_options)
293
325
  when :delete
294
- response = connection.delete(@url, http_headers)
326
+ response = connection.delete(@url, request_options)
295
327
  else
296
328
  raise InvalidRequestException.new("Invalid method #{http_method}")
297
329
  end
@@ -331,13 +363,13 @@ module ActiveRestClient
331
363
  else
332
364
  ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response received #{@response.body.size} bytes"
333
365
  end
334
- result = generate_new_object
366
+ result = generate_new_object(ignore_xml_root: @method[:options][:ignore_xml_root])
335
367
  else
336
368
  raise ResponseParseException.new(status:status, body:@response.body)
337
369
  end
338
370
  else
339
371
  if is_json_response? || is_xml_response?
340
- error_response = generate_new_object(mutable: false)
372
+ error_response = generate_new_object(mutable: false, ignore_xml_root: @method[:options][:ignore_xml_root])
341
373
  else
342
374
  error_response = @response.body
343
375
  end
@@ -483,6 +515,9 @@ module ActiveRestClient
483
515
  body = @response.body.blank? ? {} : MultiJson.load(@response.body)
484
516
  elsif is_xml_response?
485
517
  body = @response.body.blank? ? {} : Crack::XML.parse(@response.body)
518
+ if options[:ignore_xml_root]
519
+ body = body[options[:ignore_xml_root].to_s]
520
+ end
486
521
  end
487
522
  body = begin
488
523
  @method[:name].nil? ? body : translator.send(@method[:name], body)
@@ -1,3 +1,3 @@
1
1
  module ActiveRestClient
2
- VERSION = "1.1.12"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -80,6 +80,13 @@ describe ActiveRestClient::Base do
80
80
  expect(client["test"].to_s).to eq(t.to_datetime.to_s)
81
81
  end
82
82
 
83
+ it "should automatically parse ISO 8601 format date and time with milliseconds" do
84
+ t = Time.now
85
+ client = EmptyExample.new(:test => t.iso8601(3))
86
+ expect(client["test"]).to be_an_instance_of(DateTime)
87
+ expect(client["test"].to_s).to eq(t.to_datetime.to_s)
88
+ end
89
+
83
90
  it "should automatically parse ISO 8601 format dates" do
84
91
  d = Date.today
85
92
  client = EmptyExample.new(:test => d.iso8601)
@@ -111,7 +111,10 @@ describe ActiveRestClient::Caching do
111
111
  result:@cached_object,
112
112
  etag:@etag)
113
113
  expect_any_instance_of(CachingExampleCacheStore5).to receive(:read).once.with("Person:/").and_return(Marshal.dump(cached_response))
114
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/", hash_including("If-None-Match" => @etag)).and_return(::FaradayResponseMock.new(OpenStruct.new(status:304, response_headers:{})))
114
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:get){ |connection, path, options|
115
+ expect(path).to eq('/')
116
+ expect(options[:headers]).to include("If-None-Match" => @etag)
117
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(status:304, response_headers:{})))
115
118
  ret = Person.all
116
119
  expect(ret.first_name).to eq("Johnny")
117
120
  end
@@ -127,7 +130,10 @@ describe ActiveRestClient::Caching do
127
130
  response_body = Person.new(first_name: new_name).to_json
128
131
  response = ::FaradayResponseMock.new(double(status: 200, response_headers: {}, body: response_body))
129
132
  allow_any_instance_of(ActiveRestClient::Connection).to(
130
- receive(:get).with('/', hash_including('If-None-Match' => @etag)).and_return(response))
133
+ receive(:get){ |connection, path, options|
134
+ expect(path).to eq('/')
135
+ expect(options[:headers]).to include('If-None-Match' => @etag)
136
+ }.and_return(response))
131
137
 
132
138
  result = Person.all
133
139
 
@@ -155,6 +155,21 @@ describe ActiveRestClient::Configuration do
155
155
  it "should remember setting api_auth_secret_key" do
156
156
  expect(ConfigurationExample.api_auth_secret_key).to eq('secret123')
157
157
  end
158
+
159
+ it "should inherit api_auth_credentials when not set" do
160
+ class ConfigurationExtension < ConfigurationExample
161
+ end
162
+ expect(ConfigurationExtension.api_auth_access_id).to eq('id123')
163
+ expect(ConfigurationExtension.api_auth_secret_key).to eq('secret123')
164
+ end
165
+
166
+ it "should override inherited api_auth_credentials when set" do
167
+ class ConfigurationExtension2 < ConfigurationExample
168
+ end
169
+ ConfigurationExtension2.api_auth_credentials('id456', 'secret456')
170
+ expect(ConfigurationExtension2.api_auth_access_id).to eq('id456')
171
+ expect(ConfigurationExtension2.api_auth_secret_key).to eq('secret456')
172
+ end
158
173
  end
159
174
  end
160
175
 
@@ -194,7 +209,7 @@ describe ActiveRestClient::Configuration do
194
209
  let(:faraday_double){double(:faraday).as_null_object}
195
210
 
196
211
  it "should use default adapter if no other block set" do
197
- expect(faraday_double).to receive(:adapter).with(:patron)
212
+ expect(faraday_double).to receive(:adapter).with(Faraday.default_adapter)
198
213
  ConfigurationExample.faraday_config.call(faraday_double)
199
214
  end
200
215
 
@@ -100,8 +100,16 @@ describe ActiveRestClient::Connection do
100
100
 
101
101
  context 'with api auth signing requests' do
102
102
  before(:each) do
103
+ # Need to still call this to load the api_auth library so tests work
103
104
  ActiveRestClient::Base.api_auth_credentials('id123', 'secret123')
104
105
 
106
+ @options = {
107
+ :api_auth => {
108
+ :api_auth_access_id => 'id123',
109
+ :api_auth_secret_key => 'secret123'
110
+ }
111
+ }
112
+
105
113
  @default_headers = {'Date' => 'Sat, 14 Mar 2015 15:13:24 GMT'}
106
114
 
107
115
  ActiveRestClient::Base.faraday_config do |faraday|
@@ -115,7 +123,7 @@ describe ActiveRestClient::Connection do
115
123
  stub_request(:get, "www.example.com/foo")
116
124
  .with(:headers => @default_headers)
117
125
  .to_return(body: "{result:true}")
118
- result = @connection.get("/foo")
126
+ result = @connection.get("/foo", @options)
119
127
  expect(result.env.request_headers['Authorization']).to eq("APIAuth id123:PMWBThkB8vKbvUccHvoqu9G3eVk=")
120
128
  end
121
129
 
@@ -124,7 +132,7 @@ describe ActiveRestClient::Connection do
124
132
  with(body: "body", :headers => @default_headers).
125
133
  to_return(body: "{result:true}")
126
134
 
127
- result = @connection.put("/foo", "body")
135
+ result = @connection.put("/foo", "body", @options)
128
136
  expect(result.env.request_headers['Content-MD5']).to eq("hBotaJrYa9FhFEdFPCLG/A==")
129
137
  end
130
138
  end
@@ -43,6 +43,14 @@ class ProxyExample < ActiveRestClient::ProxyBase
43
43
  end
44
44
  end
45
45
 
46
+ get "/change-xml-format" do
47
+ response = passthrough
48
+ translate(response) do |body|
49
+ body["first_name"] = body["object"].delete("fname")
50
+ body
51
+ end
52
+ end
53
+
46
54
  get "/hal_test/:id" do
47
55
  response = passthrough
48
56
  translate(response) do |body|
@@ -70,6 +78,7 @@ class ProxyClientExample < ActiveRestClient::Base
70
78
  get :fake, "/fake"
71
79
  get :param, "/param/:id/:name"
72
80
  get :change_format, "/change-format"
81
+ get :change_xml_format, "/change-xml-format"
73
82
  post :create, "/create"
74
83
  put :update, "/update"
75
84
  get :not_proxied, "/not_proxied"
@@ -120,6 +129,16 @@ describe ActiveRestClient::Base do
120
129
  expect(ret.first_name).to eq("Billy")
121
130
  end
122
131
 
132
+ it "can intercept XML responses, parse the response, alter it and pass it on during the request" do
133
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/change-xml-format",
134
+ instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(
135
+ body:"<?xml version=\"1.0\" encoding=\"UTF-8\"?><object><fname>Billy</fname></object>",
136
+ status:200,
137
+ response_headers:{"Content-Type" => "application/xml"})))
138
+ ret = ProxyClientExample.change_xml_format
139
+ expect(ret.first_name).to eq("Billy")
140
+ end
141
+
123
142
  it 'skips the altering of the response body when there is none' do
124
143
  allow_any_instance_of(ActiveRestClient::Connection).to receive(:get).with('/change-format', instance_of(Hash))
125
144
  .and_return(double(body: '', status: 200, headers: {}))
@@ -7,6 +7,7 @@ describe ActiveRestClient::Request do
7
7
  class ExampleClient < ActiveRestClient::Base
8
8
  base_url "http://www.example.com"
9
9
  request_body_type :form_encoded
10
+ api_auth_credentials('id123', 'secret123')
10
11
 
11
12
  before_request do |name, request|
12
13
  if request.method[:name] == :headers
@@ -160,17 +161,28 @@ describe ActiveRestClient::Request do
160
161
  end
161
162
 
162
163
  it "should pass through custom headers" do
163
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/headers", hash_including("X-My-Header" => "myvalue")).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
164
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:get){ |connection, path, options|
165
+ expect(path).to eq('/headers')
166
+ expect(options[:headers]).to include("X-My-Header" => "myvalue")
167
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
164
168
  ExampleClient.headers
165
169
  end
166
170
 
167
171
  it "should set request header with content-type for default" do
168
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:put).with("/headers_default", "", hash_including("Content-Type" => "application/x-www-form-urlencoded")).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
172
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:put){ |connection, path, data, options|
173
+ expect(path).to eq('/headers_default')
174
+ expect(data).to eq('')
175
+ expect(options[:headers]).to include("Content-Type" => "application/x-www-form-urlencoded")
176
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
169
177
  ExampleClient.headers_default
170
178
  end
171
179
 
172
180
  it "should set request header with content-type for JSON" do
173
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:put).with("/headers_json", "{}", hash_including("Content-Type" => "application/json; charset=utf-8")).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
181
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:put){ |connection, path, data, options|
182
+ expect(path).to eq('/headers_json')
183
+ expect(data).to eq('{}')
184
+ expect(options[:headers]).to include("Content-Type" => "application/json; charset=utf-8")
185
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
174
186
  ExampleClient.headers_json
175
187
  end
176
188
 
@@ -578,7 +590,10 @@ describe ActiveRestClient::Request do
578
590
  let(:hal) { ExampleClient.hal }
579
591
 
580
592
  it "should request a HAL response or plain JSON" do
581
- expect_any_instance_of(ActiveRestClient::Connection).to receive(:get).with("/headers", hash_including("Accept" => "application/hal+json, application/json;q=0.5")).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
593
+ expect_any_instance_of(ActiveRestClient::Connection).to receive(:get){ |connection, path, options|
594
+ expect(path).to eq('/headers')
595
+ expect(options[:headers]).to include("Accept" => "application/hal+json, application/json;q=0.5")
596
+ }.and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
582
597
  ExampleClient.headers
583
598
  end
584
599
 
@@ -2,6 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  class XmlResponseExample < ActiveRestClient::Base
4
4
  base_url "http://www.example.com/v1/"
5
+ get :root, "/root", ignore_xml_root: "feed", fake_content_type: "application/xml", fake: %Q{
6
+ <?xml version="1.0" encoding="utf-8"?>
7
+ <feed xmlns="http://www.w3.org/2005/Atom">
8
+ <title>Example Feed</title>
9
+ </feed>
10
+ }
5
11
  get :atom, "/atom", fake: %Q{
6
12
  <?xml version="1.0" encoding="utf-8"?>
7
13
  <feed xmlns="http://www.w3.org/2005/Atom">
@@ -61,4 +67,8 @@ describe XmlResponseExample do
61
67
  expect(@atom.feed.entry[1].title).to eq("Something else cool happened")
62
68
  end
63
69
 
70
+ it "allows ignoring of the XML root node" do
71
+ @feed = XmlResponseExample.root
72
+ expect(@feed.title).to eq("Example Feed")
73
+ end
64
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_rest_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.12
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Which Ltd
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-08-12 00:00:00.000000000 Z
12
+ date: 2015-09-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -235,20 +235,6 @@ dependencies:
235
235
  - - ">="
236
236
  - !ruby/object:Gem::Version
237
237
  version: '0'
238
- - !ruby/object:Gem::Dependency
239
- name: patron
240
- requirement: !ruby/object:Gem::Requirement
241
- requirements:
242
- - - ">="
243
- - !ruby/object:Gem::Version
244
- version: 0.4.9
245
- type: :runtime
246
- prerelease: false
247
- version_requirements: !ruby/object:Gem::Requirement
248
- requirements:
249
- - - ">="
250
- - !ruby/object:Gem::Version
251
- version: 0.4.9
252
238
  description: Accessing REST services in an ActiveRecord style
253
239
  email:
254
240
  - swlicensing@which.co.uk
@@ -261,6 +247,7 @@ files:
261
247
  - ".rspec"
262
248
  - ".simplecov"
263
249
  - ".travis.yml"
250
+ - CHANGELOG.md
264
251
  - CONTRIBUTING.md
265
252
  - Gemfile
266
253
  - Guardfile