break: db-root-spec default app/openapi+json media

BREAKING CHANGE

Can be done later with custom media types
This commit is contained in:
steve-chavez
2023-10-26 09:04:02 -05:00
committed by Steve Chavez
parent 14d030b96c
commit 4a90e9fbd9
4 changed files with 14 additions and 19 deletions
+1
View File
@@ -92,6 +92,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
+ Can be replaced with custom media types + Can be replaced with custom media types
- #1462, #1548, Removed `application/octet-stream`, `text/plain`, `text/xml` [builtin support for scalar results](https://postgrest.org/en/v11.1/references/api/resource_representation.html#scalar-function-response-format) - @steve-chavez - #1462, #1548, Removed `application/octet-stream`, `text/plain`, `text/xml` [builtin support for scalar results](https://postgrest.org/en/v11.1/references/api/resource_representation.html#scalar-function-response-format) - @steve-chavez
+ Can be replaced with custom media types + Can be replaced with custom media types
- #1462, #1548, Removed default `application/openapi+json` media type for [db-root-spec](https://postgrest.org/en/v11.1/references/configuration.html#db-root-spec) - @steve-chavez
## [11.1.0] - 2023-06-07 ## [11.1.0] - 2023-06-07
-3
View File
@@ -15,7 +15,6 @@ module PostgREST.ApiRequest
, Action(..) , Action(..)
, Target(..) , Target(..)
, Payload(..) , Payload(..)
, PathInfo(..)
, userApiRequest , userApiRequest
) where ) where
@@ -127,7 +126,6 @@ data ApiRequest = ApiRequest {
, iHeaders :: [(ByteString, ByteString)] -- ^ HTTP request headers , iHeaders :: [(ByteString, ByteString)] -- ^ HTTP request headers
, iCookies :: [(ByteString, ByteString)] -- ^ Request Cookies , iCookies :: [(ByteString, ByteString)] -- ^ Request Cookies
, iPath :: ByteString -- ^ Raw request path , iPath :: ByteString -- ^ Raw request path
, iPathInfo :: PathInfo -- ^ Cached info about the path
, iMethod :: ByteString -- ^ Raw request method , iMethod :: ByteString -- ^ Raw request method
, iSchema :: Schema -- ^ The request schema. Can vary depending on profile headers. , iSchema :: Schema -- ^ The request schema. Can vary depending on profile headers.
, iNegotiatedByProfile :: Bool -- ^ If schema was was chosen according to the profile spec https://www.w3.org/TR/dx-prof-conneg/ , iNegotiatedByProfile :: Bool -- ^ If schema was was chosen according to the profile spec https://www.w3.org/TR/dx-prof-conneg/
@@ -158,7 +156,6 @@ userApiRequest conf req reqBody = do
, iHeaders = iHdrs , iHeaders = iHdrs
, iCookies = iCkies , iCookies = iCkies
, iPath = rawPathInfo req , iPath = rawPathInfo req
, iPathInfo = pInfo
, iMethod = method , iMethod = method
, iSchema = schema , iSchema = schema
, iNegotiatedByProfile = negotiatedByProfile , iNegotiatedByProfile = negotiatedByProfile
+10 -14
View File
@@ -41,7 +41,6 @@ import PostgREST.ApiRequest (Action (..),
ApiRequest (..), ApiRequest (..),
InvokeMethod (..), InvokeMethod (..),
Mutation (..), Mutation (..),
PathInfo (..),
Payload (..)) Payload (..))
import PostgREST.Config (AppConfig (..)) import PostgREST.Config (AppConfig (..))
import PostgREST.Error (Error (..)) import PostgREST.Error (Error (..))
@@ -123,7 +122,7 @@ data InspectPlan = InspectPlan {
wrappedReadPlan :: QualifiedIdentifier -> AppConfig -> SchemaCache -> ApiRequest -> Either Error WrappedReadPlan wrappedReadPlan :: QualifiedIdentifier -> AppConfig -> SchemaCache -> ApiRequest -> Either Error WrappedReadPlan
wrappedReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferences{..},..} = do wrappedReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferences{..},..} = do
rPlan <- readPlan identifier conf sCache apiRequest rPlan <- readPlan identifier conf sCache apiRequest
mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iPathInfo iAcceptMediaType mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iAcceptMediaType
if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right () if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right ()
return $ WrappedReadPlan rPlan SQL.Read (mediaToAggregate mediaType apiRequest) mediaType return $ WrappedReadPlan rPlan SQL.Read (mediaToAggregate mediaType apiRequest) mediaType
@@ -131,7 +130,7 @@ mutateReadPlan :: Mutation -> ApiRequest -> QualifiedIdentifier -> AppConfig ->
mutateReadPlan mutation apiRequest@ApiRequest{iPreferences=Preferences{..},..} identifier conf sCache = do mutateReadPlan mutation apiRequest@ApiRequest{iPreferences=Preferences{..},..} identifier conf sCache = do
rPlan <- readPlan identifier conf sCache apiRequest rPlan <- readPlan identifier conf sCache apiRequest
mPlan <- mutatePlan mutation identifier apiRequest sCache rPlan mPlan <- mutatePlan mutation identifier apiRequest sCache rPlan
mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iPathInfo iAcceptMediaType mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iAcceptMediaType
if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right () if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right ()
return $ MutateReadPlan rPlan mPlan SQL.Write (mediaToAggregate mediaType apiRequest) mediaType return $ MutateReadPlan rPlan mPlan SQL.Write (mediaToAggregate mediaType apiRequest) mediaType
@@ -157,7 +156,7 @@ callReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferenc
(InvPost, Routine.Immutable) -> SQL.Read (InvPost, Routine.Immutable) -> SQL.Read
(InvPost, Routine.Volatile) -> SQL.Write (InvPost, Routine.Volatile) -> SQL.Write
cPlan = callPlan proc apiRequest paramKeys args rPlan cPlan = callPlan proc apiRequest paramKeys args rPlan
mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iPathInfo iAcceptMediaType mediaType <- mapLeft ApiRequestError $ negotiateContent conf iAction iAcceptMediaType
if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right () if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestError $ InvalidPreferences invalidPrefs else Right ()
return $ CallReadPlan rPlan cPlan txMode proc (mediaToAggregate mediaType apiRequest) mediaType return $ CallReadPlan rPlan cPlan txMode proc (mediaToAggregate mediaType apiRequest) mediaType
where where
@@ -165,7 +164,7 @@ callReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferenc
inspectPlan :: AppConfig -> ApiRequest -> Either Error InspectPlan inspectPlan :: AppConfig -> ApiRequest -> Either Error InspectPlan
inspectPlan conf apiRequest = do inspectPlan conf apiRequest = do
mediaType <- mapLeft ApiRequestError $ negotiateContent conf (iAction apiRequest) (iPathInfo apiRequest) (iAcceptMediaType apiRequest) mediaType <- mapLeft ApiRequestError $ negotiateContent conf (iAction apiRequest) (iAcceptMediaType apiRequest)
return $ InspectPlan mediaType SQL.Read return $ InspectPlan mediaType SQL.Read
{-| {-|
@@ -851,29 +850,26 @@ mediaToAggregate mt apiReq@ApiRequest{iAction=act, iPreferences=Preferences{pref
_ -> False _ -> False
-- | Do content negotiation. i.e. choose a media type based on the intersection of accepted/produced media types. -- | Do content negotiation. i.e. choose a media type based on the intersection of accepted/produced media types.
negotiateContent :: AppConfig -> Action -> PathInfo -> [MediaType] -> Either ApiRequestError MediaType negotiateContent :: AppConfig -> Action -> [MediaType] -> Either ApiRequestError MediaType
negotiateContent conf action path accepts = negotiateContent conf action accepts =
case firstAcceptedPick of case firstAcceptedPick of
Just MTAny -> Right MTApplicationJSON -- by default(for */*) we respond with json Just MTAny -> Right MTApplicationJSON -- by default(for */*) we respond with json
Just mt -> Right mt Just mt -> Right mt
Nothing -> Left . MediaTypeError $ map MediaType.toMime accepts Nothing -> Left . MediaTypeError $ map MediaType.toMime accepts
where where
-- if there are multiple accepted media types, pick the first -- if there are multiple accepted media types, pick the first
firstAcceptedPick = listToMaybe $ L.intersect accepts $ producedMediaTypes conf action path firstAcceptedPick = listToMaybe $ L.intersect accepts $ producedMediaTypes conf action
producedMediaTypes :: AppConfig -> Action -> PathInfo -> [MediaType] producedMediaTypes :: AppConfig -> Action -> [MediaType]
producedMediaTypes conf action path = producedMediaTypes conf action =
case action of case action of
ActionRead _ -> defaultMediaTypes ActionRead _ -> defaultMediaTypes
ActionInvoke _ -> invokeMediaTypes ActionInvoke _ -> defaultMediaTypes
ActionInfo -> defaultMediaTypes ActionInfo -> defaultMediaTypes
ActionMutate _ -> defaultMediaTypes ActionMutate _ -> defaultMediaTypes
ActionInspect _ -> inspectMediaTypes ActionInspect _ -> inspectMediaTypes
where where
inspectMediaTypes = [MTOpenAPI, MTApplicationJSON, MTArrayJSONStrip, MTAny] inspectMediaTypes = [MTOpenAPI, MTApplicationJSON, MTArrayJSONStrip, MTAny]
invokeMediaTypes =
defaultMediaTypes
++ [MTOpenAPI | pathIsRootSpec path]
defaultMediaTypes = defaultMediaTypes =
[MTApplicationJSON, MTArrayJSONStrip, MTSingularJSON True, MTSingularJSON False, MTGeoJSON, MTTextCSV] ++ [MTApplicationJSON, MTArrayJSONStrip, MTSingularJSON True, MTSingularJSON False, MTGeoJSON, MTTextCSV] ++
[MTPlan MTApplicationJSON PlanText mempty | configDbPlanEnabled conf] ++ [MTAny] [MTPlan MTApplicationJSON PlanText mempty | configDbPlanEnabled conf] ++ [MTAny]
+3 -2
View File
@@ -3,7 +3,7 @@ module Feature.OpenApi.RootSpec where
import Network.HTTP.Types import Network.HTTP.Types
import Network.Wai (Application) import Network.Wai (Application)
import Test.Hspec import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
@@ -12,7 +12,8 @@ import Protolude hiding (get)
spec :: SpecWith ((), Application) spec :: SpecWith ((), Application)
spec = spec =
describe "root spec function" $ do describe "root spec function" $ do
it "accepts application/openapi+json" $ it "accepts application/openapi+json" $ do
pendingWith "TBD"
request methodGet "/" request methodGet "/"
[("Accept","application/openapi+json")] "" `shouldRespondWith` [("Accept","application/openapi+json")] "" `shouldRespondWith`
[json|{ [json|{