active_rest_client 0.9.75 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -46,7 +46,7 @@ module ActiveRestClient
46
46
  def read_cached_response(request)
47
47
  if cache_store && perform_caching
48
48
  key = "#{request.class_name}:#{request.original_url}"
49
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{key} - Reading from cache"
49
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{key} - Trying to read from cache"
50
50
  value = cache_store.read(key)
51
51
  value = Marshal.load(value) rescue value
52
52
  end
@@ -17,6 +17,10 @@ module ActiveRestClient
17
17
  _map_call(name, url:url, method: :delete, options:options)
18
18
  end
19
19
 
20
+ def patch(name, url, options = {})
21
+ _map_call(name, url:url, method: :patch, options:options)
22
+ end
23
+
20
24
  def _map_call(name, details)
21
25
  _calls[name] = {name:name}.merge(details)
22
26
  _calls["lazy_#{name}".to_sym] = {name:name}.merge(details)
@@ -114,6 +114,11 @@ module ActiveRestClient
114
114
  elsif cached.etag.to_s != "" #present? isn't working for some reason
115
115
  ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag cached copy found with etag #{cached.etag}"
116
116
  etag = cached.etag
117
+ response = do_request(etag)
118
+ if response.status == 304
119
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response status 304. Copy is still fresh"
120
+ return handle_cached_response(cached)
121
+ end
117
122
  end
118
123
  end
119
124
  response = if proxy
@@ -224,11 +229,12 @@ module ActiveRestClient
224
229
 
225
230
  if verbose?
226
231
  ActiveRestClient::Logger.debug "ActiveRestClient Verbose Log:"
227
- ActiveRestClient::Logger.debug " > GET #{@url} HTTP/1.1"
232
+ ActiveRestClient::Logger.debug " Request"
233
+ ActiveRestClient::Logger.debug " >> GET #{@url} HTTP/1.1"
228
234
  http_headers.each do |k,v|
229
- ActiveRestClient::Logger.debug " > #{k} : #{v}"
235
+ ActiveRestClient::Logger.debug " >> #{k} : #{v}"
230
236
  end
231
- ActiveRestClient::Logger.debug " > #{@body}"
237
+ ActiveRestClient::Logger.debug " >> Body:\n#{@body}"
232
238
  end
233
239
 
234
240
  case http_method
@@ -245,10 +251,12 @@ module ActiveRestClient
245
251
  end
246
252
 
247
253
  if verbose?
254
+ ActiveRestClient::Logger.debug " Response"
255
+ ActiveRestClient::Logger.debug " << Status : #{response.status}"
248
256
  response.headers.each do |k,v|
249
- ActiveRestClient::Logger.debug " < #{k} : #{v}"
257
+ ActiveRestClient::Logger.debug " << #{k} : #{v}"
250
258
  end
251
- ActiveRestClient::Logger.debug " < #{response.body}"
259
+ ActiveRestClient::Logger.debug " << Body:\n#{response.body}"
252
260
  end
253
261
 
254
262
  response
@@ -268,62 +276,49 @@ module ActiveRestClient
268
276
  end
269
277
 
270
278
  def handle_response(response)
271
- if response.status == 304
272
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag copy is the same as the server"
273
- return :not_modified
274
- end
275
- if response.respond_to?(:proxied) && response.proxied
276
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response was proxied, unable to determine size"
277
- else
278
- ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response received #{response.body.size} bytes"
279
- end
280
-
281
- if @method[:options][:plain]
282
- return @response = response.body
283
- end
284
-
285
279
  @response = response
280
+ @response.status ||= 200
286
281
 
287
- if response.body.is_a?(Array) || response.body.is_a?(Hash)
288
- body = response.body
289
- else
290
- body = MultiJson.load(response.body) || {}
291
- end
292
- body = begin
293
- @method[:name].nil? ? body : translator.send(@method[:name], body)
294
- rescue NoMethodError
295
- body
296
- end
297
- if body.is_a? Array
298
- result = ActiveRestClient::ResultIterator.new(response.status)
299
- body.each do |json_object|
300
- result << new_object(json_object, @overriden_name)
282
+ if (200..399).include? @response.status
283
+ if response.status == 304
284
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Etag copy is the same as the server"
285
+ return :not_modified
286
+ end
287
+ if @method[:options][:plain]
288
+ return @response = response.body
289
+ elsif is_json_response?
290
+ if @response.respond_to?(:proxied) && @response.proxied
291
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response was proxied, unable to determine size"
292
+ else
293
+ ActiveRestClient::Logger.debug " \033[1;4;32m#{ActiveRestClient::NAME}\033[0m #{@instrumentation_name} - Response received #{@response.body.size} bytes"
294
+ end
295
+ result = generate_new_object
296
+ else
297
+ raise ResponseParseException.new(status:@response.status, body:@response.body)
301
298
  end
302
299
  else
303
- result = new_object(body, @overriden_name)
304
- result._status = response.status
305
- unless object_is_class?
306
- @object._copy_from(result)
307
- result = @object
300
+ if is_json_response?
301
+ error_response = generate_new_object(mutable: false)
302
+ else
303
+ error_response = @response.body
304
+ end
305
+ if @response.status == 400
306
+ raise HTTPBadRequestClientException.new(status:@response.status, result:error_response, url:@url)
307
+ elsif @response.status == 401
308
+ raise HTTPUnauthorisedClientException.new(status:@response.status, result:error_response, url:@url)
309
+ elsif @response.status == 403
310
+ raise HTTPForbiddenClientException.new(status:@response.status, result:error_response, url:@url)
311
+ elsif @response.status == 404
312
+ raise HTTPNotFoundClientException.new(status:@response.status, result:error_response, url:@url)
313
+ elsif (400..499).include? @response.status
314
+ raise HTTPClientException.new(status:@response.status, result:error_response, url:@url)
315
+ elsif (500..599).include? @response.status
316
+ raise HTTPServerException.new(status:@response.status, result:error_response, url:@url)
308
317
  end
309
318
  end
310
319
 
311
- response.status ||= 200
312
- if response.status == 401
313
- raise HTTPUnauthorisedClientException.new(status:response.status, result:result, url:@url)
314
- elsif response.status == 403
315
- raise HTTPForbiddenClientException.new(status:response.status, result:result, url:@url)
316
- elsif response.status == 404
317
- raise HTTPNotFoundClientException.new(status:response.status, result:result, url:@url)
318
- elsif (400..499).include? response.status
319
- raise HTTPClientException.new(status:response.status, result:result, url:@url)
320
- elsif (500..599).include? response.status
321
- raise HTTPServerException.new(status:response.status, result:result, url:@url)
322
- end
323
320
 
324
321
  result
325
- rescue MultiJson::ParseError
326
- raise ResponseParseException.new(status:response.status, body:response.body)
327
322
  end
328
323
 
329
324
  def new_object(attributes, name = nil)
@@ -418,6 +413,39 @@ module ActiveRestClient
418
413
 
419
414
  attributes
420
415
  end
416
+
417
+ private
418
+
419
+ def is_json_response?
420
+ @response.headers['Content-Type'].nil? || @response.headers['Content-Type'].include?('json')
421
+ end
422
+
423
+ def generate_new_object(options={})
424
+ if @response.body.is_a?(Array) || @response.body.is_a?(Hash)
425
+ body = @response.body
426
+ else
427
+ body = MultiJson.load(@response.body) || {}
428
+ end
429
+ body = begin
430
+ @method[:name].nil? ? body : translator.send(@method[:name], body)
431
+ rescue NoMethodError
432
+ body
433
+ end
434
+ if body.is_a? Array
435
+ result = ActiveRestClient::ResultIterator.new(@response.status)
436
+ body.each do |json_object|
437
+ result << new_object(json_object, @overriden_name)
438
+ end
439
+ else
440
+ result = new_object(body, @overriden_name)
441
+ result._status = @response.status
442
+ if !object_is_class? && options[:mutable] != false
443
+ @object._copy_from(result)
444
+ result = @object
445
+ end
446
+ end
447
+ result
448
+ end
421
449
  end
422
450
 
423
451
  class RequestException < StandardError ; end
@@ -441,6 +469,7 @@ module ActiveRestClient
441
469
  end
442
470
  class HTTPClientException < HTTPException ; end
443
471
  class HTTPUnauthorisedClientException < HTTPClientException ; end
472
+ class HTTPBadRequestClientException < HTTPClientException ; end
444
473
  class HTTPForbiddenClientException < HTTPClientException ; end
445
474
  class HTTPNotFoundClientException < HTTPClientException ; end
446
475
  class HTTPServerException < HTTPException ; end
@@ -1,3 +1,3 @@
1
1
  module ActiveRestClient
2
- VERSION = "0.9.75"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -8,7 +8,8 @@ class MappingExample < MappingExampleBase
8
8
  get :test_get, "/get", tag:1, fake:"{result:true}", lazy:[:something]
9
9
  put :test_put, "/put", tag:2
10
10
  post :test_post, "/post", tag:3
11
- delete :test_delete, "/delete", tag:4
11
+ patch :test_patch, "/patch", tag:4
12
+ delete :test_delete, "/delete", tag:5
12
13
  end
13
14
 
14
15
  describe ActiveRestClient::Mapping do
@@ -23,6 +24,7 @@ describe ActiveRestClient::Mapping do
23
24
  expect(MappingExample._calls[:test_get][:url]).to eq("/get")
24
25
  expect(MappingExample._calls[:test_put][:url]).to eq("/put")
25
26
  expect(MappingExample._calls[:test_post][:url]).to eq("/post")
27
+ expect(MappingExample._calls[:test_patch][:url]).to eq("/patch")
26
28
  expect(MappingExample._calls[:test_delete][:url]).to eq("/delete")
27
29
  end
28
30
 
@@ -30,6 +32,7 @@ describe ActiveRestClient::Mapping do
30
32
  expect(MappingExample._calls[:test_get][:method]).to eq(:get)
31
33
  expect(MappingExample._calls[:test_put][:method]).to eq(:put)
32
34
  expect(MappingExample._calls[:test_post][:method]).to eq(:post)
35
+ expect(MappingExample._calls[:test_patch][:method]).to eq(:patch)
33
36
  expect(MappingExample._calls[:test_delete][:method]).to eq(:delete)
34
37
  end
35
38
 
@@ -39,7 +42,8 @@ describe ActiveRestClient::Mapping do
39
42
  expect(MappingExample._calls[:test_get][:options][:tag]).to eq(1)
40
43
  expect(MappingExample._calls[:test_put][:options][:tag]).to eq(2)
41
44
  expect(MappingExample._calls[:test_post][:options][:tag]).to eq(3)
42
- expect(MappingExample._calls[:test_delete][:options][:tag]).to eq(4)
45
+ expect(MappingExample._calls[:test_patch][:options][:tag]).to eq(4)
46
+ expect(MappingExample._calls[:test_delete][:options][:tag]).to eq(5)
43
47
  end
44
48
 
45
49
  it "should allow for mapped calls on the class" do
@@ -233,8 +233,8 @@ describe ActiveRestClient::Request do
233
233
  ActiveRestClient::ConnectionManager.should_receive(:get_connection).and_return(connection)
234
234
  connection.should_receive(:get).with("/all", an_instance_of(Hash)).and_return(OpenStruct.new(body:'{"result":true}', headers:{"Content-Type" => "application/json", "Connection" => "close"}))
235
235
  ActiveRestClient::Logger.should_receive(:debug).with("ActiveRestClient Verbose Log:")
236
- ActiveRestClient::Logger.should_receive(:debug).with(/ > /).at_least(:twice)
237
- ActiveRestClient::Logger.should_receive(:debug).with(/ < /).at_least(:twice)
236
+ ActiveRestClient::Logger.should_receive(:debug).with(/ >> /).at_least(:twice)
237
+ ActiveRestClient::Logger.should_receive(:debug).with(/ << /).at_least(:twice)
238
238
  ActiveRestClient::Logger.stub(:debug).with(any_args)
239
239
  VerboseExampleClient.all
240
240
  end
@@ -270,7 +270,7 @@ describe ActiveRestClient::Request do
270
270
  end
271
271
  expect(e).to be_instance_of(ActiveRestClient::HTTPForbiddenClientException)
272
272
  expect(e.status).to eq(403)
273
- expect(e.result.first_name).to eq("John")
273
+ expect(e.result.first_name).to eq("John")
274
274
  end
275
275
 
276
276
  it "should raise a not found client exception for 404 errors" do
@@ -304,7 +304,7 @@ describe ActiveRestClient::Request do
304
304
  end
305
305
  expect(e).to be_instance_of(ActiveRestClient::HTTPClientException)
306
306
  expect(e.status).to eq(409)
307
- expect(e.result.first_name).to eq("John")
307
+ expect(e.result.first_name).to eq("John")
308
308
  end
309
309
 
310
310
  it "should raise a server exception for 5xx errors" do
@@ -330,25 +330,79 @@ describe ActiveRestClient::Request do
330
330
  any_instance.
331
331
  should_receive(:post).
332
332
  with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
333
- and_return(OpenStruct.new(body:error_content, headers:{}, status:500))
333
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:500))
334
334
  object = ExampleClient.new(first_name:"John", should_disappear:true)
335
335
  begin
336
336
  object.create
337
- rescue ActiveRestClient::ResponseParseException => e
337
+ rescue => e
338
338
  e
339
339
  end
340
- expect(e).to be_instance_of(ActiveRestClient::ResponseParseException)
340
+ expect(e).to be_instance_of(ActiveRestClient::HTTPServerException)
341
341
  expect(e.status).to eq(500)
342
+ expect(e.result).to eq(error_content)
343
+ end
344
+
345
+ it "should raise a bad request exception for 400 response status" do
346
+ error_content = "<h1>400 Bad Request</h1>"
347
+ ActiveRestClient::Connection.
348
+ any_instance.
349
+ should_receive(:post).
350
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
351
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:400))
352
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
353
+ begin
354
+ object.create
355
+ rescue => e
356
+ e
357
+ end
358
+ expect(e).to be_instance_of(ActiveRestClient::HTTPBadRequestClientException)
359
+ expect(e.status).to eq(400)
360
+ expect(e.result).to eq(error_content)
361
+ end
362
+
363
+ it "should raise response parse exception for 200 response status and non json content type" do
364
+ error_content = "<h1>malformed json</h1>"
365
+ ActiveRestClient::Connection.
366
+ any_instance.
367
+ should_receive(:post).
368
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
369
+ and_return(OpenStruct.new(body:error_content, headers:{'Content-Type' => 'text/html'}, status:200))
370
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
371
+ begin
372
+ object.create
373
+ rescue => e
374
+ e
375
+ end
376
+ expect(e).to be_instance_of(ActiveRestClient::ResponseParseException)
377
+ expect(e.status).to eq(200)
342
378
  expect(e.body).to eq(error_content)
343
379
  end
344
380
 
381
+ it "should not override the attributes of the existing object on error response status" do
382
+ ActiveRestClient::Connection.
383
+ any_instance.
384
+ should_receive(:post).
385
+ with("/create", "first_name=John&should_disappear=true", an_instance_of(Hash)).
386
+ and_return(OpenStruct.new(body:'{"errors": ["validation": "error in validation"]}', headers:{'Content-Type' => 'text/html'}, status:400))
387
+ object = ExampleClient.new(first_name:"John", should_disappear:true)
388
+ begin
389
+ object.create
390
+ rescue => e
391
+ e
392
+ end
393
+ expect(e).to be_instance_of(ActiveRestClient::HTTPBadRequestClientException)
394
+ expect(e.status).to eq(400)
395
+ expect(object.first_name).to eq 'John'
396
+ expect(object.errors).to be_nil
397
+ end
398
+
345
399
  it "should raise an exception if you try to pass in an unsupport method" do
346
400
  method = {:method => :wiggle, url:"/"}
347
401
  class RequestFakeObject
348
402
  def request_body_type
349
403
  :form_encoded
350
404
  end
351
-
405
+
352
406
  def base_url
353
407
  "http://www.example.com/"
354
408
  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: 0.9.75
4
+ version: 1.0.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: 2014-03-21 00:00:00.000000000 Z
12
+ date: 2014-04-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -219,12 +219,15 @@ files:
219
219
  - ".rspec"
220
220
  - ".simplecov"
221
221
  - ".travis.yml"
222
+ - CONTRIBUTING.md
222
223
  - Gemfile
223
224
  - Guardfile
224
225
  - LICENSE.txt
225
226
  - README.md
226
227
  - Rakefile
227
228
  - active_rest_client.gemspec
229
+ - doc/ActiveRestClient Internals.graffle
230
+ - doc/ActiveRestClient Internals.png
228
231
  - lib/active_rest_client.rb
229
232
  - lib/active_rest_client/base.rb
230
233
  - lib/active_rest_client/caching.rb
@@ -282,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
285
  version: '0'
283
286
  requirements: []
284
287
  rubyforge_project:
285
- rubygems_version: 2.2.0
288
+ rubygems_version: 2.2.2
286
289
  signing_key:
287
290
  specification_version: 4
288
291
  summary: This gem is for accessing REST services in an ActiveRecord style. ActiveResource