module Network.Salvia.Handler.Close ( hCloseConn , hKeepAlive ) where import Control.Monad.State import Data.Maybe import Data.Record.Label import Network.Protocol.Http import Network.Salvia.Httpd import System.IO {- | Run a handler once and close the connection afterwards. -} hCloseConn :: Handler () -> Handler () hCloseConn h = h >> getM sock >>= liftIO . hClose {- | Run a handler and keep the connection open for potential consecutive requests. The connection will only be closed after a request finished and one or more of the following criteria are met: * There is no `contentLength` set in the response headers. When this is the case the connection cannot be kept alive. * The client has set the `connection` header field to 'close'. * The connection has already been closed, possible due to IO errors. -} hKeepAlive :: Handler () -> Handler () hKeepAlive handler = do handler h <- getM sock conn <- getM (connection % request) len <- getM (contentLength % response) closed <- liftIO (hIsClosed h) if or [closed, conn == "Close", isNothing (len::Maybe Integer) ] then liftIO (hClose h) else resetContext >> hKeepAlive handler resetContext :: Handler () resetContext = do setM request emptyRequest setM response emptyResponse setM queue []