{-# LANGUAGE CPP #-}
module Database.Redis.URL
( parseConnectInfo
) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>))
#endif
import Control.Error.Util (note)
import Control.Monad (guard)
#if __GLASGOW_HASKELL__ < 808
import Data.Monoid ((<>))
#endif
import Database.Redis.Connection (ConnectInfo(..), defaultConnectInfo)
import qualified Database.Redis.ConnectionContext as CC
import Network.HTTP.Base
import Network.URI (parseURI, uriPath, uriScheme)
import Text.Read (readMaybe)
import qualified Data.ByteString.Char8 as C8
parseConnectInfo :: String -> Either String ConnectInfo
parseConnectInfo :: String -> Either String ConnectInfo
parseConnectInfo String
url = do
uri <- String -> Maybe URI -> Either String URI
forall a b. a -> Maybe b -> Either a b
note String
"Invalid URI" (Maybe URI -> Either String URI) -> Maybe URI -> Either String URI
forall a b. (a -> b) -> a -> b
$ String -> Maybe URI
parseURI String
url
note "Wrong scheme" $ guard $ uriScheme uri == "redis:"
uriAuth <- note "Missing or invalid Authority"
$ parseURIAuthority
$ uriToAuthorityString uri
let h = URIAuthority -> String
host URIAuthority
uriAuth
dbNumPart = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/') (URI -> String
uriPath URI
uri)
db <- if null dbNumPart
then return $ connectDatabase defaultConnectInfo
else note ("Invalid port: " <> dbNumPart) $ readMaybe dbNumPart
return defaultConnectInfo
{ connectHost = if null h
then connectHost defaultConnectInfo
else h
, connectPort = maybe (connectPort defaultConnectInfo) (CC.PortNumber . fromIntegral) (port uriAuth)
, connectAuth = C8.pack <$> password uriAuth
, connectDatabase = db
}