packages feed

salvia-0.1: src/Network/Salvia/Handler/Close.hs

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 []