module Web.Heroku ( 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 :: IO [(Text, Text)] dbConnParams = getEnv "DATABASE_URL" >>= return . parseDatabaseUrl parseDatabaseUrl :: String -> [(Text, Text)] parseDatabaseUrl durl = let muri = parseAbsoluteURI durl (auth, path) = case muri of Nothing -> error "couldn't parse absolute uri" Just uri -> if uriScheme uri /= "postgres:" 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) -- Heroku should use default port -- ,(pack "port", pack $ uriPort auth) -- tail not safe but path should always be there ,(pack "dbname", pack $ Prelude.tail $ path) ] where -- 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"