module Network.HTTP.Mock
(
withMockedManager
) where
import Network.Wai (Application)
import Network.HTTP.Client (Manager,defaultManagerSettings, managerRawConnection, socketConnection, newManager)
import Network.Socket
import System.Directory (removeFile, getTemporaryDirectory)
import Control.Exception (bracket)
import Control.Concurrent.Async (withAsync)
import System.FilePath ((</>))
import System.Random (randomIO)
import Network.Wai.Handler.Warp (runSettingsSocket, defaultSettings)
withMockedManager :: Application -> (Manager -> IO a) -> IO a
withMockedManager app f =
bracket startSocket closeSocket $ \serverSocket -> do
socketAddr <- getSocketName serverSocket
withAsync (runSettingsSocket defaultSettings serverSocket app) $ \_ -> do
manager <- newManager $ defaultManagerSettings { managerRawConnection = (return $ rawConnection socketAddr) }
f manager
where
startSocket = do
socketName <- createNewSocketName
serverSocket <- socket AF_UNIX Stream defaultProtocol
setSocketOption serverSocket ReuseAddr 1
bind serverSocket $ SockAddrUnix socketName
listen serverSocket 10
return serverSocket
closeSocket sock = do
(SockAddrUnix path) <- getSocketName sock
close sock
removeFile path
rawConnection socketAddr _ _ _ = do
socket <- socket AF_UNIX Stream defaultProtocol
connect socket socketAddr
socketConnection socket 1024
createNewSocketName = do
temporaryDirectoryName <- getTemporaryDirectory
random <- show <$> (randomIO :: IO Int)
return $ temporaryDirectoryName </> ("socket_mock_" ++ random)