feat: Add explicit headers-only POST request using Prefer header
Allows using header "Prefer=headers-only" explicitly to get a response with only a Location header. BREAKING CHANGE: Change default for POST request from headers-only to minimal Resolves #1656
This commit is contained in:
@@ -334,11 +334,10 @@ userApiRequest confSchemas rootSpec dbStructure req reqBody
|
|||||||
split :: BS.ByteString -> [Text]
|
split :: BS.ByteString -> [Text]
|
||||||
split = map T.strip . T.split (==',') . toS
|
split = map T.strip . T.split (==',') . toS
|
||||||
representation
|
representation
|
||||||
| hasPrefer (show Full) = Full
|
| hasPrefer (show Full) = Full
|
||||||
| hasPrefer (show None) = None
|
| hasPrefer (show None) = None
|
||||||
| otherwise = if action == ActionCreate
|
| hasPrefer (show HeadersOnly) = HeadersOnly
|
||||||
then HeadersOnly -- Assume the user wants the Location header(for POST) by default
|
| otherwise = None
|
||||||
else None
|
|
||||||
auth = fromMaybe "" $ lookupHeader hAuthorization
|
auth = fromMaybe "" $ lookupHeader hAuthorization
|
||||||
tokenStr = case T.split (== ' ') (toS auth) of
|
tokenStr = case T.split (== ' ') (toS auth) of
|
||||||
("Bearer" : t : _) -> t
|
("Bearer" : t : _) -> t
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ data PreferRepresentation
|
|||||||
instance Show PreferRepresentation where
|
instance Show PreferRepresentation where
|
||||||
show Full = "return=representation"
|
show Full = "return=representation"
|
||||||
show None = "return=minimal"
|
show None = "return=minimal"
|
||||||
show HeadersOnly = mempty
|
show HeadersOnly = "return=headers-only"
|
||||||
|
|
||||||
data PreferParameters
|
data PreferParameters
|
||||||
= SingleObject -- ^ Pass all parameters as a single json object to a stored procedure
|
= SingleObject -- ^ Pass all parameters as a single json object to a stored procedure
|
||||||
|
|||||||
+32
-13
@@ -111,15 +111,23 @@ spec actualPgVersion = do
|
|||||||
, "Content-Range" <:> "*/*" ]
|
, "Content-Range" <:> "*/*" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
context "requesting no representation" $
|
context "requesting headers only representation" $
|
||||||
it "should not throw and return location header when selecting without PK" $
|
it "should not throw and return location header when selecting without PK" $
|
||||||
request methodPost "/projects?select=name,client_id" []
|
request methodPost "/projects?select=name,client_id" [("Prefer", "return=headers-only")]
|
||||||
[json|{"id":11,"name":"New Project","client_id":2}|] `shouldRespondWith` ""
|
[json|{"id":11,"name":"New Project","client_id":2}|] `shouldRespondWith` ""
|
||||||
{ matchStatus = 201
|
{ matchStatus = 201
|
||||||
, matchHeaders = [ "Location" <:> "/projects?id=eq.11"
|
, matchHeaders = [ "Location" <:> "/projects?id=eq.11"
|
||||||
, "Content-Range" <:> "*/*" ]
|
, "Content-Range" <:> "*/*" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context "requesting no representation" $
|
||||||
|
it "should not throw and return no location header when selecting without PK" $
|
||||||
|
request methodPost "/projects?select=name,client_id" []
|
||||||
|
[json|{"id":12,"name":"New Project","client_id":2}|] `shouldRespondWith` ""
|
||||||
|
{ matchStatus = 201
|
||||||
|
, matchHeaders = [ matchHeaderAbsent hLocation ]
|
||||||
|
}
|
||||||
|
|
||||||
context "from an html form" $
|
context "from an html form" $
|
||||||
it "accepts disparate json types" $ do
|
it "accepts disparate json types" $ do
|
||||||
request methodPost "/menagerie"
|
request methodPost "/menagerie"
|
||||||
@@ -140,7 +148,7 @@ spec actualPgVersion = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|""|]
|
[json|""|]
|
||||||
|
|
||||||
post "/auto_incrementing_pk"
|
request methodPost "/auto_incrementing_pk" [("Prefer", "return=headers-only")]
|
||||||
[json| { "non_nullable_string":"not null"} |]
|
[json| { "non_nullable_string":"not null"} |]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
""
|
""
|
||||||
@@ -508,13 +516,24 @@ spec actualPgVersion = do
|
|||||||
""
|
""
|
||||||
{ matchStatus = 201 }
|
{ matchStatus = 201 }
|
||||||
|
|
||||||
describe "Inserting into VIEWs" $
|
describe "Inserting into VIEWs" $ do
|
||||||
it "returns a location header" $
|
context "requesting no representation" $
|
||||||
post "/compound_pk_view"
|
it "succeeds with 201" $
|
||||||
[json|{"k1":1,"k2":"test","extra":2}|]
|
post "/compound_pk_view"
|
||||||
`shouldRespondWith`
|
[json|{"k1":1,"k2":"test","extra":2}|]
|
||||||
""
|
`shouldRespondWith`
|
||||||
{ matchStatus = 201
|
""
|
||||||
, matchHeaders = [ "Location" <:> "/compound_pk_view?k1=eq.1&k2=eq.test"
|
{ matchStatus = 201
|
||||||
, "Content-Range" <:> "*/*" ]
|
, matchHeaders = [ matchHeaderAbsent hLocation ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context "requesting header only representation" $
|
||||||
|
it "returns a location header" $
|
||||||
|
request methodPost "/compound_pk_view" [("Prefer", "return=headers-only")]
|
||||||
|
[json|{"k1":1,"k2":"test","extra":2}|]
|
||||||
|
`shouldRespondWith`
|
||||||
|
""
|
||||||
|
{ matchStatus = 201
|
||||||
|
, matchHeaders = [ "Location" <:> "/compound_pk_view?k1=eq.1&k2=eq.test"
|
||||||
|
, "Content-Range" <:> "*/*" ]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user