refactor: move ApiRequestError to Error module

This commit is contained in:
Taimoor Zaeem
2025-02-13 09:38:18 -05:00
committed by Steve Chavez
parent 33b69b5894
commit e04cd70d83
7 changed files with 67 additions and 75 deletions
+2 -2
View File
@@ -44,10 +44,10 @@ import Network.Wai.Parse (parseHttpAccept)
import Web.Cookie (parseCookies) import Web.Cookie (parseCookies)
import PostgREST.ApiRequest.QueryParams (QueryParams (..)) import PostgREST.ApiRequest.QueryParams (QueryParams (..))
import PostgREST.ApiRequest.Types (ApiRequestError (..),
RangeError (..))
import PostgREST.Config (AppConfig (..), import PostgREST.Config (AppConfig (..),
OpenAPIMode (..)) OpenAPIMode (..))
import PostgREST.Error (ApiRequestError (..),
RangeError (..))
import PostgREST.MediaType (MediaType (..)) import PostgREST.MediaType (MediaType (..))
import PostgREST.RangeQuery (NonnegRange, allRange, import PostgREST.RangeQuery (NonnegRange, allRange,
convertToLimitZeroRange, convertToLimitZeroRange,
+3 -1
View File
@@ -54,10 +54,12 @@ import PostgREST.ApiRequest.Types (AggregateFunction (..),
OpQuantifier (..), Operation (..), OpQuantifier (..), Operation (..),
OrderDirection (..), OrderDirection (..),
OrderNulls (..), OrderTerm (..), OrderNulls (..), OrderTerm (..),
QPError (..), QuantOperator (..), QuantOperator (..),
SelectItem (..), SelectItem (..),
SimpleOperator (..), SingleVal) SimpleOperator (..), SingleVal)
import PostgREST.Error (QPError (..))
import Protolude hiding (Sum, try) import Protolude hiding (Sum, try)
data QueryParams = data QueryParams =
+1 -53
View File
@@ -5,7 +5,6 @@ module PostgREST.ApiRequest.Types
, Cast , Cast
, Depth , Depth
, EmbedParam(..) , EmbedParam(..)
, ApiRequestError(..)
, EmbedPath , EmbedPath
, Field , Field
, Filter(..) , Filter(..)
@@ -25,9 +24,6 @@ module PostgREST.ApiRequest.Types
, OrderDirection(..) , OrderDirection(..)
, OrderNulls(..) , OrderNulls(..)
, OrderTerm(..) , OrderTerm(..)
, QPError(..)
, RaiseError(..)
, RangeError(..)
, SingleVal , SingleVal
, IsVal(..) , IsVal(..)
, SimpleOperator(..) , SimpleOperator(..)
@@ -36,12 +32,7 @@ module PostgREST.ApiRequest.Types
, SelectItem(..) , SelectItem(..)
) where ) where
import PostgREST.MediaType (MediaType (..)) import PostgREST.SchemaCache.Identifiers (FieldName)
import PostgREST.SchemaCache.Identifiers (FieldName,
QualifiedIdentifier)
import PostgREST.SchemaCache.Relationship (Relationship,
RelationshipsMap)
import PostgREST.SchemaCache.Routine (Routine (..))
import Protolude import Protolude
@@ -69,49 +60,6 @@ data SelectItem
} }
deriving (Eq, Show) deriving (Eq, Show)
data ApiRequestError
= AggregatesNotAllowed
| AmbiguousRelBetween Text Text [Relationship]
| AmbiguousRpc [Routine]
| MediaTypeError [ByteString]
| InvalidBody ByteString
| InvalidFilters
| InvalidPreferences [ByteString]
| InvalidRange RangeError
| InvalidRpcMethod ByteString
| NotFound
| NoRelBetween Text Text (Maybe Text) Text RelationshipsMap
| NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine]
| NotEmbedded Text
| PutLimitNotAllowedError
| QueryParamError QPError
| RelatedOrderNotToOne Text Text
| SpreadNotToOne Text Text
| UnacceptableFilter Text
| UnacceptableSchema [Text]
| UnsupportedMethod ByteString
| ColumnNotFound Text Text
| GucHeadersError
| GucStatusError
| PutMatchingPkError
| SingularityError Integer
| PGRSTParseError RaiseError
| MaxAffectedViolationError Integer
deriving Show
data QPError = QPError Text Text
deriving Show
data RaiseError
= MsgParseError ByteString
| DetParseError ByteString
| NoDetail
deriving Show
data RangeError
= NegativeLimit
| LowerGTUpper
| OutOfBounds Text Text
deriving Show
type NodeName = Text type NodeName = Text
type Depth = Integer type Depth = Integer
+49 -6
View File
@@ -8,6 +8,8 @@ Description : PostgREST error HTTP responses
module PostgREST.Error module PostgREST.Error
( errorResponseFor ( errorResponseFor
, ApiRequestError(..) , ApiRequestError(..)
, QPError(..)
, RangeError(..)
, PgError(..) , PgError(..)
, Error(..) , Error(..)
, errorPayload , errorPayload
@@ -32,12 +34,8 @@ import Network.Wai (Response, responseLBS)
import Network.HTTP.Types.Header (Header) import Network.HTTP.Types.Header (Header)
import PostgREST.ApiRequest.Types (ApiRequestError (..), import PostgREST.MediaType (MediaType (..))
QPError (..), import qualified PostgREST.MediaType as MediaType
RaiseError (..),
RangeError (..))
import PostgREST.MediaType (MediaType (..))
import qualified PostgREST.MediaType as MediaType
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..), import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
Schema) Schema)
@@ -62,6 +60,51 @@ class (JSON.ToJSON a) => PgrstError a where
let baseHeader = MediaType.toContentType MTApplicationJSON in let baseHeader = MediaType.toContentType MTApplicationJSON in
responseLBS (status err) (baseHeader : headers err) $ errorPayload err responseLBS (status err) (baseHeader : headers err) $ errorPayload err
data ApiRequestError
= AggregatesNotAllowed
| AmbiguousRelBetween Text Text [Relationship]
| AmbiguousRpc [Routine]
| MediaTypeError [ByteString]
| InvalidBody ByteString
| InvalidFilters
| InvalidPreferences [ByteString]
| InvalidRange RangeError
| InvalidRpcMethod ByteString
| NotFound
| NoRelBetween Text Text (Maybe Text) Text RelationshipsMap
| NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine]
| NotEmbedded Text
| PutLimitNotAllowedError
| QueryParamError QPError
| RelatedOrderNotToOne Text Text
| SpreadNotToOne Text Text
| UnacceptableFilter Text
| UnacceptableSchema [Text]
| UnsupportedMethod ByteString
| ColumnNotFound Text Text
| GucHeadersError
| GucStatusError
| PutMatchingPkError
| SingularityError Integer
| PGRSTParseError RaiseError
| MaxAffectedViolationError Integer
deriving Show
data QPError = QPError Text Text
deriving Show
data RaiseError
= MsgParseError ByteString
| DetParseError ByteString
| NoDetail
deriving Show
data RangeError
= NegativeLimit
| LowerGTUpper
| OutOfBounds Text Text
deriving Show
instance PgrstError ApiRequestError where instance PgrstError ApiRequestError where
status AggregatesNotAllowed{} = HTTP.status400 status AggregatesNotAllowed{} = HTTP.status400
status AmbiguousRelBetween{} = HTTP.status300 status AmbiguousRelBetween{} = HTTP.status300
+2 -1
View File
@@ -42,7 +42,8 @@ import PostgREST.ApiRequest (Action (..),
Mutation (..), Mutation (..),
Payload (..)) Payload (..))
import PostgREST.Config (AppConfig (..)) import PostgREST.Config (AppConfig (..))
import PostgREST.Error (Error (..)) import PostgREST.Error (ApiRequestError (..),
Error (..))
import PostgREST.MediaType (MediaType (..)) import PostgREST.MediaType (MediaType (..))
import PostgREST.Query.SqlFragment (sourceCTEName) import PostgREST.Query.SqlFragment (sourceCTEName)
import PostgREST.RangeQuery (NonnegRange, allRange, import PostgREST.RangeQuery (NonnegRange, allRange,
+3 -4
View File
@@ -20,7 +20,6 @@ import qualified Hasql.DynamicStatements.Statement as SQL
import qualified Hasql.Transaction as SQL import qualified Hasql.Transaction as SQL
import qualified Hasql.Transaction.Sessions as SQL import qualified Hasql.Transaction.Sessions as SQL
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
import qualified PostgREST.AppState as AppState import qualified PostgREST.AppState as AppState
import qualified PostgREST.Error as Error import qualified PostgREST.Error as Error
import qualified PostgREST.Query.QueryBuilder as QueryBuilder import qualified PostgREST.Query.QueryBuilder as QueryBuilder
@@ -217,7 +216,7 @@ failPut RSPlan{} = pure ()
failPut RSStandard{rsQueryTotal=queryTotal} = failPut RSStandard{rsQueryTotal=queryTotal} =
when (queryTotal /= 1) $ do when (queryTotal /= 1) $ do
lift SQL.condemn lift SQL.condemn
throwError $ Error.ApiRequestError ApiRequestTypes.PutMatchingPkError throwError $ Error.ApiRequestError Error.PutMatchingPkError
resultSetWTotal :: AppConfig -> ApiRequest -> ResultSet -> SQL.Snippet -> DbHandler ResultSet resultSetWTotal :: AppConfig -> ApiRequest -> ResultSet -> SQL.Snippet -> DbHandler ResultSet
resultSetWTotal _ _ rs@RSPlan{} _ = return rs resultSetWTotal _ _ rs@RSPlan{} _ = return rs
@@ -249,14 +248,14 @@ failNotSingular _ RSPlan{} = pure ()
failNotSingular mediaType RSStandard{rsQueryTotal=queryTotal} = failNotSingular mediaType RSStandard{rsQueryTotal=queryTotal} =
when (elem mediaType [MTVndSingularJSON True, MTVndSingularJSON False] && queryTotal /= 1) $ do when (elem mediaType [MTVndSingularJSON True, MTVndSingularJSON False] && queryTotal /= 1) $ do
lift SQL.condemn lift SQL.condemn
throwError $ Error.ApiRequestError . ApiRequestTypes.SingularityError $ toInteger queryTotal throwError $ Error.ApiRequestError . Error.SingularityError $ toInteger queryTotal
failExceedsMaxAffectedPref :: (Maybe PreferMaxAffected, Maybe PreferHandling) -> ResultSet -> DbHandler () failExceedsMaxAffectedPref :: (Maybe PreferMaxAffected, Maybe PreferHandling) -> ResultSet -> DbHandler ()
failExceedsMaxAffectedPref (Nothing,_) _ = pure () failExceedsMaxAffectedPref (Nothing,_) _ = pure ()
failExceedsMaxAffectedPref _ RSPlan{} = pure () failExceedsMaxAffectedPref _ RSPlan{} = pure ()
failExceedsMaxAffectedPref (Just (PreferMaxAffected n), handling) RSStandard{rsQueryTotal=queryTotal} = when ((queryTotal > n) && (handling == Just Strict)) $ do failExceedsMaxAffectedPref (Just (PreferMaxAffected n), handling) RSStandard{rsQueryTotal=queryTotal} = when ((queryTotal > n) && (handling == Just Strict)) $ do
lift SQL.condemn lift SQL.condemn
throwError $ Error.ApiRequestError . ApiRequestTypes.MaxAffectedViolationError $ toInteger queryTotal throwError $ Error.ApiRequestError . Error.MaxAffectedViolationError $ toInteger queryTotal
-- | Set a transaction to roll back if requested -- | Set a transaction to roll back if requested
optionalRollback :: AppConfig -> ApiRequest -> DbHandler () optionalRollback :: AppConfig -> ApiRequest -> DbHandler ()
+7 -8
View File
@@ -50,7 +50,6 @@ import PostgREST.SchemaCache.Routine (FuncVolatility (..),
Routine (..)) Routine (..))
import PostgREST.SchemaCache.Table (Table (..)) import PostgREST.SchemaCache.Table (Table (..))
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
import qualified PostgREST.SchemaCache.Routine as Routine import qualified PostgREST.SchemaCache.Routine as Routine
import Protolude hiding (Handler, toS) import Protolude hiding (Handler, toS)
@@ -83,8 +82,8 @@ actionResponse (DbCrudResult WrappedReadPlan{wrMedia, wrHdrsOnly=headersOnly, cr
(ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status headers (ovStatus, ovHeaders) <- overrideStatusHeaders rsGucStatus rsGucHeaders status headers
let bod | status == HTTP.status416 = Error.errorPayload $ Error.ApiRequestError $ ApiRequestTypes.InvalidRange $ let bod | status == HTTP.status416 = Error.errorPayload $ Error.ApiRequestError $ Error.InvalidRange $
ApiRequestTypes.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal) Error.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
| headersOnly = mempty | headersOnly = mempty
| otherwise = LBS.fromStrict rsBody | otherwise = LBS.fromStrict rsBody
@@ -203,8 +202,8 @@ actionResponse (DbCallResult CallReadPlan{crMedia, crInvMthd=invMethod, crProc=p
(status, contentRange) = (status, contentRange) =
RangeQuery.rangeStatusHeader iTopLevelRange rsQueryTotal rsTableTotal RangeQuery.rangeStatusHeader iTopLevelRange rsQueryTotal rsTableTotal
rsOrErrBody = if status == HTTP.status416 rsOrErrBody = if status == HTTP.status416
then Error.errorPayload $ Error.ApiRequestError $ ApiRequestTypes.InvalidRange then Error.errorPayload $ Error.ApiRequestError $ Error.InvalidRange
$ ApiRequestTypes.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal) $ Error.OutOfBounds (show $ RangeQuery.rangeOffset iTopLevelRange) (maybe "0" show rsTableTotal)
else LBS.fromStrict rsBody else LBS.fromStrict rsBody
prefHeader = maybeToList . prefAppliedHeader $ Preferences Nothing Nothing preferCount preferTransaction Nothing preferHandling preferTimezone preferMaxAffected [] prefHeader = maybeToList . prefAppliedHeader $ Preferences Nothing Nothing preferCount preferTransaction Nothing preferHandling preferTimezone preferMaxAffected []
headers = contentRange : prefHeader headers = contentRange : prefHeader
@@ -232,7 +231,7 @@ actionResponse (MaybeDbResult InspectPlan{ipHdrsOnly=headersOnly} body) _ versio
actionResponse (NoDbResult (RelInfoPlan identifier)) _ _ _ sCache _ _ = actionResponse (NoDbResult (RelInfoPlan identifier)) _ _ _ sCache _ _ =
case HM.lookup identifier (dbTables sCache) of case HM.lookup identifier (dbTables sCache) of
Just tbl -> respondInfo $ allowH tbl Just tbl -> respondInfo $ allowH tbl
Nothing -> Left $ Error.ApiRequestError ApiRequestTypes.NotFound Nothing -> Left $ Error.ApiRequestError Error.NotFound
where where
allowH table = allowH table =
let hasPK = not . null $ tablePKCols table in let hasPK = not . null $ tablePKCols table in
@@ -263,11 +262,11 @@ overrideStatusHeaders rsGucStatus rsGucHeaders pgrstStatus pgrstHeaders = do
decodeGucHeaders :: Maybe BS.ByteString -> Either Error.Error [GucHeader] decodeGucHeaders :: Maybe BS.ByteString -> Either Error.Error [GucHeader]
decodeGucHeaders = decodeGucHeaders =
maybe (Right []) $ first (const . Error.ApiRequestError $ ApiRequestTypes.GucHeadersError) . JSON.eitherDecode . LBS.fromStrict maybe (Right []) $ first (const . Error.ApiRequestError $ Error.GucHeadersError) . JSON.eitherDecode . LBS.fromStrict
decodeGucStatus :: Maybe Text -> Either Error.Error (Maybe HTTP.Status) decodeGucStatus :: Maybe Text -> Either Error.Error (Maybe HTTP.Status)
decodeGucStatus = decodeGucStatus =
maybe (Right Nothing) $ first (const . Error.ApiRequestError $ ApiRequestTypes.GucStatusError) . fmap (Just . toEnum . fst) . decimal maybe (Right Nothing) $ first (const . Error.ApiRequestError $ Error.GucStatusError) . fmap (Just . toEnum . fst) . decimal
contentTypeHeaders :: MediaType -> ApiRequest -> [HTTP.Header] contentTypeHeaders :: MediaType -> ApiRequest -> [HTTP.Header]
contentTypeHeaders mediaType ApiRequest{..} = contentTypeHeaders mediaType ApiRequest{..} =