fix: add missing Content-Length to empty HTTP 201 responses

For when a preference other than return=representation is requested.
This commit is contained in:
Laurence Isla
2025-12-12 14:47:26 -05:00
committed by Steve Chavez
parent 7be638f0f2
commit 1c33d2dd38
4 changed files with 20 additions and 6 deletions
+1
View File
@@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. From versio
- Fix regression where the `PGRST103` error response was truncated by @laurenceisla in #4455 - Fix regression where the `PGRST103` error response was truncated by @laurenceisla in #4455
+ Happened when an `offset` was greater than the rows requested and `Prefer: count=exact` was sent. + Happened when an `offset` was greater than the rows requested and `Prefer: count=exact` was sent.
- Fix not returning `Content-Length` on empty HTTP `201` responses by @laurenceisla in #4518
## Fixed ## Fixed
+1 -2
View File
@@ -106,7 +106,6 @@ actionResponse (DbCrudResult MutateReadPlan{mrMutation=MutationCreate, mrMutateP
) )
, Just . RangeQuery.contentRangeH 1 0 $ , Just . RangeQuery.contentRangeH 1 0 $
if shouldCount preferCount then Just rsQueryTotal else Nothing if shouldCount preferCount then Just rsQueryTotal else Nothing
, Just $ contentLengthHeaderStrict rsBody
, prefHeader ] , prefHeader ]
isInsertIfGTZero i = isInsertIfGTZero i =
@@ -121,7 +120,7 @@ actionResponse (DbCrudResult MutateReadPlan{mrMutation=MutationCreate, mrMutateP
Just HeadersOnly -> (headers, mempty) Just HeadersOnly -> (headers, mempty)
Nothing -> (headers, mempty) Nothing -> (headers, mempty)
(ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status headers' (ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status $ contentLengthHeaderLazy bod:headers'
Right $ PgrstResponse ovStatus ovHeaders bod Right $ PgrstResponse ovStatus ovHeaders bod
+15 -3
View File
@@ -138,6 +138,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/projects?id=eq.11" , "Location" <:> "/projects?id=eq.11"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -151,6 +152,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/car_models?name=eq.Enzo&year=eq.2021" , "Location" <:> "/car_models?name=eq.Enzo&year=eq.2021"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -163,7 +165,8 @@ spec actualPgVersion = do
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, matchHeaderAbsent hLocation ] , matchHeaderAbsent hLocation
, "Content-Length" <:> "0"]
} }
context "from an html form" $ context "from an html form" $
@@ -175,7 +178,8 @@ spec actualPgVersion = do
`shouldRespondWith` `shouldRespondWith`
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType ] , matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Length" <:> "0"]
} }
context "with no pk supplied" $ do context "with no pk supplied" $ do
@@ -199,6 +203,7 @@ spec actualPgVersion = do
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Length" <:> "0"
, "Location" <:> "/auto_incrementing_pk?id=eq.2" , "Location" <:> "/auto_incrementing_pk?id=eq.2"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -741,6 +746,7 @@ spec actualPgVersion = do
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [matchHeaderAbsent hContentType , matchHeaders = [matchHeaderAbsent hContentType
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=minimal"] , "Preference-Applied" <:> "return=minimal"]
} }
@@ -753,7 +759,8 @@ spec actualPgVersion = do
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, matchHeaderAbsent hLocation ] , matchHeaderAbsent hLocation
, "Content-Length" <:> "0"]
} }
it "returns a location header with pks from both tables" $ it "returns a location header with pks from both tables" $
@@ -765,6 +772,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/with_multiple_pks?pk1=eq.1&pk2=eq.2" , "Location" <:> "/with_multiple_pks?pk1=eq.1&pk2=eq.2"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -778,6 +786,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/compound_pk_view?k1=eq.1&k2=eq.test" , "Location" <:> "/compound_pk_view?k1=eq.1&k2=eq.test"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -790,6 +799,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/test_null_pk_competitors_sponsors?id=eq.1&sponsor_id=is.null" , "Location" <:> "/test_null_pk_competitors_sponsors?id=eq.1&sponsor_id=is.null"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -807,6 +817,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/datarep_todos?id=eq.5" , "Location" <:> "/datarep_todos?id=eq.5"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
@@ -862,6 +873,7 @@ spec actualPgVersion = do
, matchHeaders = [ matchHeaderAbsent hContentType , matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/datarep_todos_computed?id=eq.5" , "Location" <:> "/datarep_todos_computed?id=eq.5"
, "Content-Range" <:> "*/*" , "Content-Range" <:> "*/*"
, "Content-Length" <:> "0"
, "Preference-Applied" <:> "return=headers-only"] , "Preference-Applied" <:> "return=headers-only"]
} }
+3 -1
View File
@@ -20,7 +20,9 @@ postItem =
`shouldRespondWith` `shouldRespondWith`
"" ""
{ matchStatus = 201 { matchStatus = 201
, matchHeaders = [matchHeaderAbsent hContentType] } , matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Length" <:> "0" ]
}
-- removes Items left over from POST, PUT, and PATCH -- removes Items left over from POST, PUT, and PATCH
deleteItems = deleteItems =