From acf2003487c951b017d6a0805ccd3574ee98d3e3 Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Sat, 6 Oct 2012 18:44:21 +0200 Subject: [PATCH] Handle invalid JSON on PUT requests --- lib/remote_storage/riak.rb | 24 +++++++++++++++++++----- spec/riak_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/remote_storage/riak.rb b/lib/remote_storage/riak.rb index 5350ffa..4148e8e 100644 --- a/lib/remote_storage/riak.rb +++ b/lib/remote_storage/riak.rb @@ -63,12 +63,11 @@ module RemoteStorage def put_data(user, directory, key, data, content_type=nil) object = data_bucket.new("#{user}:#{directory}:#{key}") object.content_type = content_type || "text/plain; charset=utf-8" - data = JSON.parse(data) if content_type[/^[^;\s]+/] == "application/json" - if serializer_for(object.content_type) - object.data = data - else - object.raw_data = data + + unless set_object_data(object, data) + halt 422 end + directory_index = directory == "" ? "/" : directory object.indexes.merge!({:user_id_bin => [user], :directory_bin => [directory_index]}) @@ -206,5 +205,20 @@ module RemoteStorage directory_object.store end + def set_object_data(object, data) + if object.content_type[/^[^;\s]+/] == "application/json" + data = "{}" if data.blank? + data = JSON.parse(data) + end + + if serializer_for(object.content_type) + object.data = data + else + object.raw_data = data + end + rescue JSON::ParserError + return false + end + end end diff --git a/spec/riak_spec.rb b/spec/riak_spec.rb index 7209cc8..a2d6ccb 100644 --- a/spec/riak_spec.rb +++ b/spec/riak_spec.rb @@ -173,6 +173,32 @@ describe "App with Riak backend" do last_response.content_type.must_equal "application/json; charset=UTF-8" end end + + context "invalid JSON" do + context "empty body" do + before do + header "Content-Type", "application/json" + put "/jimmy/documents/jason", "" + end + + it "saves an empty JSON object" do + last_response.status.must_equal 200 + data_bucket.get("jimmy:documents:jason").data.must_be_kind_of Hash + data_bucket.get("jimmy:documents:jason").data.must_equal({}) + end + end + + context "unparsable JSON" do + before do + header "Content-Type", "application/json" + put "/jimmy/documents/jason", "foo" + end + + it "returns a 422" do + last_response.status.must_equal 422 + end + end + end end describe "DELETE" do