heroku-0.1.2: Web/Heroku/Internal.hs
module Web.Heroku.Internal (
dbConnParams'
, parseDatabaseUrl'
) where
import System.Environment
import Network.URI
import Data.Text
import Prelude
-- | read the DATABASE_URL environment variable
-- and return an alist of connection parameters with the following keys:
-- user, password, host, port, dbname
--
-- warning: just calls error if it can't parse correctly
dbConnParams' :: String -> (String -> [(Text, Text)]) -> IO [(Text, Text)]
dbConnParams' envVar parse = getEnv envVar >>= return . parse
parseDatabaseUrl' :: String -> String -> [(Text, Text)]
parseDatabaseUrl' scheme durl =
let muri = parseAbsoluteURI durl
(auth, path) = case muri of
Nothing -> error "couldn't parse absolute uri"
Just uri -> if uriScheme uri /= scheme
then schemeError uri
else case uriAuthority uri of
Nothing -> invalid
Just a -> (a, uriPath uri)
(user,password) = userAndPassword auth
in [ (pack "user", user)
-- tail not safe, but should be there on Heroku
, (pack "password", Data.Text.tail password)
, (pack "host", pack $ uriRegName auth)
, (pack "port", pack $ removeColon $ uriPort auth)
-- tail not safe but path should always be there
, (pack "dbname", pack $ Prelude.tail $ path)
]
where
removeColon (':':port) = port
removeColon port = port
-- init is not safe, but should be there on Heroku
userAndPassword :: URIAuth -> (Text, Text)
userAndPassword = (breakOn $ pack ":") . pack . Prelude.init . uriUserInfo
schemeError uri = error $ "was expecting a postgres scheme, not: " ++ (uriScheme uri) ++ "\n" ++ (show uri)
-- should be an error
invalid = error "could not parse heroku DATABASE_URL"