{-| Module : PostgREST.Private.ProxyUri Description : Proxy Uri validator -} module PostgREST.Config.Proxy ( Proxy(..) , isMalformedProxyUri , toURI ) where import qualified Data.Text as T import Data.Maybe (fromJust) import Network.URI (URI (..), URIAuth (..), isAbsoluteURI, parseURI) import Protolude hiding (Proxy) data Proxy = Proxy { proxyScheme :: Text , proxyHost :: Text , proxyPort :: Integer , proxyPath :: Text } {-| Test whether a proxy uri is malformed or not. A valid proxy uri should be an absolute uri without query and user info, only http(s) schemes are valid, port number range is 1-65535. For example http://postgrest.com/openapi.json https://postgrest.com:8080/openapi.json -} isMalformedProxyUri :: Text -> Bool isMalformedProxyUri uri | isAbsoluteURI (toS uri) = not $ isUriValid $ toURI uri | otherwise = True toURI :: Text -> URI toURI uri = fromJust $ parseURI (toS uri) isUriValid:: URI -> Bool isUriValid = fAnd [isSchemeValid, isQueryValid, isAuthorityValid] fAnd :: [a -> Bool] -> a -> Bool fAnd fs x = all ($ x) fs isSchemeValid :: URI -> Bool isSchemeValid URI {uriScheme = s} | T.toLower (T.pack s) == "https:" = True | T.toLower (T.pack s) == "http:" = True | otherwise = False isQueryValid :: URI -> Bool isQueryValid URI {uriQuery = ""} = True isQueryValid _ = False isAuthorityValid :: URI -> Bool isAuthorityValid URI {uriAuthority = a} | isJust a = fAnd [isUserInfoValid, isHostValid, isPortValid] $ fromJust a | otherwise = False isUserInfoValid :: URIAuth -> Bool isUserInfoValid URIAuth {uriUserInfo = ""} = True isUserInfoValid _ = False isHostValid :: URIAuth -> Bool isHostValid URIAuth {uriRegName = ""} = False isHostValid _ = True isPortValid :: URIAuth -> Bool isPortValid URIAuth {uriPort = ""} = True isPortValid URIAuth {uriPort = (':':p)} = case readMaybe p of Just i -> i > (0 :: Integer) && i < 65536 Nothing -> False isPortValid _ = False