Skip to content

Commit

Permalink
Fix #347: Grape will accept any valid JSON as PUT or POST, including …
Browse files Browse the repository at this point in the history
…strings, symbols and arrays. JSON format APIs will always return valid JSON.
  • Loading branch information
dblock committed Mar 4, 2013
1 parent 0d05c42 commit 6fa8f59
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ Next Release
============

* [#352](https://github.com/intridea/grape/pull/352): Modified registration/execution order of Rack Middleware, fixes issues with `Rack::JSONP` responses that contain a `Grape::Entity` - [@deckchair](https://github.com/deckchair).
* [#347](https://github.com/intridea/grape/issues/347): Grape will accept any valid JSON as PUT or POST, including strings, symbols and arrays - [@qqshfox](https://github.com/qqshfox), [@dblock](https://github.com/dblock).
* [#347](https://github.com/intridea/grape/issues/347): JSON format APIs will always return valid JSON, eg. strings are now returned as `"string"` and no longer `string` - [@dblock](https://github.com/dblock).
* Your contribution here.

0.3.2 (2/28/2013)
Expand Down
1 change: 0 additions & 1 deletion lib/grape/formatter/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module Json
class << self

def call(object, env)
return object if object.is_a?(String)
return object.to_json if object.respond_to?(:to_json)
MultiJson.dump(object)
end
Expand Down
10 changes: 7 additions & 3 deletions lib/grape/middleware/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ def read_body_input
fmt = mime_types[request.media_type] if request.media_type
if content_type_for(fmt)
parser = Grape::Parser::Base.parser_for fmt, options
unless parser.nil?
if parser
begin
body = parser.call body, env
env['rack.request.form_hash'] = env['rack.request.form_hash'] ? env['rack.request.form_hash'].merge(body) : body
body = (env['api.request.body'] = parser.call(body, env))
if body.is_a?(Hash)
env['rack.request.form_hash'] = env['rack.request.form_hash'] ? env['rack.request.form_hash'].merge(body) : body
else
env['api.request.body'] = body

This comment has been minimized.

Copy link
@qqshfox

qqshfox Mar 4, 2013

Contributor

a little dup code?

This comment has been minimized.

Copy link
@dblock

dblock Mar 4, 2013

Author Member

Thanks for spotting this. Late night coding, fixed.

end
env['rack.request.form_input'] = env['rack.input']
rescue Exception => e
throw :error, :status => 400, :message => e.message
Expand Down
25 changes: 14 additions & 11 deletions spec/grape/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,14 @@ def app; subject end

describe 'root routes should work with' do
before do
subject.format :txt
def subject.enable_root_route!
self.get("/") {"root"}
self.get("/") { "root" }
end
end

after do
last_response.body.should eql 'root'
last_response.body.should eql "root"
end

describe 'path versioned APIs' do
Expand Down Expand Up @@ -314,16 +315,18 @@ def subject.enable_root_route!
last_response.body.should eql 'hiya'
end

%w(put post).each do |verb|
['string', :symbol, 1, -1.1, {}, [], true, false, nil].each do |object|
it "allows a(n) #{object.class} json object for #{verb.upcase} when accessing the params" do
subject.send(verb) do
params # TODO: get the object passed in
{}
[ :put, :post ].each do |verb|
context verb do
[ 'string', :symbol, 1, -1.1, {}, [], true, false, nil ].each do |object|
it "allows a(n) #{object.class} json object in params" do
subject.format :json
subject.send(verb) do
env['api.request.body']
end
send verb, '/', MultiJson.dump(object), { 'CONTENT_TYPE' => 'application/json' }
last_response.status.should == (verb == :post ? 201 : 200)
last_response.body.should eql MultiJson.dump(object)
end
send verb, '/', MultiJson.dump(object), {'CONTENT_TYPE' => 'application/json'}
last_response.status.should == (verb == 'post' ? 201 : 200)
last_response.body.should eql '{}'
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions spec/grape/validations/presence_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class API < Grape::API
requires :id, :regexp => /^[0-9]+$/
end
post do
{:ret => params[:id]}
{ :ret => params[:id] }
end

params do
Expand Down Expand Up @@ -60,7 +60,7 @@ def app
it 'does not validate for any params' do
get("/bacons")
last_response.status.should == 200
last_response.body.should == "All the bacon"
last_response.body.should == "All the bacon".to_json
end

it 'validates id' do
Expand Down Expand Up @@ -94,7 +94,7 @@ def app

get('/', :name => "Bob", :company => "TestCorp")
last_response.status.should == 200
last_response.body.should == "Hello"
last_response.body.should == "Hello".to_json
end

it 'validates nested parameters' do
Expand All @@ -108,7 +108,7 @@ def app

get('/nested', :user => {:first_name => "Billy", :last_name => "Bob"})
last_response.status.should == 200
last_response.body.should == "Nested"
last_response.body.should == "Nested".to_json
end

it 'validates triple nested parameters' do
Expand Down Expand Up @@ -138,7 +138,7 @@ def app

get('/nested_triple', :admin => { :admin_name => 'admin', :super => {:user => {:first_name => "Billy", :last_name => "Bob"}}})
last_response.status.should == 200
last_response.body.should == "Nested triple"
last_response.body.should == "Nested triple".to_json
end

end
8 changes: 6 additions & 2 deletions spec/shared/versioning_examples.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
shared_examples_for 'versioning' do
it 'sets the API version' do
subject.format :txt
subject.version 'v1', macro_options
subject.get :hello do
"Version: #{request.env['api.version']}"
Expand All @@ -9,7 +10,8 @@
end

it 'adds the prefix before the API version' do
subject.prefix 'api'
subject.format :txt
subject.prefix 'api'
subject.version 'v1', macro_options
subject.get :hello do
"Version: #{request.env['api.version']}"
Expand Down Expand Up @@ -58,6 +60,7 @@
context 'with different versions for the same endpoint' do
context 'without a prefix' do
it 'allows the same endpoint to be implemented' do
subject.format :txt
subject.version 'v2', macro_options
subject.get 'version' do
request.env['api.version']
Expand All @@ -79,7 +82,8 @@
end

context 'with a prefix' do
it 'allows the same endpoint to be implemented' do
it 'allows the same endpoint to be implemented' do
subject.format :txt
subject.prefix 'api'
subject.version 'v2', macro_options
subject.get 'version' do
Expand Down

0 comments on commit 6fa8f59

Please sign in to comment.