Provide more information in PATCH response
* 404 if no records updated * Range header for number updated * Full results depending on Prefer header Fixes #187 Fixes #182
This commit is contained in:
+18
-4
@@ -39,6 +39,8 @@ import PgQuery
|
|||||||
import RangeQuery
|
import RangeQuery
|
||||||
import PgStructure
|
import PgStructure
|
||||||
|
|
||||||
|
import Debug.Trace
|
||||||
|
|
||||||
app :: Text -> BL.ByteString -> Request -> H.Tx P.Postgres s Response
|
app :: Text -> BL.ByteString -> Request -> H.Tx P.Postgres s Response
|
||||||
app v1schema reqBody req =
|
app v1schema reqBody req =
|
||||||
case (path, verb) of
|
case (path, verb) of
|
||||||
@@ -164,10 +166,22 @@ app v1schema reqBody req =
|
|||||||
([table], "PATCH") ->
|
([table], "PATCH") ->
|
||||||
handleJsonObj reqBody $ \obj -> do
|
handleJsonObj reqBody $ \obj -> do
|
||||||
let qt = QualifiedTable schema (cs table)
|
let qt = QualifiedTable schema (cs table)
|
||||||
H.unitEx
|
up = returningStarT
|
||||||
$ whereT qq
|
. whereT qq
|
||||||
$ update qt (map cs $ M.keys obj) (M.elems obj)
|
$ update qt (map cs $ M.keys obj) (M.elems obj)
|
||||||
return $ responseLBS status204 [ jsonH ] ""
|
patch = withT up "t" $ B.Stmt
|
||||||
|
"select count(t), array_to_json(array_agg(row_to_json(t)))::character varying"
|
||||||
|
V.empty True
|
||||||
|
|
||||||
|
row <- H.maybeEx $ traceShow (B.stmtTemplate patch) patch
|
||||||
|
let (queryTotal, body) =
|
||||||
|
fromMaybe (0 :: Int, Just "" :: Maybe Text) row
|
||||||
|
r = contentRangeH 0 (queryTotal-1) queryTotal
|
||||||
|
echoRequested = lookup "Prefer" hdrs == Just "return=representation"
|
||||||
|
s = case () of _ | queryTotal == 0 -> status404
|
||||||
|
| echoRequested -> status200
|
||||||
|
| otherwise -> status204
|
||||||
|
return $ responseLBS s [ jsonH, r ] $ if echoRequested then cs $ fromMaybe "[]" body else ""
|
||||||
|
|
||||||
([table], "DELETE") -> do
|
([table], "DELETE") -> do
|
||||||
let qt = QualifiedTable schema (cs table)
|
let qt = QualifiedTable schema (cs table)
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ whereT params q =
|
|||||||
cols = [ col | col <- params, fst col `notElem` ["order"] ]
|
cols = [ col | col <- params, fst col `notElem` ["order"] ]
|
||||||
conjunction = mconcat $ L.intersperse andq (map wherePred cols)
|
conjunction = mconcat $ L.intersperse andq (map wherePred cols)
|
||||||
|
|
||||||
|
withT :: PStmt -> T.Text -> StatementT
|
||||||
|
withT (B.Stmt eq ep epre) v (B.Stmt wq wp wpre) =
|
||||||
|
B.Stmt ("WITH " <> v <> " AS (" <> eq <> ") " <> wq <> " from " <> v)
|
||||||
|
(ep <> wp)
|
||||||
|
(epre && wpre)
|
||||||
|
|
||||||
orderT :: [OrderTerm] -> StatementT
|
orderT :: [OrderTerm] -> StatementT
|
||||||
orderT ts q =
|
orderT ts q =
|
||||||
if L.null ts
|
if L.null ts
|
||||||
|
|||||||
@@ -232,10 +232,10 @@ spec = afterAll_ resetDb $ around withApp $ do
|
|||||||
`shouldRespondWith` 404
|
`shouldRespondWith` 404
|
||||||
|
|
||||||
context "on an empty table" $
|
context "on an empty table" $
|
||||||
it "succeeds with no effect" $
|
it "indicates no records found to update" $
|
||||||
request methodPatch "/simple_pk" []
|
request methodPatch "/simple_pk" []
|
||||||
[json| { "extra":20 } |]
|
[json| { "extra":20 } |]
|
||||||
`shouldRespondWith` 204
|
`shouldRespondWith` 404
|
||||||
|
|
||||||
context "in a nonempty table" . before_ (clearTable "items" >> createItems 15) .
|
context "in a nonempty table" . before_ (clearTable "items" >> createItems 15) .
|
||||||
after_ (clearTable "items") $ do
|
after_ (clearTable "items") $ do
|
||||||
@@ -245,7 +245,11 @@ spec = afterAll_ resetDb $ around withApp $ do
|
|||||||
`shouldSatisfy` matchHeader "Content-Range" "\\*/0"
|
`shouldSatisfy` matchHeader "Content-Range" "\\*/0"
|
||||||
request methodPatch "/items?id=eq.1" []
|
request methodPatch "/items?id=eq.1" []
|
||||||
[json| { "id":42 } |]
|
[json| { "id":42 } |]
|
||||||
`shouldRespondWith` 204
|
`shouldRespondWith` ResponseMatcher {
|
||||||
|
matchBody = Nothing,
|
||||||
|
matchStatus = 204,
|
||||||
|
matchHeaders = ["Content-Range" <:> "0-0/1"]
|
||||||
|
}
|
||||||
g' <- get "/items?id=eq.42"
|
g' <- get "/items?id=eq.42"
|
||||||
liftIO $ simpleHeaders g'
|
liftIO $ simpleHeaders g'
|
||||||
`shouldSatisfy` matchHeader "Content-Range" "0-0/1"
|
`shouldSatisfy` matchHeader "Content-Range" "0-0/1"
|
||||||
@@ -261,3 +265,12 @@ spec = afterAll_ resetDb $ around withApp $ do
|
|||||||
g <- get "/auto_incrementing_pk?non_nullable_string=eq.c"
|
g <- get "/auto_incrementing_pk?non_nullable_string=eq.c"
|
||||||
liftIO $ simpleHeaders g
|
liftIO $ simpleHeaders g
|
||||||
`shouldSatisfy` matchHeader "Content-Range" "0-9/10"
|
`shouldSatisfy` matchHeader "Content-Range" "0-9/10"
|
||||||
|
|
||||||
|
it "can provide a representation" $ do
|
||||||
|
_ <- post "/items"
|
||||||
|
[json| { id: 1 } |]
|
||||||
|
request methodPatch
|
||||||
|
"/items?id=eq.1"
|
||||||
|
[("Prefer", "return=representation")]
|
||||||
|
[json| { id: 99 } |]
|
||||||
|
`shouldRespondWith` [json| [{id:99}] |]
|
||||||
|
|||||||
Reference in New Issue
Block a user