refactor: separate reading file from parsing it
This commit is contained in:
committed by
Steve Chavez
parent
343e41c51d
commit
896b79f05b
+6
-3
@@ -31,7 +31,7 @@ import System.IO (BufferMode (..), hSetBuffering)
|
|||||||
|
|
||||||
import PostgREST.App (postgrest)
|
import PostgREST.App (postgrest)
|
||||||
import PostgREST.Config (AppConfig (..), configPoolTimeout',
|
import PostgREST.Config (AppConfig (..), configPoolTimeout',
|
||||||
prettyVersion, readOptions)
|
prettyVersion, readAppConfig, readPath)
|
||||||
import PostgREST.DbStructure (getDbStructure, getPgVersion)
|
import PostgREST.DbStructure (getDbStructure, getPgVersion)
|
||||||
import PostgREST.Error (PgError (PgError), checkIsFatal,
|
import PostgREST.Error (PgError (PgError), checkIsFatal,
|
||||||
errorPayload)
|
errorPayload)
|
||||||
@@ -200,10 +200,13 @@ main = do
|
|||||||
hSetBuffering stdout LineBuffering
|
hSetBuffering stdout LineBuffering
|
||||||
hSetBuffering stdin LineBuffering
|
hSetBuffering stdin LineBuffering
|
||||||
hSetBuffering stderr NoBuffering
|
hSetBuffering stderr NoBuffering
|
||||||
--
|
|
||||||
|
path <- readPath
|
||||||
|
|
||||||
-- readOptions builds the 'AppConfig' from the config file specified on the
|
-- readOptions builds the 'AppConfig' from the config file specified on the
|
||||||
-- command line
|
-- command line
|
||||||
conf <- loadDbUriFile =<< loadSecretFile =<< readOptions
|
conf <- loadDbUriFile =<< loadSecretFile =<< readAppConfig path
|
||||||
|
|
||||||
let schemas = toList $ configSchemas conf
|
let schemas = toList $ configSchemas conf
|
||||||
host = configHost conf
|
host = configHost conf
|
||||||
port = configPort conf
|
port = configPort conf
|
||||||
|
|||||||
+87
-80
@@ -19,7 +19,8 @@ Other hardcoded options such as the minimum version number also belong here.
|
|||||||
|
|
||||||
module PostgREST.Config ( prettyVersion
|
module PostgREST.Config ( prettyVersion
|
||||||
, docsVersion
|
, docsVersion
|
||||||
, readOptions
|
, readPath
|
||||||
|
, readAppConfig
|
||||||
, corsPolicy
|
, corsPolicy
|
||||||
, AppConfig (..)
|
, AppConfig (..)
|
||||||
, configPoolTimeout'
|
, configPoolTimeout'
|
||||||
@@ -93,6 +94,8 @@ data AppConfig = AppConfig {
|
|||||||
|
|
||||||
, configRootSpec :: Maybe Text
|
, configRootSpec :: Maybe Text
|
||||||
, configRawMediaTypes :: [B.ByteString]
|
, configRawMediaTypes :: [B.ByteString]
|
||||||
|
|
||||||
|
, configPath :: Maybe FilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
configPoolTimeout' :: (Fractional a) => AppConfig -> a
|
configPoolTimeout' :: (Fractional a) => AppConfig -> a
|
||||||
@@ -137,25 +140,100 @@ prettyVersion =
|
|||||||
docsVersion :: Text
|
docsVersion :: Text
|
||||||
docsVersion = "v" <> dropEnd 1 (dropWhileEnd (/= '.') prettyVersion)
|
docsVersion = "v" <> dropEnd 1 (dropWhileEnd (/= '.') prettyVersion)
|
||||||
|
|
||||||
-- | Function to read and parse options from the command line
|
-- | Read config the file path from the command line. Also print helpful messages.
|
||||||
readOptions :: IO AppConfig
|
readPath :: IO FilePath
|
||||||
readOptions = do
|
readPath = customExecParser parserPrefs opts
|
||||||
-- First read the config file path from command line
|
where
|
||||||
cfgPath <- customExecParser parserPrefs opts
|
parserPrefs = prefs showHelpOnError
|
||||||
|
|
||||||
|
opts = info (helper <*> pathParser) $
|
||||||
|
fullDesc
|
||||||
|
<> progDesc (
|
||||||
|
"PostgREST "
|
||||||
|
<> toS prettyVersion
|
||||||
|
<> " / create a REST API to an existing Postgres database"
|
||||||
|
)
|
||||||
|
<> footerDoc (Just $
|
||||||
|
text "Example Config File:"
|
||||||
|
L.<> nest 2 (hardline L.<> exampleCfg)
|
||||||
|
)
|
||||||
|
|
||||||
|
pathParser :: Parser FilePath
|
||||||
|
pathParser =
|
||||||
|
strArgument $
|
||||||
|
metavar "FILENAME" <>
|
||||||
|
help "Path to configuration file"
|
||||||
|
|
||||||
|
exampleCfg :: Doc
|
||||||
|
exampleCfg = vsep . map (text . toS) . lines $
|
||||||
|
[str|db-uri = "postgres://user:pass@localhost:5432/dbname"
|
||||||
|
|db-schema = "public" # this schema gets added to the search_path of every request
|
||||||
|
|db-anon-role = "postgres"
|
||||||
|
|db-pool = 10
|
||||||
|
|db-pool-timeout = 10
|
||||||
|
|
|
||||||
|
|server-host = "!4"
|
||||||
|
|server-port = 3000
|
||||||
|
|
|
||||||
|
|## unix socket location
|
||||||
|
|## if specified it takes precedence over server-port
|
||||||
|
|# server-unix-socket = "/tmp/pgrst.sock"
|
||||||
|
|## unix socket file mode
|
||||||
|
|## when none is provided, 660 is applied by default
|
||||||
|
|# server-unix-socket-mode = "660"
|
||||||
|
|
|
||||||
|
|## Notification channel for reloading the schema cache
|
||||||
|
|# db-channel = "pgrst"
|
||||||
|
|## Enable or disable the notification channel
|
||||||
|
|# db-channel-enabled = false
|
||||||
|
|
|
||||||
|
|## base url for swagger output
|
||||||
|
|# openapi-server-proxy-uri = ""
|
||||||
|
|
|
||||||
|
|## choose a secret, JSON Web Key (or set) to enable JWT auth
|
||||||
|
|## (use "@filename" to load from separate file)
|
||||||
|
|# jwt-secret = "secret_with_at_least_32_characters"
|
||||||
|
|# secret-is-base64 = false
|
||||||
|
|# jwt-aud = "your_audience_claim"
|
||||||
|
|
|
||||||
|
|## limit rows in response
|
||||||
|
|# max-rows = 1000
|
||||||
|
|
|
||||||
|
|## stored proc to exec immediately after auth
|
||||||
|
|# pre-request = "stored_proc_name"
|
||||||
|
|
|
||||||
|
|## jspath to the role claim key
|
||||||
|
|# role-claim-key = ".role"
|
||||||
|
|
|
||||||
|
|## extra schemas to add to the search_path of every request
|
||||||
|
|# db-extra-search-path = "extensions, util"
|
||||||
|
|
|
||||||
|
|## stored proc that overrides the root "/" spec
|
||||||
|
|## it must be inside the db-schema
|
||||||
|
|# root-spec = "stored_proc_name"
|
||||||
|
|
|
||||||
|
|## content types to produce raw output
|
||||||
|
|# raw-media-types="image/png, image/jpg"
|
||||||
|
|]
|
||||||
|
|
||||||
|
|
||||||
|
-- | Parse the config file
|
||||||
|
readAppConfig :: FilePath -> IO AppConfig
|
||||||
|
readAppConfig cfgPath = do
|
||||||
-- Now read the actual config file
|
-- Now read the actual config file
|
||||||
conf <- catches (C.load cfgPath)
|
conf <- catches (C.load cfgPath)
|
||||||
[ Handler (\(ex :: IOError) -> exitErr $ "Cannot open config file:\n\t" <> show ex)
|
[ Handler (\(ex :: IOError) -> exitErr $ "Cannot open config file:\n\t" <> show ex)
|
||||||
, Handler (\(C.ParseError err) -> exitErr $ "Error parsing config file:\n" <> err)
|
, Handler (\(C.ParseError err) -> exitErr $ "Error parsing config file:\n" <> err)
|
||||||
]
|
]
|
||||||
|
|
||||||
case C.runParser parseConfig conf of
|
case C.runParser (parseConfig cfgPath) conf of
|
||||||
Left err ->
|
Left err ->
|
||||||
exitErr $ "Error parsing config file:\n\t" <> err
|
exitErr $ "Error parsing config file:\n\t" <> err
|
||||||
Right appConf ->
|
Right appConf ->
|
||||||
return appConf
|
return appConf
|
||||||
|
|
||||||
where
|
where
|
||||||
parseConfig =
|
parseConfig path =
|
||||||
AppConfig
|
AppConfig
|
||||||
<$> reqString "db-uri"
|
<$> reqString "db-uri"
|
||||||
<*> reqString "db-anon-role"
|
<*> reqString "db-anon-role"
|
||||||
@@ -180,6 +258,7 @@ readOptions = do
|
|||||||
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
|
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
|
||||||
<*> optString "root-spec"
|
<*> optString "root-spec"
|
||||||
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
|
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
|
||||||
|
<*> pure (Just path)
|
||||||
|
|
||||||
parseSocketFileMode :: C.Key -> C.Parser C.Config (Either Text FileMode)
|
parseSocketFileMode :: C.Key -> C.Parser C.Config (Either Text FileMode)
|
||||||
parseSocketFileMode k =
|
parseSocketFileMode k =
|
||||||
@@ -243,79 +322,7 @@ readOptions = do
|
|||||||
splitOnCommas (C.String s) = strip <$> splitOn "," s
|
splitOnCommas (C.String s) = strip <$> splitOn "," s
|
||||||
splitOnCommas _ = []
|
splitOnCommas _ = []
|
||||||
|
|
||||||
opts = info (helper <*> pathParser) $
|
|
||||||
fullDesc
|
|
||||||
<> progDesc (
|
|
||||||
"PostgREST "
|
|
||||||
<> toS prettyVersion
|
|
||||||
<> " / create a REST API to an existing Postgres database"
|
|
||||||
)
|
|
||||||
<> footerDoc (Just $
|
|
||||||
text "Example Config File:"
|
|
||||||
L.<> nest 2 (hardline L.<> exampleCfg)
|
|
||||||
)
|
|
||||||
|
|
||||||
parserPrefs = prefs showHelpOnError
|
|
||||||
|
|
||||||
exitErr :: Text -> IO a
|
exitErr :: Text -> IO a
|
||||||
exitErr err = do
|
exitErr err = do
|
||||||
hPutStrLn stderr err
|
hPutStrLn stderr err
|
||||||
exitFailure
|
exitFailure
|
||||||
|
|
||||||
exampleCfg :: Doc
|
|
||||||
exampleCfg = vsep . map (text . toS) . lines $
|
|
||||||
[str|db-uri = "postgres://user:pass@localhost:5432/dbname"
|
|
||||||
|db-schema = "public" # this schema gets added to the search_path of every request
|
|
||||||
|db-anon-role = "postgres"
|
|
||||||
|db-pool = 10
|
|
||||||
|db-pool-timeout = 10
|
|
||||||
|
|
|
||||||
|server-host = "!4"
|
|
||||||
|server-port = 3000
|
|
||||||
|
|
|
||||||
|## unix socket location
|
|
||||||
|## if specified it takes precedence over server-port
|
|
||||||
|# server-unix-socket = "/tmp/pgrst.sock"
|
|
||||||
|## unix socket file mode
|
|
||||||
|## when none is provided, 660 is applied by default
|
|
||||||
|# server-unix-socket-mode = "660"
|
|
||||||
|
|
|
||||||
|## Notification channel for reloading the schema cache
|
|
||||||
|# db-channel = "pgrst"
|
|
||||||
|## Enable or disable the notification channel
|
|
||||||
|# db-channel-enabled = false
|
|
||||||
|
|
|
||||||
|## base url for swagger output
|
|
||||||
|# openapi-server-proxy-uri = ""
|
|
||||||
|
|
|
||||||
|## choose a secret, JSON Web Key (or set) to enable JWT auth
|
|
||||||
|## (use "@filename" to load from separate file)
|
|
||||||
|# jwt-secret = "secret_with_at_least_32_characters"
|
|
||||||
|# secret-is-base64 = false
|
|
||||||
|# jwt-aud = "your_audience_claim"
|
|
||||||
|
|
|
||||||
|## limit rows in response
|
|
||||||
|# max-rows = 1000
|
|
||||||
|
|
|
||||||
|## stored proc to exec immediately after auth
|
|
||||||
|# pre-request = "stored_proc_name"
|
|
||||||
|
|
|
||||||
|## jspath to the role claim key
|
|
||||||
|# role-claim-key = ".role"
|
|
||||||
|
|
|
||||||
|## extra schemas to add to the search_path of every request
|
|
||||||
|# db-extra-search-path = "extensions, util"
|
|
||||||
|
|
|
||||||
|## stored proc that overrides the root "/" spec
|
|
||||||
|## it must be inside the db-schema
|
|
||||||
|# root-spec = "stored_proc_name"
|
|
||||||
|
|
|
||||||
|## content types to produce raw output
|
|
||||||
|# raw-media-types="image/png, image/jpg"
|
|
||||||
|]
|
|
||||||
|
|
||||||
pathParser :: Parser FilePath
|
|
||||||
pathParser =
|
|
||||||
strArgument $
|
|
||||||
metavar "FILENAME" <>
|
|
||||||
help "Path to configuration file"
|
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ _baseCfg = -- Connection Settings
|
|||||||
Nothing
|
Nothing
|
||||||
-- Raw output media types
|
-- Raw output media types
|
||||||
[]
|
[]
|
||||||
|
-- Config path
|
||||||
|
Nothing
|
||||||
|
|
||||||
testCfg :: Text -> AppConfig
|
testCfg :: Text -> AppConfig
|
||||||
testCfg testDbConn = _baseCfg { configDbUri = testDbConn }
|
testCfg testDbConn = _baseCfg { configDbUri = testDbConn }
|
||||||
|
|||||||
Reference in New Issue
Block a user