module PostgREST.Network ( resolveSocketToAddress , escapeHostName , isSpecialHostName ) where import Data.String (IsString (..)) import qualified Network.Socket as NS import Protolude -- | Resolves the socket to an address depending on the socket type. The Show -- instance of the socket types automatically resolves it to the correct -- address. Example resolution: -- ----------------------------------------------------- -- | IPv4 | IPv6 | Unix | -- ----------------------------------------------------- -- | 127.0.0.1:80 | [2001:db8::1]:80 | /tmp/pgrst.sock | -- ----------------------------------------------------- resolveSocketToAddress :: NS.Socket -> IO Text resolveSocketToAddress sock = do sn <- NS.getSocketName sock return $ showSocketAddr sn -- | -- >>> let addr_ipv4 = NS.SockAddrInet 80 (NS.tupleToHostAddress (127,0,0,1)) -- >>> let addr_ipv6 = NS.SockAddrInet6 80 0 (0,0,0,1) 0 -- >>> let addr_unix = NS.SockAddrUnix "/tmp/pgrst.sock" -- -- >>> showSocketAddr addr_ipv4 -- "127.0.0.1:80" -- >>> showSocketAddr addr_ipv6 -- "[::1]:80" -- -- >>> showSocketAddr addr_unix -- "/tmp/pgrst.sock" showSocketAddr :: NS.SockAddr -> Text showSocketAddr = fromString . show -- | When printing special addresses like !4 or *6, we use the following mapping. -- These special addresses come from: -- https://hackage.haskell.org/package/streaming-commons-0.2.3.0/docs/\ -- Data-Streaming-Network.html#t:HostPreference -- TODO: "!6" should not be printed as "0.0.0.0" address. escapeHostName :: Text -> Text escapeHostName "*" = "0.0.0.0" escapeHostName "*4" = "0.0.0.0" escapeHostName "!4" = "0.0.0.0" escapeHostName "*6" = "0.0.0.0" escapeHostName "!6" = "0.0.0.0" escapeHostName h = h -- | Check if a hostname is special isSpecialHostName :: Text -> Bool isSpecialHostName "*" = True isSpecialHostName "*4" = True isSpecialHostName "!4" = True isSpecialHostName "*6" = True isSpecialHostName "!6" = True isSpecialHostName _ = False