App has database pools!
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ cabal-version: >=1.10
|
|||||||
|
|
||||||
executable dbapi
|
executable dbapi
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
ghc-options: -Wall -W -threaded
|
ghc-options: -Wall -W -Werror
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
build-depends: base >=4.6 && <5
|
build-depends: base >=4.6 && <5
|
||||||
, HDBC, HDBC-postgresql
|
, HDBC, HDBC-postgresql
|
||||||
|
|||||||
+4
-14
@@ -16,12 +16,6 @@ import Network.Wai.Middleware.Static (staticPolicy, only)
|
|||||||
import Database.HDBC (disconnect)
|
import Database.HDBC (disconnect)
|
||||||
import Database.HDBC.PostgreSQL(connectPostgreSQL')
|
import Database.HDBC.PostgreSQL(connectPostgreSQL')
|
||||||
import Data.Pool(createPool)
|
import Data.Pool(createPool)
|
||||||
import System.Process
|
|
||||||
|
|
||||||
import Control.Concurrent(threadDelay)
|
|
||||||
|
|
||||||
import Network.HTTP.Types.Status
|
|
||||||
import Network.Wai
|
|
||||||
|
|
||||||
argParser :: Parser AppConfig
|
argParser :: Parser AppConfig
|
||||||
argParser = AppConfig
|
argParser = AppConfig
|
||||||
@@ -37,21 +31,17 @@ argParser = AppConfig
|
|||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
conf <- execParser (info (helper <*> argParser) describe)
|
conf <- execParser (info (helper <*> argParser) describe)
|
||||||
let dburi = configDbUri conf
|
pool <- createPool (connectPostgreSQL' (configDbUri conf)) disconnect 1 600 10
|
||||||
pool <- createPool (putStrLn "creating connection" >> connectPostgreSQL' (configDbUri conf)) (\c-> putStrLn "destroying connection" >> disconnect c) 1 600 10
|
|
||||||
let port = configPort conf
|
let port = configPort conf
|
||||||
|
|
||||||
unless (configSecure conf) $
|
unless (configSecure conf) $
|
||||||
putStrLn "WARNING, running in insecure mode, auth will be in plaintext"
|
putStrLn "WARNING, running in insecure mode, auth will be in plaintext"
|
||||||
|
|
||||||
Prelude.putStrLn $ "Listening on port " ++ (show $ configPort conf :: String)
|
Prelude.putStrLn $ "Listening on port " ++ (show $ configPort conf :: String)
|
||||||
conn <- connectPostgreSQL' dburi
|
|
||||||
run port $ (if configSecure conf then redirectInsecure else id)
|
run port $ (if configSecure conf then redirectInsecure else id)
|
||||||
. gzip def
|
. gzip def . cors corsPolicy . clientErrors
|
||||||
. cors corsPolicy
|
|
||||||
. clientErrors
|
|
||||||
. staticPolicy (only [("favicon.ico", "static/favicon.ico")])
|
. staticPolicy (only [("favicon.ico", "static/favicon.ico")])
|
||||||
$ (inTransaction . authenticated (cs $ configAnonRole conf) . withSavepoint)
|
. withDBConnection pool . inTransaction
|
||||||
app conn
|
. authenticated (cs $ configAnonRole conf) . withSavepoint $ app
|
||||||
where
|
where
|
||||||
describe = progDesc "create a REST API to an existing Postgres database"
|
describe = progDesc "create a REST API to an existing Postgres database"
|
||||||
|
|||||||
+2
-3
@@ -16,7 +16,6 @@ import Data.String.Conversions(cs)
|
|||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
import Control.Exception (finally, throw, catchJust, catch, SomeException,
|
import Control.Exception (finally, throw, catchJust, catch, SomeException,
|
||||||
bracket_)
|
bracket_)
|
||||||
import Control.Concurrent(threadDelay)
|
|
||||||
|
|
||||||
import Network.HTTP.Types.Header (RequestHeaders, hContentType, hAuthorization,
|
import Network.HTTP.Types.Header (RequestHeaders, hContentType, hAuthorization,
|
||||||
hLocation)
|
hLocation)
|
||||||
@@ -53,9 +52,9 @@ authenticated anon app conn req respond = do
|
|||||||
LoginFailed ->
|
LoginFailed ->
|
||||||
respond $ responseLBS status401 [] "Invalid username or password"
|
respond $ responseLBS status401 [] "Invalid username or password"
|
||||||
LoginSuccess role ->
|
LoginSuccess role ->
|
||||||
bracket_ (setRole conn role >> threadDelay 10000000) (resetRole conn) $ app conn req respond
|
bracket_ (setRole conn role) (resetRole conn) $ app conn req respond
|
||||||
NoCredentials ->
|
NoCredentials ->
|
||||||
bracket_ (setRole conn anon >> threadDelay 10000000) (resetRole conn) $ app conn req respond
|
bracket_ (setRole conn anon) (resetRole conn) $ app conn req respond
|
||||||
|
|
||||||
where
|
where
|
||||||
httpRequesterRole :: RequestHeaders -> IO LoginAttempt
|
httpRequesterRole :: RequestHeaders -> IO LoginAttempt
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ spec = around appWithFixture $ do
|
|||||||
it "fails with 400 and error" $
|
it "fails with 400 and error" $
|
||||||
post "/simple_pk" "}{ x = 2"
|
post "/simple_pk" "}{ x = 2"
|
||||||
`shouldRespondWith` ResponseMatcher {
|
`shouldRespondWith` ResponseMatcher {
|
||||||
matchBody = Just [json| {"error":"Failed to parse JSON payload. Failed reading: satisfy"} |]
|
matchBody = Just [json| {"error":"Failed to parse JSON payload. Failed reading: satisfyElem"} |]
|
||||||
, matchStatus = 400
|
, matchStatus = 400
|
||||||
, matchHeaders = []
|
, matchHeaders = []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user