@@ -3,6 +3,7 @@ module Network.Wai.Handler.Warp.WithApplication (
3 withApplication,
3 withApplication,
4 testWithApplication,
4 testWithApplication,
5 openFreePort,
5 openFreePort,
8import Control.Concurrent
9import Control.Concurrent
@@ -16,8 +17,7 @@ import Network.Wai.Handler.Warp.Types
18 appThread :: ThreadId,
19 appThread :: ThreadId,
19− appKilled :: Waiter (),
20+ appKilled :: Waiter ()
23-- | Runs the given 'Application' on a free port. Passes the port to the given
23-- | Runs the given 'Application' on a free port. Passes the port to the given
@@ -26,25 +26,26 @@ data App
26withApplication :: IO Application -> (Port -> IO a) -> IO a
26withApplication :: IO Application -> (Port -> IO a) -> IO a
27withApplication mkApp action = do
27withApplication mkApp action = do
28 app <- mkApp
28 app <- mkApp
29− bracket (acquire app) free (\ runningApp -> action (appPort runningApp))
29+ withFreePort $ \ (port, sock) -> do
30+ bracket (start app sock) stop $ \ _ ->
31− acquire :: Application -> IO App
33+ start :: Application -> Socket -> IO App
32− acquire app = do
34+ start app sock = do
33− start <- mkWaiter
35+ started <- mkWaiter
34 killed <- mkWaiter
36 killed <- mkWaiter
35 thread <- forkIO $ do
37 thread <- forkIO $ do
36− (port, sock) <- openFreePort
37 let settings =
38 let settings =
38 defaultSettings{
39 defaultSettings{
39− settingsBeforeMainLoop = notify start port
40+ settingsBeforeMainLoop = notify started ()
41 runSettingsSocket settings sock app
42 runSettingsSocket settings sock app
42 `finally` notify killed ()
43 `finally` notify killed ()
43− port <- waitFor start
44+ waitFor started
44− return $ App thread killed port
45+ return $ App thread killed
46− free :: App -> IO ()
47+ stop :: App -> IO ()
47− free runningApp = do
48+ stop runningApp = do
48 killThread $ appThread runningApp
49 killThread $ appThread runningApp
49 waitFor $ appKilled runningApp
50 waitFor $ appKilled runningApp
@@ -92,3 +93,7 @@ openFreePort = do
92 listen s 1
93 listen s 1
93 port <- socketPort s
94 port <- socketPort s
94 return (fromIntegral port, s)
95 return (fromIntegral port, s)
97+-- | Like 'openFreePort' but closes the socket before exiting.
98+withFreePort :: ((Port, Socket) -> IO a) -> IO a
99+withFreePort = bracket openFreePort (close . snd)