From 5ae25f85d95c93e14114b025c1a01b85eb2c1645 Mon Sep 17 00:00:00 2001 From: Romain d'Alverny Date: Fri, 4 Aug 2017 14:08:50 +0200 Subject: [PATCH 1/3] Serialize to JSON when content type is set to JSON Until now, the request body is only serialized if it's a Hash. But it could be an Array, or any other serializable type, and those bodies are serialized. See #129, probably #141 as well. I am not sure if this wouldn't break use cases where the body is already expected to be serialized. --- lib/airborne/rest_client_requester.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/airborne/rest_client_requester.rb b/lib/airborne/rest_client_requester.rb index 3ebe68f..220d461 100644 --- a/lib/airborne/rest_client_requester.rb +++ b/lib/airborne/rest_client_requester.rb @@ -7,7 +7,7 @@ def make_request(method, url, options = {}) res = if method == :post || method == :patch || method == :put begin request_body = options[:body].nil? ? '' : options[:body] - request_body = request_body.to_json if options[:body].is_a?(Hash) + request_body = request_body.to_json if is_json_request(headers) RestClient.send(method, get_url(url), request_body, headers) rescue RestClient::Exception => e e.response @@ -24,6 +24,10 @@ def make_request(method, url, options = {}) private + def is_json_request(headers) + headers.fetch(:content_type) == :json + end + def base_headers { content_type: :json }.merge(Airborne.configuration.headers || {}) end From 1373fd87353716b485172a8190ecdd41819d02ca Mon Sep 17 00:00:00 2001 From: Romain d'Alverny Date: Fri, 4 Aug 2017 23:44:16 +0200 Subject: [PATCH 2/3] Update README, add 2 spec tests --- README.md | 9 ++++++++- spec/airborne/client_requester_spec.rb | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4eaa58b..c410e47 100644 --- a/README.md +++ b/README.md @@ -137,12 +137,19 @@ When calling any of the methods above, you can pass request headers to be used. get 'http://example.com/api/v1/my_api', { 'x-auth-token' => 'my_token' } ``` -For requests that require a body (`post`, `put`, `patch`) you can pass the body as a hash as well: +For requests that require a body (`post`, `put`, `patch`) you can pass the body as well: ```ruby post 'http://example.com/api/v1/my_api', { :name => 'John Doe' }, { 'x-auth-token' => 'my_token' } ``` +The body may be any JSON-serializable type, as long as you want to post `application/json` content type. +You may set a different content type and post a string body this way: + +```ruby +post 'http://example.com/api/v1/my_api', "Hello there!", { content_type: 'text/plain' } +``` + For requests that require Query params you can pass a params hash into headers. ```ruby diff --git a/spec/airborne/client_requester_spec.rb b/spec/airborne/client_requester_spec.rb index 3023801..3264956 100644 --- a/spec/airborne/client_requester_spec.rb +++ b/spec/airborne/client_requester_spec.rb @@ -33,4 +33,18 @@ expect(RestClient).to have_received(:send) .with(:get, 'http://www.example.com/foo', { content_type: 'text/plain' }) end + + it 'should serialize body to json when :content_type is :json' do + post '/foo', { test: 'serialized' } + + expect(RestClient).to have_received(:send) + .with(:post, 'http://www.example.com/foo', '{"test":"serialized"}', { content_type: :json }) + end + + it 'should not serialize body to json when :content_type is not :json' do + post '/foo', { test: 'not serialized' }, { content_type: 'text/plain' } + + expect(RestClient).to have_received(:send) + .with(:post, 'http://www.example.com/foo', { test: 'not serialized' }, { content_type: 'text/plain' }) + end end From 26e5eb30647193a6376fec91e6c35fddde89f12f Mon Sep 17 00:00:00 2001 From: Romain d'Alverny Date: Mon, 18 Sep 2017 16:44:33 +0200 Subject: [PATCH 3/3] Add support for enhanced JSON content type header --- lib/airborne/rest_client_requester.rb | 3 ++- spec/airborne/client_requester_spec.rb | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/airborne/rest_client_requester.rb b/lib/airborne/rest_client_requester.rb index 220d461..13292ea 100644 --- a/lib/airborne/rest_client_requester.rb +++ b/lib/airborne/rest_client_requester.rb @@ -25,7 +25,8 @@ def make_request(method, url, options = {}) private def is_json_request(headers) - headers.fetch(:content_type) == :json + header = headers.fetch(:content_type) + header == :json || /application\/([a-zA-Z0-9\.\_\-]*\+?)json/ =~ header end def base_headers diff --git a/spec/airborne/client_requester_spec.rb b/spec/airborne/client_requester_spec.rb index 3264956..136349f 100644 --- a/spec/airborne/client_requester_spec.rb +++ b/spec/airborne/client_requester_spec.rb @@ -34,14 +34,21 @@ .with(:get, 'http://www.example.com/foo', { content_type: 'text/plain' }) end - it 'should serialize body to json when :content_type is :json' do + it 'should serialize body to json when :content_type is (default) :json' do post '/foo', { test: 'serialized' } expect(RestClient).to have_received(:send) .with(:post, 'http://www.example.com/foo', '{"test":"serialized"}', { content_type: :json }) end - it 'should not serialize body to json when :content_type is not :json' do + it 'should serialize body to json when :content_type is any enhanced JSON content type' do + post '/foo', { test: 'serialized' }, { content_type: 'application/vnd.airborne.2+json' } + + expect(RestClient).to have_received(:send) + .with(:post, 'http://www.example.com/foo', '{"test":"serialized"}', { content_type: 'application/vnd.airborne.2+json' }) + end + + it 'should not serialize body to json when :content_type does not match JSON' do post '/foo', { test: 'not serialized' }, { content_type: 'text/plain' } expect(RestClient).to have_received(:send)