diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dab99015..4bd2281a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #827, Avoid Warp reaper, extend socket timeout to 1 hour - @majorcode - #791, malformed nested JSON error - @diogob - Resource embedding in views referencing tables in public schema - @fab1an +- #777, Empty body is allowed when calling a non-parameterized RPC - @koulakis - #831, Fix proc resource embedding issue with search_path - @steve-chavez ## [0.4.0.0] - 2017-01-19 diff --git a/src/PostgREST/ApiRequest.hs b/src/PostgREST/ApiRequest.hs index 857d718e9..1bbd69d99 100644 --- a/src/PostgREST/ApiRequest.hs +++ b/src/PostgREST/ApiRequest.hs @@ -13,6 +13,7 @@ module PostgREST.ApiRequest ( ApiRequest(..) import Protolude import qualified Data.Aeson as JSON +import Data.Aeson.Types (emptyObject) import qualified Data.ByteString as BS import qualified Data.ByteString.Internal as BS (c2w) import qualified Data.ByteString.Lazy as BL @@ -124,13 +125,13 @@ userApiRequest schema req reqBody payload = case decodeContentType . fromMaybe "application/json" $ lookupHeader "content-type" of CTApplicationJSON -> - either Left (\val -> case ensureUniform (pluralize val) of - Nothing -> Left "All object keys must match" - Just json -> Right json) (JSON.eitherDecode reqBody) + note "All object keys must match" . ensureUniform . pluralize + =<< if BL.null reqBody && isTargetingProc + then Right emptyObject + else JSON.eitherDecode reqBody CTTextCSV -> - either Left (\val -> case ensureUniform (csvToJson val) of - Nothing -> Left "All lines must have same number of fields" - Just json -> Right json) (CSV.decodeByName reqBody) + note "All lines must have same number of fields" . ensureUniform . csvToJson + =<< CSV.decodeByName reqBody CTOther "application/x-www-form-urlencoded" -> Right . PayloadJSON . V.singleton . M.fromList . map (toS *** JSON.String . toS) . parseSimpleQuery diff --git a/test/Feature/QuerySpec.hs b/test/Feature/QuerySpec.hs index f1fe446d2..5c2ca30c9 100644 --- a/test/Feature/QuerySpec.hs +++ b/test/Feature/QuerySpec.hs @@ -5,6 +5,7 @@ import Test.Hspec.Wai import Test.Hspec.Wai.JSON import Network.HTTP.Types import Network.Wai.Test (SResponse(simpleHeaders,simpleStatus,simpleBody)) +import qualified Data.ByteString.Lazy as BL (empty) import SpecHelper import Text.Heredoc @@ -481,7 +482,6 @@ spec = do , matchHeaders = ["Content-Range" <:> "0-0/2"] } - it "returns proper json" $ post "/rpc/getitemrange" [json| { "min": 2, "max": 4 } |] `shouldRespondWith` [json| [ {"id": 3}, {"id":4} ] |] @@ -640,6 +640,12 @@ spec = do , "boolean":"false", "date":"1900-01-01", "money":"$3.99", "enum":"foo" } |] { matchHeaders = [matchContentTypeJson] } + context "a proc that receives no parameters" $ + it "interprets empty string as empty json object on a post request" $ + post "/rpc/noparamsproc" BL.empty `shouldRespondWith` + [json| "Return value of no parameters procedure." |] + { matchHeaders = [matchContentTypeJson] } + describe "weird requests" $ do it "can query as normal" $ do get "/Escap3e;" `shouldRespondWith` diff --git a/test/fixtures/schema.sql b/test/fixtures/schema.sql index b06b68fe8..1a19b45d4 100755 --- a/test/fixtures/schema.sql +++ b/test/fixtures/schema.sql @@ -173,6 +173,15 @@ CREATE FUNCTION getitemrange(min bigint, max bigint) RETURNS SETOF items SELECT * FROM test.items WHERE id > $1 AND id <= $2; $_$; +-- +-- Name: version(); Type: FUNCTION; Schema: test; Owner: - +-- + +CREATE FUNCTION noparamsproc() RETURNS text + LANGUAGE sql + AS $$ + SELECT a FROM (VALUES ('Return value of no parameters procedure.')) s(a); + $$; -- -- Name: insert_insertable_view_with_join(); Type: FUNCTION; Schema: test; Owner: -