Skip to content

Commit

Permalink
add raw-media-endpoints config option
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-amoroso committed Jun 22, 2020
1 parent 24064f8 commit 15d2405
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 65 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added

- #1462, Add `raw-media-endpoint` config option - @Dansvidania
- #1525, Allow http status override through response.status guc - @steve-chavez

### Fixed
Expand Down
122 changes: 62 additions & 60 deletions postgrest.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -172,37 +172,38 @@ test-suite spec
SpecHelper
TestTypes
hs-source-dirs: test
build-depends: base >= 4.9 && < 4.15
, aeson >= 1.4.7 && < 1.6
, aeson-qq >= 0.8.1 && < 0.9
, async >= 2.1.1 && < 2.3
, auto-update >= 0.1.4 && < 0.2
, base64-bytestring >= 1 && < 1.2
, bytestring >= 0.10.8 && < 0.11
, case-insensitive >= 1.2 && < 1.3
, cassava >= 0.4.5 && < 0.6
, containers >= 0.5.7 && < 0.7
, contravariant >= 1.4 && < 1.6
, hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6
, hasql-transaction >= 0.7.2 && < 1.1
, heredoc >= 0.2 && < 0.3
, hspec >= 2.3 && < 2.8
, hspec-wai >= 0.10 && < 0.11
, hspec-wai-json >= 0.10 && < 0.11
, http-types >= 0.12.3 && < 0.13
, lens >= 4.14 && < 4.20
, lens-aeson >= 1.0.1 && < 1.2
, monad-control >= 1.0.1 && < 1.1
build-depends: base >= 4.9 && < 4.15
, aeson >= 1.4.7 && < 1.6
, aeson-qq >= 0.8.1 && < 0.9
, async >= 2.1.1 && < 2.3
, auto-update >= 0.1.4 && < 0.2
, base64-bytestring >= 1 && < 1.2
, bytestring >= 0.10.8 && < 0.11
, case-insensitive >= 1.2 && < 1.3
, cassava >= 0.4.5 && < 0.6
, containers >= 0.5.7 && < 0.7
, contravariant >= 1.4 && < 1.6
, hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6
, hasql-transaction >= 0.7.2 && < 1.1
, heredoc >= 0.2 && < 0.3
, hspec >= 2.3 && < 2.8
, hspec-wai >= 0.10 && < 0.11
, hspec-wai-json >= 0.10 && < 0.11
, http-types >= 0.12.3 && < 0.13
, lens >= 4.14 && < 4.20
, lens-aeson >= 1.0.1 && < 1.2
, monad-control >= 1.0.1 && < 1.1
, postgrest
, process >= 1.4.2 && < 1.7
, protolude >= 0.3 && < 0.4
, regex-tdfa >= 1.2.2 && < 1.4
, text >= 1.2.2 && < 1.3
, time >= 1.6 && < 1.11
, transformers-base >= 0.4.4 && < 0.5
, wai >= 3.2.1 && < 3.3
, wai-extra >= 3.0.19 && < 3.1
, process >= 1.4.2 && < 1.7
, protolude >= 0.3 && < 0.4
, regex-tdfa >= 1.2.2 && < 1.4
, text >= 1.2.2 && < 1.3
, time >= 1.6 && < 1.11
, transformers-base >= 0.4.4 && < 0.5
, unordered-containers >= 0.2.8 && < 0.3
, wai >= 3.2.1 && < 3.3
, wai-extra >= 3.0.19 && < 3.1
default-language: Haskell2010
default-extensions: OverloadedStrings
QuasiQuotes
Expand All @@ -216,34 +217,35 @@ Test-Suite spec-querycost
Hs-Source-Dirs: test
Main-Is: QueryCost.hs
Other-Modules: SpecHelper
Build-Depends: base >= 4.9 && < 4.15
, aeson >= 1.4.7 && < 1.6
, aeson-qq >= 0.8.1 && < 0.9
, async >= 2.1.1 && < 2.3
, auto-update >= 0.1.4 && < 0.2
, base64-bytestring >= 1 && < 1.2
, bytestring >= 0.10.8 && < 0.11
, case-insensitive >= 1.2 && < 1.3
, cassava >= 0.4.5 && < 0.6
, containers >= 0.5.7 && < 0.7
, contravariant >= 1.4 && < 1.6
, hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6
, hasql-transaction >= 0.7.2 && < 1.1
, heredoc >= 0.2 && < 0.3
, hspec >= 2.3 && < 2.8
, hspec-wai >= 0.10 && < 0.11
, hspec-wai-json >= 0.10 && < 0.11
, http-types >= 0.12.3 && < 0.13
, lens >= 4.14 && < 4.20
, lens-aeson >= 1.0.1 && < 1.2
, monad-control >= 1.0.1 && < 1.1
Build-Depends: base >= 4.9 && < 4.15
, aeson >= 1.4.7 && < 1.6
, aeson-qq >= 0.8.1 && < 0.9
, async >= 2.1.1 && < 2.3
, auto-update >= 0.1.4 && < 0.2
, base64-bytestring >= 1 && < 1.2
, bytestring >= 0.10.8 && < 0.11
, case-insensitive >= 1.2 && < 1.3
, cassava >= 0.4.5 && < 0.6
, containers >= 0.5.7 && < 0.7
, contravariant >= 1.4 && < 1.6
, hasql >= 1.4 && < 1.5
, hasql-pool >= 0.5 && < 0.6
, hasql-transaction >= 0.7.2 && < 1.1
, heredoc >= 0.2 && < 0.3
, hspec >= 2.3 && < 2.8
, hspec-wai >= 0.10 && < 0.11
, hspec-wai-json >= 0.10 && < 0.11
, http-types >= 0.12.3 && < 0.13
, lens >= 4.14 && < 4.20
, lens-aeson >= 1.0.1 && < 1.2
, monad-control >= 1.0.1 && < 1.1
, postgrest
, process >= 1.4.2 && < 1.7
, protolude >= 0.3 && < 0.4
, regex-tdfa >= 1.2.2 && < 1.4
, text >= 1.2.2 && < 1.3
, time >= 1.6 && < 1.11
, transformers-base >= 0.4.4 && < 0.5
, wai >= 3.2.1 && < 3.3
, wai-extra >= 3.0.19 && < 3.1
, process >= 1.4.2 && < 1.7
, protolude >= 0.3 && < 0.4
, regex-tdfa >= 1.2.2 && < 1.4
, text >= 1.2.2 && < 1.3
, time >= 1.6 && < 1.11
, transformers-base >= 0.4.4 && < 0.5
, wai >= 3.2.1 && < 3.3
, wai-extra >= 3.0.19 && < 3.1
, unordered-containers >= 0.2.8 && < 0.3
9 changes: 9 additions & 0 deletions src/PostgREST/ApiRequest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module PostgREST.ApiRequest (
, Target(..)
, mutuallyAgreeable
, userApiRequest
, targetIdentifierText
) where

import qualified Data.Aeson as JSON
Expand Down Expand Up @@ -68,6 +69,14 @@ data Target = TargetIdent QualifiedIdentifier
| TargetUnknown [Text]
deriving Eq

targetIdentifierText :: Target -> Text
targetIdentifierText target
= case target of
TargetIdent qualifiedIdentifier -> qiName qualifiedIdentifier
TargetProc targetProcQfdId _ -> qiName targetProcQfdId
TargetDefaultSpec _ -> "/"
TargetUnknown t -> foldr (<>) "" t

{-|
Describes what the user wants to do. This data type is a
translation of the raw elements of an HTTP request into domain
Expand Down
19 changes: 17 additions & 2 deletions src/PostgREST/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ import Network.Wai

import PostgREST.ApiRequest (Action (..), ApiRequest (..),
InvokeMethod (..), Target (..),
mutuallyAgreeable, userApiRequest)
mutuallyAgreeable,
targetIdentifierText,
userApiRequest)
import PostgREST.Auth (containsRole, jwtClaims,
parseSecret)
import PostgREST.Config (AppConfig (..))
Expand Down Expand Up @@ -117,9 +119,22 @@ transactionMode proc action =
else HT.Write
_ -> HT.Write

getRawMediaTypesForApiRequest :: AppConfig -> ApiRequest -> [ContentType]
getRawMediaTypesForApiRequest conf request
| configRawMediaEndpoints conf == M.empty
= decodeContentType <$> configRawMediaTypes conf
| otherwise
= let targetText :: Text
targetText = targetIdentifierText $ iTarget request
requestContentTypes = decodeContentType
<$> fromMaybe [] (M.lookup targetText $ configRawMediaEndpoints conf)
defaultContentTypes = (decodeContentType
<$> fromMaybe [] (M.lookup "*" $ configRawMediaEndpoints conf))
in requestContentTypes <> defaultContentTypes

app :: DbStructure -> Maybe ProcDescription -> S.Set FieldName -> AppConfig -> ApiRequest -> H.Transaction Response
app dbStructure proc cols conf apiRequest =
let rawContentTypes = (decodeContentType <$> configRawMediaTypes conf) `L.union` [ CTOctetStream, CTTextPlain ] in
let rawContentTypes = getRawMediaTypesForApiRequest conf apiRequest `L.union` [ CTOctetStream, CTTextPlain ] in
case responseContentTypeOrError (iAccepts apiRequest) rawContentTypes (iAction apiRequest) (iTarget apiRequest) of
Left errorResponse -> return errorResponse
Right contentType ->
Expand Down
18 changes: 16 additions & 2 deletions src/PostgREST/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BS
import qualified Data.CaseInsensitive as CI
import qualified Data.Configurator as C
import qualified Data.HashMap.Strict as M
import qualified Text.PrettyPrint.ANSI.Leijen as L

import Control.Lens (preview)
Expand All @@ -40,7 +41,7 @@ import Data.List.NonEmpty (fromList)
import Data.Scientific (floatingOrInteger)
import Data.Text (dropEnd, dropWhileEnd,
intercalate, splitOn, strip, take,
unpack)
takeWhileEnd, unpack)
import Data.Text.IO (hPutStrLn)
import Data.Version (versionBranch)
import Development.GitRev (gitHash)
Expand Down Expand Up @@ -91,6 +92,7 @@ data AppConfig = AppConfig {

, configRootSpec :: Maybe Text
, configRawMediaTypes :: [B.ByteString]
, configRawMediaEndpoints :: M.HashMap Text [B.ByteString]
}

configPoolTimeout' :: (Fractional a) => AppConfig -> a
Expand Down Expand Up @@ -175,7 +177,19 @@ readOptions = do
<*> (maybe (Right [JSPKey "role"]) parseRoleClaimKey <$> optValue "role-claim-key")
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
<*> optString "root-spec"
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
<*> parseRawMediaTypes
<*> parseRawMediaEndpoints

parseRawMediaTypes :: C.Parser C.Config [B.ByteString]
parseRawMediaTypes = maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types"

parseRawMediaEndpoints :: C.Parser C.Config (M.HashMap Text [B.ByteString])
parseRawMediaEndpoints = M.fromList . stripKeysRoot <$> C.subassocs "raw-media-endpoints" (fmap encodeUtf8 . splitOnCommas <$> C.value)
where stripKeyRoot :: Text -> Text
stripKeyRoot = takeWhileEnd (/= '.')
stripKeysRoot :: [(Text, [B.ByteString])] -> [(Text, [B.ByteString])]
stripKeysRoot [] = []
stripKeysRoot ((key, val):kvs) = (stripKeyRoot key, val):stripKeysRoot kvs

parseSocketFileMode :: C.Key -> C.Parser C.Config (Either Text FileMode)
parseSocketFileMode k =
Expand Down
3 changes: 2 additions & 1 deletion test/SpecHelper.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module SpecHelper where
import qualified Data.ByteString.Base64 as B64 (decodeLenient, encode)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.HashMap.Strict as HM
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import qualified System.IO.Error as E
Expand All @@ -16,7 +17,6 @@ import System.Environment (getEnv)
import System.Process (readProcess)
import Text.Regex.TDFA ((=~))


import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai
Expand Down Expand Up @@ -86,6 +86,7 @@ _baseCfg = -- Connection Settings
Nothing
-- Raw output media types
[]
HM.empty

testCfg :: Text -> AppConfig
testCfg testDbConn = _baseCfg { configDatabase = testDbConn }
Expand Down

0 comments on commit 15d2405

Please sign in to comment.