{-# LANGUAGE BangPatterns               #-}
{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE ExistentialQuantification  #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE Rank2Types                 #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE TypeSynonymInstances       #-}
#if __GLASGOW_HASKELL__ >= 708
{-# LANGUAGE StandaloneDeriving         #-}
#endif
module Snap.Internal.Core
  ( MonadSnap(..)
  , SnapResult(..)
  , EscapeHttpHandler
  , EscapeSnap(..)
  , Zero(..)
  , Snap(..)
  , SnapState(..)
  , runRequestBody
  , readRequestBody
  , transformRequestBody
  , finishWith
  , catchFinishWith
  , pass
  , method
  , methods
  , updateContextPath
  , pathWith
  , dir
  , path
  , pathArg
  , ifTop
  , sget
  , smodify
  , getRequest
  , getResponse
  , getsRequest
  , getsResponse
  , putRequest
  , putResponse
  , modifyRequest
  , modifyResponse
  , redirect
  , redirect'
  , logError
  , addToOutput
  , writeBuilder
  , writeBS
  , writeLBS
  , writeText
  , writeLazyText
  , sendFile
  , sendFilePartial
  , localRequest
  , withRequest
  , withResponse
  , ipHeaderFilter
  , ipHeaderFilter'
  , bracketSnap
  , NoHandlerException(..)
  , terminateConnection
  , escapeHttp
  , runSnap
  , fixupResponse
  , evalSnap
  , getParamFrom
  , getParam
  , getPostParam
  , getQueryParam
  , getParams
  , getPostParams
  , getQueryParams
  , getCookie
  , readCookie
  , expireCookie
  , setTimeout
  , extendTimeout
  , modifyTimeout
  , getTimeoutModifier
  , module Snap.Internal.Http.Types
  ) where
import           Control.Applicative                (Alternative ((<|>), empty), Applicative ((<*>), pure), (<$>))
import           Control.Exception.Lifted           (ErrorCall (..), Exception, Handler (..), SomeException (..), catch, catches, mask, onException, throwIO)
import           Control.Monad                      (Functor (..), Monad (..), MonadPlus (..), ap, liftM, unless, (=<<))
import qualified Control.Monad.Fail                 as Fail
import           Control.Monad.Base                 (MonadBase (..))
import           Control.Monad.IO.Class             (MonadIO (..))
import           Control.Monad.Trans.Control        (MonadBaseControl (..))
import           Control.Monad.Trans.State          (StateT (..))
import           Data.ByteString.Builder            (Builder, byteString, lazyByteString)
import           Data.ByteString.Char8              (ByteString)
import qualified Data.ByteString.Char8              as S (break, concat, drop, dropWhile, intercalate, length, take, takeWhile)
import qualified Data.ByteString.Internal           as S (create)
import qualified Data.ByteString.Lazy.Char8         as L (ByteString, fromChunks)
import           Data.CaseInsensitive               (CI)
import           Data.Maybe                         (Maybe (..), listToMaybe, maybe)
import qualified Data.Text                          as T (Text)
import qualified Data.Text.Encoding as T (encodeUtf8)
import qualified Data.Text.Lazy.Encoding as LT (encodeUtf8)
import qualified Data.Text.Lazy                     as LT (Text)
import           Data.Time                          (Day (ModifiedJulianDay), UTCTime (UTCTime))
#if __GLASGOW_HASKELL__ < 708
import           Data.Typeable                      (TyCon, Typeable, Typeable1 (..), mkTyCon3, mkTyConApp)
#else
import           Data.Typeable                      (Typeable)
#endif
import           Data.Word                          (Word64, Word8)
import           Foreign.Ptr                        (Ptr, plusPtr)
import           Foreign.Storable                   (poke)
import           Prelude                            (Bool (..), Either (..), Eq (..), FilePath, IO, Int, Num (..), Ord (..), Show (..), String, const, divMod, elem, filter, fromIntegral, id, map, max, otherwise, quot, ($), ($!), (++), (.), (||))
import           System.IO.Streams                  (InputStream, OutputStream)
import qualified System.IO.Streams                  as Streams
import           System.Posix.Types                 (FileOffset)
import           System.PosixCompat.Files           (fileSize, getFileStatus)
#if !MIN_VERSION_bytestring(0,10,6)
import qualified Data.ByteString.Internal           as S (inlinePerformIO)
#else
import qualified Data.ByteString.Internal           as S (accursedUnutterablePerformIO)
#endif
import qualified Data.Readable                      as R
import           Snap.Internal.Http.Types           (Cookie (..), HasHeaders (..), HttpVersion, Method (..), Params, Request (..), Response (..), ResponseBody (..), StreamProc, addHeader, addResponseCookie, clearContentLength, deleteHeader, deleteResponseCookie, emptyResponse, formatHttpTime, formatLogTime, getHeader, getResponseCookie, getResponseCookies, listHeaders, modifyResponseBody, modifyResponseCookie, normalizeMethod, parseHttpTime, rqModifyParams, rqParam, rqPostParam, rqQueryParam, rqSetParam, rspBodyMap, rspBodyToEnum, setContentLength, setContentType, setHeader, setResponseBody, setResponseCode, setResponseStatus, statusReasonMap)
import           Snap.Internal.Parsing              (urlDecode)
import qualified Snap.Types.Headers                 as H
class (Monad m, MonadIO m, MonadBaseControl IO m, MonadPlus m, Functor m,
       Applicative m, Alternative m) => MonadSnap m where
  
  liftSnap :: Snap a -> m a
data SnapResult a = SnapValue a
                  | Zero Zero
type EscapeHttpHandler =  ((Int -> Int) -> IO ())    
                       -> InputStream ByteString     
                       -> OutputStream Builder       
                       -> IO ()
data EscapeSnap = TerminateConnection SomeException
                | EscapeHttp EscapeHttpHandler
  deriving (Typeable)
instance Exception EscapeSnap
instance Show EscapeSnap where
    show :: EscapeSnap -> String
show (TerminateConnection SomeException
e) = String
"<terminated: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show SomeException
e forall a. [a] -> [a] -> [a]
++ String
">"
    show (EscapeHttp EscapeHttpHandler
_)          = String
"<escape http>"
data Zero = PassOnProcessing
          | EarlyTermination Response
          | EscapeSnap EscapeSnap
                             
                             
                             
newtype Snap a = Snap {
      forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap :: forall r . (a -> SnapState -> IO r)   
             -> (Zero -> SnapState -> IO r)           
             -> SnapState                             
             -> IO r
    }
data SnapState = SnapState
    { SnapState -> Request
_snapRequest       :: Request
    , SnapState -> Response
_snapResponse      :: Response
    , SnapState -> ByteString -> IO ()
_snapLogError      :: ByteString -> IO ()
    , SnapState -> (Int -> Int) -> IO ()
_snapModifyTimeout :: (Int -> Int) -> IO ()
    }
instance Monad Snap where
    >>= :: forall a b. Snap a -> (a -> Snap b) -> Snap b
(>>=)  = forall a b. Snap a -> (a -> Snap b) -> Snap b
snapBind
#if !MIN_VERSION_base(4,8,0)
    
    return = pure
    {-# INLINE return #-}
#endif
#if !MIN_VERSION_base(4,13,0)
    fail   = Fail.fail
#endif
instance Fail.MonadFail Snap where
    fail :: forall a. String -> Snap a
fail   = forall a. String -> Snap a
snapFail
snapBind :: Snap a -> (a -> Snap b) -> Snap b
snapBind :: forall a b. Snap a -> (a -> Snap b) -> Snap b
snapBind Snap a
m a -> Snap b
f = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \b -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st -> forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap Snap a
m (\a
a SnapState
st' -> forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap (a -> Snap b
f a
a) b -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st') Zero -> SnapState -> IO r
fk SnapState
st
{-# INLINE snapBind #-}
snapFail :: String -> Snap a
snapFail :: forall a. String -> Snap a
snapFail !String
_ = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
_ Zero -> SnapState -> IO r
fk SnapState
st -> Zero -> SnapState -> IO r
fk Zero
PassOnProcessing SnapState
st
{-# INLINE snapFail #-}
instance MonadIO Snap where
    liftIO :: forall a. IO a -> Snap a
liftIO IO a
m = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
_ SnapState
st -> do a
x <- IO a
m
                                     a -> SnapState -> IO r
sk a
x SnapState
st
instance (MonadBase IO) Snap where
    liftBase :: forall a. IO a -> Snap a
liftBase = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
newtype StSnap a = StSnap {
      forall a. StSnap a -> StM (StateT SnapState IO) (SnapResult a)
unStSnap :: StM (StateT SnapState IO) (SnapResult a)
    }
instance (MonadBaseControl IO) Snap where
    type StM Snap a = StSnap a
    liftBaseWith :: forall a. (RunInBase Snap IO -> IO a) -> Snap a
liftBaseWith RunInBase Snap IO -> IO a
f = forall a. StateT SnapState IO (SnapResult a) -> Snap a
stateTToSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a. a -> SnapResult a
SnapValue forall a b. (a -> b) -> a -> b
$
                     forall (b :: * -> *) (m :: * -> *) a.
MonadBaseControl b m =>
(RunInBase m b -> b a) -> m a
liftBaseWith forall a b. (a -> b) -> a -> b
$ \RunInBase (StateT SnapState IO) IO
g' -> RunInBase Snap IO -> IO a
f forall a b. (a -> b) -> a -> b
$ \Snap a
m ->
                     forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a. StM (StateT SnapState IO) (SnapResult a) -> StSnap a
StSnap forall a b. (a -> b) -> a -> b
$ RunInBase (StateT SnapState IO) IO
g' forall a b. (a -> b) -> a -> b
$ forall a. Snap a -> StateT SnapState IO (SnapResult a)
snapToStateT Snap a
m
    {-# INLINE liftBaseWith #-}
    restoreM :: forall a. StM Snap a -> Snap a
restoreM = forall a. StateT SnapState IO (SnapResult a) -> Snap a
stateTToSnap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: * -> *) (m :: * -> *) a.
MonadBaseControl b m =>
StM m a -> m a
restoreM forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. StSnap a -> StM (StateT SnapState IO) (SnapResult a)
unStSnap
    {-# INLINE restoreM #-}
snapToStateT :: Snap a -> StateT SnapState IO (SnapResult a)
snapToStateT :: forall a. Snap a -> StateT SnapState IO (SnapResult a)
snapToStateT Snap a
m = forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT forall a b. (a -> b) -> a -> b
$ \SnapState
st -> do
    forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap Snap a
m (\a
a SnapState
st' -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> SnapResult a
SnapValue a
a, SnapState
st'))
             (\Zero
z SnapState
st' -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Zero -> SnapResult a
Zero Zero
z, SnapState
st')) SnapState
st
{-# INLINE snapToStateT #-}
{-# INLINE stateTToSnap #-}
stateTToSnap :: StateT SnapState IO (SnapResult a) -> Snap a
stateTToSnap :: forall a. StateT SnapState IO (SnapResult a) -> Snap a
stateTToSnap StateT SnapState IO (SnapResult a)
m = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st -> do
    (SnapResult a
a, SnapState
st') <- forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT StateT SnapState IO (SnapResult a)
m SnapState
st
    case SnapResult a
a of
      SnapValue a
x -> a -> SnapState -> IO r
sk a
x SnapState
st'
      Zero Zero
z      -> Zero -> SnapState -> IO r
fk Zero
z SnapState
st'
instance MonadPlus Snap where
    mzero :: forall a. Snap a
mzero = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
_ Zero -> SnapState -> IO r
fk SnapState
st -> Zero -> SnapState -> IO r
fk Zero
PassOnProcessing SnapState
st
    Snap a
a mplus :: forall a. Snap a -> Snap a -> Snap a
`mplus` Snap a
b =
        forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st ->
            let fk' :: Zero -> SnapState -> IO r
fk' Zero
z SnapState
st' = case Zero
z of
                              Zero
PassOnProcessing -> forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap Snap a
b a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st'
                              Zero
_                -> Zero -> SnapState -> IO r
fk Zero
z SnapState
st'
            in forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap Snap a
a a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk' SnapState
st
instance Functor Snap where
    fmap :: forall a b. (a -> b) -> Snap a -> Snap b
fmap a -> b
f Snap a
m = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \b -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st -> forall a.
Snap a
-> forall r.
   (a -> SnapState -> IO r)
   -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
unSnap Snap a
m (b -> SnapState -> IO r
sk forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) Zero -> SnapState -> IO r
fk SnapState
st
instance Applicative Snap where
    pure :: forall a. a -> Snap a
pure a
x  = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
_ SnapState
st -> a -> SnapState -> IO r
sk a
x SnapState
st
    <*> :: forall a b. Snap (a -> b) -> Snap a -> Snap b
(<*>)   = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Alternative Snap where
    empty :: forall a. Snap a
empty = forall (m :: * -> *) a. MonadPlus m => m a
mzero
    <|> :: forall a. Snap a -> Snap a -> Snap a
(<|>) = forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus
instance MonadSnap Snap where
    liftSnap :: forall a. Snap a -> Snap a
liftSnap = forall a. a -> a
id
#if __GLASGOW_HASKELL__ < 708
snapTyCon :: TyCon
#if MIN_VERSION_base(4,4,0)
snapTyCon = mkTyCon3 "snap-core" "Snap.Core" "Snap"
#else
snapTyCon = mkTyCon "Snap.Core.Snap"
#endif
{-# NOINLINE snapTyCon #-}
instance Typeable1 Snap where
    typeOf1 _ = mkTyConApp snapTyCon []
#else
deriving instance Typeable Snap
#endif
runRequestBody :: MonadSnap m =>
                  (InputStream ByteString -> IO a)
               -> m a
runRequestBody :: forall (m :: * -> *) a.
MonadSnap m =>
(InputStream ByteString -> IO a) -> m a
runRequestBody InputStream ByteString -> IO a
proc = do
    IO ()
bumpTimeout <- forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> a
max Int
5) forall (m :: * -> *). MonadSnap m => m ((Int -> Int) -> IO ())
getTimeoutModifier
    Request
req         <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    InputStream ByteString
body        <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ IO ()
-> Double
-> Int
-> InputStream ByteString
-> IO (InputStream ByteString)
Streams.throwIfTooSlow IO ()
bumpTimeout Double
500 Int
5 forall a b. (a -> b) -> a -> b
$
                            Request -> InputStream ByteString
rqBody Request
req
    InputStream ByteString -> m a
run InputStream ByteString
body
  where
    skip :: InputStream a -> m ()
skip InputStream a
body = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall a. InputStream a -> IO ()
Streams.skipToEof InputStream a
body) forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` forall {m :: * -> *} {a}.
MonadSnap m =>
RateTooSlowException -> m a
tooSlow
    tooSlow :: RateTooSlowException -> m a
tooSlow (RateTooSlowException
e :: Streams.RateTooSlowException) =
        forall e (m :: * -> *) a. (Exception e, MonadSnap m) => e -> m a
terminateConnection RateTooSlowException
e
    run :: InputStream ByteString -> m a
run InputStream ByteString
body = (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
        a
x <- InputStream ByteString -> IO a
proc InputStream ByteString
body
        forall a. InputStream a -> IO ()
Streams.skipToEof InputStream ByteString
body
        forall (m :: * -> *) a. Monad m => a -> m a
return a
x) forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> [Handler m a] -> m a
`catches` [Handler m a]
handlers
      where
        handlers :: [Handler m a]
handlers = [ forall (m :: * -> *) a e. Exception e => (e -> m a) -> Handler m a
Handler forall {m :: * -> *} {a}.
MonadSnap m =>
RateTooSlowException -> m a
tooSlow, forall (m :: * -> *) a e. Exception e => (e -> m a) -> Handler m a
Handler SomeException -> m a
other ]
        other :: SomeException -> m a
other (SomeException
e :: SomeException) = forall {m :: * -> *} {a}. MonadSnap m => InputStream a -> m ()
skip InputStream ByteString
body forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO SomeException
e
readRequestBody :: MonadSnap m =>
                   Word64  
                           
                           
                           
                -> m L.ByteString
readRequestBody :: forall (m :: * -> *). MonadSnap m => Word64 -> m ByteString
readRequestBody Word64
sz = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM [ByteString] -> ByteString
L.fromChunks forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadSnap m =>
(InputStream ByteString -> IO a) -> m a
runRequestBody InputStream ByteString -> IO [ByteString]
f
  where
    f :: InputStream ByteString -> IO [ByteString]
f InputStream ByteString
str = Int64 -> InputStream ByteString -> IO (InputStream ByteString)
Streams.throwIfProducesMoreThan (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sz) InputStream ByteString
str forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
            forall a. InputStream a -> IO [a]
Streams.toList
transformRequestBody :: (InputStream ByteString -> IO (InputStream ByteString))
                         
                         
                         
                     -> Snap ()
transformRequestBody :: (InputStream ByteString -> IO (InputStream ByteString)) -> Snap ()
transformRequestBody InputStream ByteString -> IO (InputStream ByteString)
trans = do
    Request
req     <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    InputStream Builder
is      <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO ((InputStream ByteString -> IO (InputStream ByteString)
trans forall a b. (a -> b) -> a -> b
$ Request -> InputStream ByteString
rqBody Request
req) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
                         forall a b. (a -> IO b) -> InputStream a -> IO (InputStream b)
Streams.mapM (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
byteString))
    Response
origRsp <- forall (m :: * -> *). MonadSnap m => m Response
getResponse
    let rsp :: Response
rsp = (OutputStream Builder -> IO (OutputStream Builder))
-> Response -> Response
setResponseBody (\OutputStream Builder
out -> forall a. InputStream a -> OutputStream a -> IO ()
Streams.connect InputStream Builder
is OutputStream Builder
out forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return OutputStream Builder
out) forall a b. (a -> b) -> a -> b
$
              Response
origRsp { rspTransformingRqBody :: Bool
rspTransformingRqBody = Bool
True }
    forall (m :: * -> *) a. MonadSnap m => Response -> m a
finishWith Response
rsp
finishWith :: MonadSnap m => Response -> m a
finishWith :: forall (m :: * -> *) a. MonadSnap m => Response -> m a
finishWith Response
r = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
_ Zero -> SnapState -> IO r
fk SnapState
st -> Zero -> SnapState -> IO r
fk (Response -> Zero
EarlyTermination Response
r) SnapState
st
{-# INLINE finishWith #-}
catchFinishWith :: Snap a -> Snap (Either Response a)
catchFinishWith :: forall a. Snap a -> Snap (Either Response a)
catchFinishWith (Snap forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m) = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \Either Response a -> SnapState -> IO r
sk Zero -> SnapState -> IO r
fk SnapState
st -> do
    let sk' :: a -> SnapState -> IO r
sk' a
v SnapState
s = Either Response a -> SnapState -> IO r
sk (forall a b. b -> Either a b
Right a
v) SnapState
s
    let fk' :: Zero -> SnapState -> IO r
fk' Zero
z SnapState
s = case Zero
z of
                    (EarlyTermination Response
resp) -> Either Response a -> SnapState -> IO r
sk (forall a b. a -> Either a b
Left Response
resp) SnapState
s
                    Zero
_                       -> Zero -> SnapState -> IO r
fk Zero
z SnapState
s
    forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m a -> SnapState -> IO r
sk' Zero -> SnapState -> IO r
fk' SnapState
st
{-# INLINE catchFinishWith #-}
pass :: MonadSnap m => m a
pass :: forall (m :: * -> *) a. MonadSnap m => m a
pass = forall (f :: * -> *) a. Alternative f => f a
empty
method :: MonadSnap m => Method -> m a -> m a
method :: forall (m :: * -> *) a. MonadSnap m => Method -> m a -> m a
method Method
m m a
action = do
    Request
req <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Request -> Method
rqMethod Request
req forall a. Eq a => a -> a -> Bool
== Method
m) forall (m :: * -> *) a. MonadSnap m => m a
pass
    m a
action
{-# INLINE method #-}
methods :: MonadSnap m => [Method] -> m a -> m a
methods :: forall (m :: * -> *) a. MonadSnap m => [Method] -> m a -> m a
methods [Method]
ms m a
action = do
    Request
req <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Request -> Method
rqMethod Request
req forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Method]
ms) forall (m :: * -> *) a. MonadSnap m => m a
pass
    m a
action
{-# INLINE methods #-}
updateContextPath :: Int -> Request -> Request
updateContextPath :: Int -> Request -> Request
updateContextPath Int
n Request
req | Int
n forall a. Ord a => a -> a -> Bool
> Int
0     = Request
req { rqContextPath :: ByteString
rqContextPath = ByteString
ctx
                                          , rqPathInfo :: ByteString
rqPathInfo    = ByteString
pinfo }
                        | Bool
otherwise = Request
req
  where
    ctx' :: ByteString
ctx'  = Int -> ByteString -> ByteString
S.take Int
n (Request -> ByteString
rqPathInfo Request
req)
    ctx :: ByteString
ctx   = [ByteString] -> ByteString
S.concat [Request -> ByteString
rqContextPath Request
req, ByteString
ctx', ByteString
"/"]
    pinfo :: ByteString
pinfo = Int -> ByteString -> ByteString
S.drop (Int
nforall a. Num a => a -> a -> a
+Int
1) (Request -> ByteString
rqPathInfo Request
req)
pathWith :: MonadSnap m
         => (ByteString -> ByteString -> Bool)
         -> ByteString
         -> m a
         -> m a
pathWith :: forall (m :: * -> *) a.
MonadSnap m =>
(ByteString -> ByteString -> Bool) -> ByteString -> m a -> m a
pathWith ByteString -> ByteString -> Bool
c ByteString
p m a
action = do
    Request
req <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> ByteString -> Bool
c ByteString
p (Request -> ByteString
rqPathInfo Request
req)) forall (m :: * -> *) a. MonadSnap m => m a
pass
    forall (m :: * -> *) a.
MonadSnap m =>
(Request -> Request) -> m a -> m a
localRequest (Int -> Request -> Request
updateContextPath forall a b. (a -> b) -> a -> b
$ ByteString -> Int
S.length ByteString
p) m a
action
dir :: MonadSnap m
    => ByteString  
    -> m a         
    -> m a
dir :: forall (m :: * -> *) a. MonadSnap m => ByteString -> m a -> m a
dir = forall (m :: * -> *) a.
MonadSnap m =>
(ByteString -> ByteString -> Bool) -> ByteString -> m a -> m a
pathWith ByteString -> ByteString -> Bool
f
  where
    f :: ByteString -> ByteString -> Bool
f ByteString
dr ByteString
pinfo = ByteString
dr forall a. Eq a => a -> a -> Bool
== ByteString
x
      where
        (ByteString
x,ByteString
_) = (Char -> Bool) -> ByteString -> (ByteString, ByteString)
S.break (forall a. Eq a => a -> a -> Bool
==Char
'/') ByteString
pinfo
{-# INLINE dir #-}
path :: MonadSnap m
     => ByteString  
     -> m a         
     -> m a
path :: forall (m :: * -> *) a. MonadSnap m => ByteString -> m a -> m a
path = forall (m :: * -> *) a.
MonadSnap m =>
(ByteString -> ByteString -> Bool) -> ByteString -> m a -> m a
pathWith forall a. Eq a => a -> a -> Bool
(==)
{-# INLINE path #-}
pathArg :: (R.Readable a, MonadSnap m)
        => (a -> m b)
        -> m b
pathArg :: forall a (m :: * -> *) b.
(Readable a, MonadSnap m) =>
(a -> m b) -> m b
pathArg a -> m b
f = do
    Request
req <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    let (ByteString
p,ByteString
_) = (Char -> Bool) -> ByteString -> (ByteString, ByteString)
S.break (forall a. Eq a => a -> a -> Bool
==Char
'/') (Request -> ByteString
rqPathInfo Request
req)
    ByteString
p' <- forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (m :: * -> *) a. MonadPlus m => m a
mzero forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe ByteString
urlDecode ByteString
p
    a
a <- forall a (m :: * -> *).
(Readable a, MonadPlus m) =>
ByteString -> m a
R.fromBS ByteString
p'
    forall (m :: * -> *) a.
MonadSnap m =>
(Request -> Request) -> m a -> m a
localRequest (Int -> Request -> Request
updateContextPath forall a b. (a -> b) -> a -> b
$ ByteString -> Int
S.length ByteString
p) (a -> m b
f a
a)
ifTop :: MonadSnap m => m a -> m a
ifTop :: forall (m :: * -> *) a. MonadSnap m => m a -> m a
ifTop = forall (m :: * -> *) a. MonadSnap m => ByteString -> m a -> m a
path ByteString
""
{-# INLINE ifTop #-}
sget :: Snap SnapState
sget :: Snap SnapState
sget = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \SnapState -> SnapState -> IO r
sk Zero -> SnapState -> IO r
_ SnapState
st -> SnapState -> SnapState -> IO r
sk SnapState
st SnapState
st
{-# INLINE sget #-}
smodify :: (SnapState -> SnapState) -> Snap ()
smodify :: (SnapState -> SnapState) -> Snap ()
smodify SnapState -> SnapState
f = forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \() -> SnapState -> IO r
sk Zero -> SnapState -> IO r
_ SnapState
st -> () -> SnapState -> IO r
sk () (SnapState -> SnapState
f SnapState
st)
{-# INLINE smodify #-}
getRequest :: MonadSnap m => m Request
getRequest :: forall (m :: * -> *). MonadSnap m => m Request
getRequest = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM SnapState -> Request
_snapRequest Snap SnapState
sget
{-# INLINE getRequest #-}
getsRequest :: MonadSnap m => (Request -> a) -> m a
getsRequest :: forall (m :: * -> *) a. MonadSnap m => (Request -> a) -> m a
getsRequest Request -> a
f = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Request -> a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. SnapState -> Request
_snapRequest) Snap SnapState
sget
{-# INLINE getsRequest #-}
getResponse :: MonadSnap m => m Response
getResponse :: forall (m :: * -> *). MonadSnap m => m Response
getResponse = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM SnapState -> Response
_snapResponse Snap SnapState
sget
{-# INLINE getResponse #-}
getsResponse :: MonadSnap m => (Response -> a) -> m a
getsResponse :: forall (m :: * -> *) a. MonadSnap m => (Response -> a) -> m a
getsResponse Response -> a
f = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Response -> a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. SnapState -> Response
_snapResponse) Snap SnapState
sget
{-# INLINE getsResponse #-}
putResponse :: MonadSnap m => Response -> m ()
putResponse :: forall (m :: * -> *). MonadSnap m => Response -> m ()
putResponse Response
r = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ (SnapState -> SnapState) -> Snap ()
smodify forall a b. (a -> b) -> a -> b
$ \SnapState
ss -> SnapState
ss { _snapResponse :: Response
_snapResponse = Response
r }
{-# INLINE putResponse #-}
putRequest :: MonadSnap m => Request -> m ()
putRequest :: forall (m :: * -> *). MonadSnap m => Request -> m ()
putRequest Request
r = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ (SnapState -> SnapState) -> Snap ()
smodify forall a b. (a -> b) -> a -> b
$ \SnapState
ss -> SnapState
ss { _snapRequest :: Request
_snapRequest = Request
r }
{-# INLINE putRequest #-}
modifyRequest :: MonadSnap m => (Request -> Request) -> m ()
modifyRequest :: forall (m :: * -> *). MonadSnap m => (Request -> Request) -> m ()
modifyRequest Request -> Request
f = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$
    (SnapState -> SnapState) -> Snap ()
smodify forall a b. (a -> b) -> a -> b
$ \SnapState
ss -> SnapState
ss { _snapRequest :: Request
_snapRequest = Request -> Request
f forall a b. (a -> b) -> a -> b
$ SnapState -> Request
_snapRequest SnapState
ss }
{-# INLINE modifyRequest #-}
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()
modifyResponse :: forall (m :: * -> *). MonadSnap m => (Response -> Response) -> m ()
modifyResponse Response -> Response
f = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$
     (SnapState -> SnapState) -> Snap ()
smodify forall a b. (a -> b) -> a -> b
$ \SnapState
ss -> SnapState
ss { _snapResponse :: Response
_snapResponse = Response -> Response
f forall a b. (a -> b) -> a -> b
$ SnapState -> Response
_snapResponse SnapState
ss }
{-# INLINE modifyResponse #-}
redirect :: MonadSnap m => ByteString -> m a
redirect :: forall (m :: * -> *) a. MonadSnap m => ByteString -> m a
redirect ByteString
target = forall (m :: * -> *) a. MonadSnap m => ByteString -> Int -> m a
redirect' ByteString
target Int
302
{-# INLINE redirect #-}
redirect' :: MonadSnap m => ByteString -> Int -> m a
redirect' :: forall (m :: * -> *) a. MonadSnap m => ByteString -> Int -> m a
redirect' ByteString
target Int
status = do
    Response
r <- forall (m :: * -> *). MonadSnap m => m Response
getResponse
    forall (m :: * -> *) a. MonadSnap m => Response -> m a
finishWith
        forall a b. (a -> b) -> a -> b
$ Int -> Response -> Response
setResponseCode Int
status
        forall a b. (a -> b) -> a -> b
$ Word64 -> Response -> Response
setContentLength Word64
0
        forall a b. (a -> b) -> a -> b
$ ((OutputStream Builder -> IO (OutputStream Builder))
 -> OutputStream Builder -> IO (OutputStream Builder))
-> Response -> Response
modifyResponseBody (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> a
id)
        forall a b. (a -> b) -> a -> b
$ forall a. HasHeaders a => CI ByteString -> ByteString -> a -> a
setHeader CI ByteString
"Location" ByteString
target Response
r
{-# INLINE redirect' #-}
logError :: MonadSnap m => ByteString -> m ()
logError :: forall (m :: * -> *). MonadSnap m => ByteString -> m ()
logError ByteString
s = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \() -> SnapState -> IO r
sk Zero -> SnapState -> IO r
_ SnapState
st -> do
    SnapState -> ByteString -> IO ()
_snapLogError SnapState
st ByteString
s
    () -> SnapState -> IO r
sk () SnapState
st
{-# INLINE logError #-}
addToOutput :: MonadSnap m
            => (OutputStream Builder -> IO (OutputStream Builder))
                    
            -> m ()
addToOutput :: forall (m :: * -> *).
MonadSnap m =>
(OutputStream Builder -> IO (OutputStream Builder)) -> m ()
addToOutput OutputStream Builder -> IO (OutputStream Builder)
enum = forall (m :: * -> *). MonadSnap m => (Response -> Response) -> m ()
modifyResponse forall a b. (a -> b) -> a -> b
$ ((OutputStream Builder -> IO (OutputStream Builder))
 -> OutputStream Builder -> IO (OutputStream Builder))
-> Response -> Response
modifyResponseBody (forall {m :: * -> *} {a} {b} {t}.
Monad m =>
(a -> m b) -> (t -> m a) -> t -> m b
c OutputStream Builder -> IO (OutputStream Builder)
enum)
  where
    c :: (a -> m b) -> (t -> m a) -> t -> m b
c a -> m b
a t -> m a
b = \t
out -> t -> m a
b t
out forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> m b
a
writeBuilder :: MonadSnap m => Builder -> m ()
writeBuilder :: forall (m :: * -> *). MonadSnap m => Builder -> m ()
writeBuilder Builder
b = forall (m :: * -> *).
MonadSnap m =>
(OutputStream Builder -> IO (OutputStream Builder)) -> m ()
addToOutput OutputStream Builder -> IO (OutputStream Builder)
f
  where
    f :: OutputStream Builder -> IO (OutputStream Builder)
f OutputStream Builder
str = forall a. Maybe a -> OutputStream a -> IO ()
Streams.write (forall a. a -> Maybe a
Just Builder
b) OutputStream Builder
str forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return OutputStream Builder
str
{-# INLINE writeBuilder #-}
writeBS :: MonadSnap m => ByteString -> m ()
writeBS :: forall (m :: * -> *). MonadSnap m => ByteString -> m ()
writeBS = forall (m :: * -> *). MonadSnap m => Builder -> m ()
writeBuilder forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
byteString
{-# INLINE writeBS #-}
writeLBS :: MonadSnap m => L.ByteString -> m ()
writeLBS :: forall (m :: * -> *). MonadSnap m => ByteString -> m ()
writeLBS = forall (m :: * -> *). MonadSnap m => Builder -> m ()
writeBuilder forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
lazyByteString
{-# INLINE writeLBS #-}
writeText :: MonadSnap m => T.Text -> m ()
writeText :: forall (m :: * -> *). MonadSnap m => Text -> m ()
writeText = forall (m :: * -> *). MonadSnap m => ByteString -> m ()
writeBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8
  
  
{-# INLINE writeText #-}
writeLazyText :: MonadSnap m => LT.Text -> m ()
writeLazyText :: forall (m :: * -> *). MonadSnap m => Text -> m ()
writeLazyText = forall (m :: * -> *). MonadSnap m => ByteString -> m ()
writeLBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
LT.encodeUtf8
{-# INLINE writeLazyText #-}
sendFile :: (MonadSnap m) => FilePath -> m ()
sendFile :: forall (m :: * -> *). MonadSnap m => String -> m ()
sendFile String
f = forall (m :: * -> *). MonadSnap m => (Response -> Response) -> m ()
modifyResponse forall a b. (a -> b) -> a -> b
$ \Response
r -> Response
r { rspBody :: ResponseBody
rspBody = String -> Maybe (Word64, Word64) -> ResponseBody
SendFile String
f forall a. Maybe a
Nothing }
sendFilePartial :: (MonadSnap m) => FilePath -> (Word64, Word64) -> m ()
sendFilePartial :: forall (m :: * -> *).
MonadSnap m =>
String -> (Word64, Word64) -> m ()
sendFilePartial String
f (Word64, Word64)
rng = forall (m :: * -> *). MonadSnap m => (Response -> Response) -> m ()
modifyResponse forall a b. (a -> b) -> a -> b
$ \Response
r ->
                        Response
r { rspBody :: ResponseBody
rspBody = String -> Maybe (Word64, Word64) -> ResponseBody
SendFile String
f (forall a. a -> Maybe a
Just (Word64, Word64)
rng) }
localRequest :: MonadSnap m => (Request -> Request) -> m a -> m a
localRequest :: forall (m :: * -> *) a.
MonadSnap m =>
(Request -> Request) -> m a -> m a
localRequest Request -> Request
f m a
m = do
    Request
req <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    Request -> m a
runAct Request
req forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall (m :: * -> *). MonadSnap m => Request -> m ()
putRequest Request
req forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. MonadSnap m => m a
pass)
  where
    runAct :: Request -> m a
runAct Request
req = do
        forall (m :: * -> *). MonadSnap m => (Request -> Request) -> m ()
modifyRequest Request -> Request
f
        a
result <- m a
m
        forall (m :: * -> *). MonadSnap m => Request -> m ()
putRequest Request
req
        forall (m :: * -> *) a. Monad m => a -> m a
return a
result
{-# INLINE localRequest #-}
withRequest :: MonadSnap m => (Request -> m a) -> m a
withRequest :: forall (m :: * -> *) a. MonadSnap m => (Request -> m a) -> m a
withRequest = (forall (m :: * -> *). MonadSnap m => m Request
getRequest forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=)
{-# INLINE withRequest #-}
withResponse :: MonadSnap m => (Response -> m a) -> m a
withResponse :: forall (m :: * -> *) a. MonadSnap m => (Response -> m a) -> m a
withResponse = (forall (m :: * -> *). MonadSnap m => m Response
getResponse forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=)
{-# INLINE withResponse #-}
ipHeaderFilter :: MonadSnap m => m ()
 = forall (m :: * -> *). MonadSnap m => CI ByteString -> m ()
ipHeaderFilter' CI ByteString
"x-forwarded-for"
ipHeaderFilter' :: MonadSnap m => CI ByteString -> m ()
 CI ByteString
header = do
    Maybe ByteString
headerContents <- forall a. HasHeaders a => CI ByteString -> a -> Maybe ByteString
getHeader CI ByteString
header forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). MonadSnap m => m Request
getRequest
    let whitespace :: String
whitespace = [ Char
' ', Char
'\t', Char
'\r', Char
'\n' ]
        ipChrs :: String
ipChrs = Char
'.' forall a. a -> [a] -> [a]
: String
"0123456789"
        trim :: ((a -> Bool) -> t) -> t a -> t
trim (a -> Bool) -> t
f t a
s = (a -> Bool) -> t
f (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` t a
s)
        clean :: ByteString -> ByteString
clean = forall {t :: * -> *} {a} {t}.
(Foldable t, Eq a) =>
((a -> Bool) -> t) -> t a -> t
trim (Char -> Bool) -> ByteString -> ByteString
S.takeWhile String
ipChrs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {t :: * -> *} {a} {t}.
(Foldable t, Eq a) =>
((a -> Bool) -> t) -> t a -> t
trim (Char -> Bool) -> ByteString -> ByteString
S.dropWhile String
whitespace
        setIP :: ByteString -> m ()
setIP ByteString
ip = forall (m :: * -> *). MonadSnap m => (Request -> Request) -> m ()
modifyRequest forall a b. (a -> b) -> a -> b
$ \Request
rq -> Request
rq { rqClientAddr :: ByteString
rqClientAddr = ByteString -> ByteString
clean ByteString
ip }
    forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! ()) forall (m :: * -> *). MonadSnap m => ByteString -> m ()
setIP Maybe ByteString
headerContents
bracketSnap :: IO a -> (a -> IO b) -> (a -> Snap c) -> Snap c
bracketSnap :: forall a b c. IO a -> (a -> IO b) -> (a -> Snap c) -> Snap c
bracketSnap IO a
before a -> IO b
after a -> Snap c
thing = forall (m :: * -> *) b.
MonadBaseControl IO m =>
((forall a. m a -> m a) -> m b) -> m b
mask forall a b. (a -> b) -> a -> b
$ \forall a. Snap a -> Snap a
restore ->
                                 forall a. StateT SnapState IO (SnapResult a) -> Snap a
stateTToSnap forall a b. (a -> b) -> a -> b
$ do
    a
a <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
before
    let after' :: StateT SnapState IO b
after' = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ a -> IO b
after a
a
    SnapResult c
r <- forall a. Snap a -> StateT SnapState IO (SnapResult a)
snapToStateT (forall a. Snap a -> Snap a
restore forall a b. (a -> b) -> a -> b
$ a -> Snap c
thing a
a) forall (m :: * -> *) a b.
MonadBaseControl IO m =>
m a -> m b -> m a
`onException` StateT SnapState IO b
after'
    b
_ <- StateT SnapState IO b
after'
    forall (m :: * -> *) a. Monad m => a -> m a
return SnapResult c
r
data NoHandlerException = NoHandlerException String
   deriving (NoHandlerException -> NoHandlerException -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NoHandlerException -> NoHandlerException -> Bool
$c/= :: NoHandlerException -> NoHandlerException -> Bool
== :: NoHandlerException -> NoHandlerException -> Bool
$c== :: NoHandlerException -> NoHandlerException -> Bool
Eq, Typeable)
instance Show NoHandlerException where
    show :: NoHandlerException -> String
show (NoHandlerException String
e) = String
"No handler for request: failure was " forall a. [a] -> [a] -> [a]
++ String
e
instance Exception NoHandlerException
terminateConnection :: (Exception e, MonadSnap m) => e -> m a
terminateConnection :: forall e (m :: * -> *) a. (Exception e, MonadSnap m) => e -> m a
terminateConnection e
e =
    forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \a -> SnapState -> IO r
_ Zero -> SnapState -> IO r
fk -> Zero -> SnapState -> IO r
fk forall a b. (a -> b) -> a -> b
$ EscapeSnap -> Zero
EscapeSnap forall a b. (a -> b) -> a -> b
$ SomeException -> EscapeSnap
TerminateConnection
                                  forall a b. (a -> b) -> a -> b
$ forall e. Exception e => e -> SomeException
SomeException e
e
escapeHttp :: MonadSnap m =>
              EscapeHttpHandler
           -> m ()
escapeHttp :: forall (m :: * -> *). MonadSnap m => EscapeHttpHandler -> m ()
escapeHttp EscapeHttpHandler
h = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall a.
(forall r.
 (a -> SnapState -> IO r)
 -> (Zero -> SnapState -> IO r) -> SnapState -> IO r)
-> Snap a
Snap forall a b. (a -> b) -> a -> b
$ \() -> SnapState -> IO r
_ Zero -> SnapState -> IO r
fk SnapState
st -> Zero -> SnapState -> IO r
fk (EscapeSnap -> Zero
EscapeSnap forall a b. (a -> b) -> a -> b
$ EscapeHttpHandler -> EscapeSnap
EscapeHttp EscapeHttpHandler
h) SnapState
st
runSnap :: Snap a                   
        -> (ByteString -> IO ())    
        -> ((Int -> Int) -> IO ())  
        -> Request                  
        -> IO (Request, Response)
runSnap :: forall a.
Snap a
-> (ByteString -> IO ())
-> ((Int -> Int) -> IO ())
-> Request
-> IO (Request, Response)
runSnap (Snap forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m) ByteString -> IO ()
logerr (Int -> Int) -> IO ()
timeoutAction Request
req =
    forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m forall {m :: * -> *} {p}.
Monad m =>
p -> SnapState -> m (Request, Response)
ok Zero -> SnapState -> IO (Request, Response)
diediedie SnapState
ss
  where
    ok :: p -> SnapState -> m (Request, Response)
ok p
_ SnapState
st = forall (m :: * -> *) a. Monad m => a -> m a
return (SnapState -> Request
_snapRequest SnapState
st, SnapState -> Response
_snapResponse SnapState
st)
    diediedie :: Zero -> SnapState -> IO (Request, Response)
diediedie Zero
z !SnapState
st = do
        Response
resp <- case Zero
z of
                  Zero
PassOnProcessing     -> forall (m :: * -> *) a. Monad m => a -> m a
return Response
fourohfour
                  (EarlyTermination Response
x) -> forall (m :: * -> *) a. Monad m => a -> m a
return Response
x
                  (EscapeSnap EscapeSnap
e)       -> forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO EscapeSnap
e
        forall (m :: * -> *) a. Monad m => a -> m a
return (SnapState -> Request
_snapRequest SnapState
st, Response
resp)
    
    fourohfour :: Response
fourohfour = do
        Response -> Response
clearContentLength                  forall a b. (a -> b) -> a -> b
$
          Int -> ByteString -> Response -> Response
setResponseStatus Int
404 ByteString
"Not Found" forall a b. (a -> b) -> a -> b
$
          (OutputStream Builder -> IO (OutputStream Builder))
-> Response -> Response
setResponseBody OutputStream Builder -> IO (OutputStream Builder)
enum404           forall a b. (a -> b) -> a -> b
$
          Response
emptyResponse
    
    enum404 :: OutputStream Builder -> IO (OutputStream Builder)
enum404 OutputStream Builder
out = do
        InputStream Builder
is <- forall c. [c] -> IO (InputStream c)
Streams.fromList [Builder]
html
        forall a. InputStream a -> OutputStream a -> IO ()
Streams.connect InputStream Builder
is OutputStream Builder
out
        forall (m :: * -> *) a. Monad m => a -> m a
return OutputStream Builder
out
    
    html :: [Builder]
html = forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Builder
byteString [ ByteString
"<!DOCTYPE html>\n"
                          , ByteString
"<html>\n"
                          , ByteString
"<head>\n"
                          , ByteString
"<title>Not found</title>\n"
                          , ByteString
"</head>\n"
                          , ByteString
"<body>\n"
                          , ByteString
"<code>No handler accepted \""
                          , Request -> ByteString
rqURI Request
req
                          , ByteString
"\"</code>\n</body></html>"
                          ]
    
    dresp :: Response
dresp = Response
emptyResponse
    
    ss :: SnapState
ss = Request
-> Response
-> (ByteString -> IO ())
-> ((Int -> Int) -> IO ())
-> SnapState
SnapState Request
req Response
dresp ByteString -> IO ()
logerr (Int -> Int) -> IO ()
timeoutAction
{-# INLINE runSnap #-}
{-# INLINE fixupResponse #-}
fixupResponse :: Request -> Response -> IO Response
fixupResponse :: Request -> Response -> IO Response
fixupResponse Request
req Response
rsp = {-# SCC "fixupResponse" #-} do
    Response
rsp' <- case Response -> ResponseBody
rspBody Response
rsp of
              (Stream OutputStream Builder -> IO (OutputStream Builder)
_)                -> forall (m :: * -> *) a. Monad m => a -> m a
return Response
rsp
              (SendFile String
f Maybe (Word64, Word64)
Nothing)      -> String -> Response -> IO Response
setFileSize String
f Response
rsp
              (SendFile String
_ (Just (Word64
s,Word64
e))) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! Word64 -> Response -> Response
setContentLength (Word64
eforall a. Num a => a -> a -> a
-Word64
s) Response
rsp
    let !cl :: Maybe Word64
cl = if Bool
noBody then forall a. Maybe a
Nothing else Response -> Maybe Word64
rspContentLength Response
rsp'
    let rsp'' :: Response
rsp'' = if Bool
noBody
                  then Response
rsp' { rspBody :: ResponseBody
rspBody          = (OutputStream Builder -> IO (OutputStream Builder)) -> ResponseBody
Stream forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> a
id
                            , rspContentLength :: Maybe Word64
rspContentLength = forall a. Maybe a
Nothing
                            }
                  else Response
rsp'
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a. HasHeaders a => (Headers -> Headers) -> a -> a
updateHeaders ([(CI ByteString, ByteString)] -> Headers
H.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}.
IsString a =>
Maybe Word64 -> [(a, ByteString)] -> [(a, ByteString)]
addCL Maybe Word64
cl forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers -> [(CI ByteString, ByteString)]
H.toList) Response
rsp''
  where
    
    addCL :: Maybe Word64 -> [(a, ByteString)] -> [(a, ByteString)]
addCL Maybe Word64
Nothing [(a, ByteString)]
xs   = [(a, ByteString)]
xs
    addCL (Just Word64
cl) [(a, ByteString)]
xs = (a
"content-length", Word64 -> ByteString
word64ToByteString Word64
cl)forall a. a -> [a] -> [a]
:[(a, ByteString)]
xs
    
    setFileSize :: FilePath -> Response -> IO Response
    setFileSize :: String -> Response -> IO Response
setFileSize String
fp Response
r = {-# SCC "setFileSize" #-} do
        Word64
fs <- forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ String -> IO FileOffset
getFileSize String
fp
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! Response
r { rspContentLength :: Maybe Word64
rspContentLength = forall a. a -> Maybe a
Just Word64
fs }
    
    getFileSize :: FilePath -> IO FileOffset
    getFileSize :: String -> IO FileOffset
getFileSize String
fp = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM FileStatus -> FileOffset
fileSize forall a b. (a -> b) -> a -> b
$ String -> IO FileStatus
getFileStatus String
fp
    code :: Int
code   = Response -> Int
rspStatus Response
rsp
    noBody :: Bool
noBody = Int
code forall a. Eq a => a -> a -> Bool
== Int
204 Bool -> Bool -> Bool
|| Int
code forall a. Eq a => a -> a -> Bool
== Int
304 Bool -> Bool -> Bool
|| Request -> Method
rqMethod Request
req forall a. Eq a => a -> a -> Bool
== Method
HEAD
    
    fixup :: [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [] = []
    fixup ((CI ByteString
"date",ByteString
_):[(CI ByteString, ByteString)]
xs)           = [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [(CI ByteString, ByteString)]
xs
    fixup ((CI ByteString
"content-length",ByteString
_):[(CI ByteString, ByteString)]
xs) = [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [(CI ByteString, ByteString)]
xs
    fixup (x :: (CI ByteString, ByteString)
x@(CI ByteString
"transfer-encoding",ByteString
_):[(CI ByteString, ByteString)]
xs) = if Bool
noBody
                                             then [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [(CI ByteString, ByteString)]
xs
                                             else (CI ByteString, ByteString)
x forall a. a -> [a] -> [a]
: [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [(CI ByteString, ByteString)]
xs
    fixup ((CI ByteString, ByteString)
x:[(CI ByteString, ByteString)]
xs) = (CI ByteString, ByteString)
x forall a. a -> [a] -> [a]
: [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
fixup [(CI ByteString, ByteString)]
xs
{-# INLINE countDigits #-}
countDigits :: Word64 -> Int
countDigits :: Word64 -> Int
countDigits Word64
v0 = forall {t} {t}. (Num t, Integral t) => t -> t -> t
go Int
1 Word64
v0
  where go :: t -> t -> t
go !t
k t
v
           | t
v forall a. Ord a => a -> a -> Bool
< t
10    = t
k
           | t
v forall a. Ord a => a -> a -> Bool
< t
100   = t
k forall a. Num a => a -> a -> a
+ t
1
           | t
v forall a. Ord a => a -> a -> Bool
< t
1000  = t
k forall a. Num a => a -> a -> a
+ t
2
           | t
v forall a. Ord a => a -> a -> Bool
< t
10000 = t
k forall a. Num a => a -> a -> a
+ t
3
           | Bool
otherwise = t -> t -> t
go (t
kforall a. Num a => a -> a -> a
+t
4) (t
v forall a. Integral a => a -> a -> a
`quot` t
10000)
{-# INLINE word64ToByteString #-}
word64ToByteString :: Word64 -> ByteString
word64ToByteString :: Word64 -> ByteString
word64ToByteString Word64
d =
#if !MIN_VERSION_bytestring(0,10,6)
    S.inlinePerformIO $
#else
    forall a. IO a -> a
S.accursedUnutterablePerformIO forall a b. (a -> b) -> a -> b
$
#endif
    if Word64
d forall a. Ord a => a -> a -> Bool
< Word64
10
       then Int -> (Ptr Word8 -> IO ()) -> IO ByteString
S.create Int
1 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
p (Word64 -> Word8
i2w Word64
d)
       else let !n :: Int
n = Word64 -> Int
countDigits Word64
d
            in Int -> (Ptr Word8 -> IO ()) -> IO ByteString
S.create Int
n forall a b. (a -> b) -> a -> b
$ Int -> Word64 -> Ptr Word8 -> IO ()
posDecimal Int
n Word64
d
{-# INLINE posDecimal #-}
posDecimal :: Int -> Word64 -> Ptr Word8 -> IO ()
posDecimal :: Int -> Word64 -> Ptr Word8 -> IO ()
posDecimal !Int
n0 !Word64
v0 !Ptr Word8
op0 = forall {t}. (Eq t, Num t) => t -> Ptr Word8 -> Word64 -> IO ()
go Int
n0 (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
op0 (Int
n0forall a. Num a => a -> a -> a
-Int
1)) Word64
v0
  where go :: t -> Ptr Word8 -> Word64 -> IO ()
go !t
n !Ptr Word8
op !Word64
v
          | t
n forall a. Eq a => a -> a -> Bool
== t
1 = forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
op forall a b. (a -> b) -> a -> b
$! Word64 -> Word8
i2w Word64
v
          | Bool
otherwise = do
              let (!Word64
v', !Word64
d) = forall a. Integral a => a -> a -> (a, a)
divMod Word64
v Word64
10
              forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
op forall a b. (a -> b) -> a -> b
$! Word64 -> Word8
i2w Word64
d
              t -> Ptr Word8 -> Word64 -> IO ()
go (t
nforall a. Num a => a -> a -> a
-t
1) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
op (-Int
1)) Word64
v'
{-# INLINE i2w #-}
i2w :: Word64 -> Word8
i2w :: Word64 -> Word8
i2w Word64
v = Word8
48 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
v
evalSnap :: Snap a                  
         -> (ByteString -> IO ())   
         -> ((Int -> Int) -> IO ()) 
         -> Request                 
         -> IO a
evalSnap :: forall a.
Snap a
-> (ByteString -> IO ())
-> ((Int -> Int) -> IO ())
-> Request
-> IO a
evalSnap (Snap forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m) ByteString -> IO ()
logerr (Int -> Int) -> IO ()
timeoutAction Request
req =
    forall r.
(a -> SnapState -> IO r)
-> (Zero -> SnapState -> IO r) -> SnapState -> IO r
m (\a
v SnapState
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return a
v) forall {m :: * -> *} {p} {a}. MonadBase IO m => Zero -> p -> m a
diediedie SnapState
ss
  where
    diediedie :: Zero -> p -> m a
diediedie Zero
z p
_ = case Zero
z of
      Zero
PassOnProcessing     -> forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO forall a b. (a -> b) -> a -> b
$ String -> NoHandlerException
NoHandlerException String
"pass"
      (EarlyTermination Response
_) -> forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO forall a b. (a -> b) -> a -> b
$ String -> ErrorCall
ErrorCall String
"no value"
      (EscapeSnap EscapeSnap
e)       -> forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO EscapeSnap
e
    dresp :: Response
dresp = Response
emptyResponse
    ss :: SnapState
ss = Request
-> Response
-> (ByteString -> IO ())
-> ((Int -> Int) -> IO ())
-> SnapState
SnapState Request
req Response
dresp ByteString -> IO ()
logerr (Int -> Int) -> IO ()
timeoutAction
{-# INLINE evalSnap #-}
getParamFrom :: MonadSnap m =>
                (ByteString -> Request -> Maybe [ByteString])
             -> ByteString
             -> m (Maybe ByteString)
getParamFrom :: forall (m :: * -> *).
MonadSnap m =>
(ByteString -> Request -> Maybe [ByteString])
-> ByteString -> m (Maybe ByteString)
getParamFrom ByteString -> Request -> Maybe [ByteString]
f ByteString
k = do
    Request
rq <- forall (m :: * -> *). MonadSnap m => m Request
getRequest
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (ByteString -> [ByteString] -> ByteString
S.intercalate ByteString
" ") forall a b. (a -> b) -> a -> b
$ ByteString -> Request -> Maybe [ByteString]
f ByteString
k Request
rq
{-# INLINE getParamFrom #-}
getParam :: MonadSnap m
         => ByteString          
         -> m (Maybe ByteString)
getParam :: forall (m :: * -> *).
MonadSnap m =>
ByteString -> m (Maybe ByteString)
getParam = forall (m :: * -> *).
MonadSnap m =>
(ByteString -> Request -> Maybe [ByteString])
-> ByteString -> m (Maybe ByteString)
getParamFrom ByteString -> Request -> Maybe [ByteString]
rqParam
{-# INLINE getParam #-}
getPostParam :: MonadSnap m
             => ByteString          
             -> m (Maybe ByteString)
getPostParam :: forall (m :: * -> *).
MonadSnap m =>
ByteString -> m (Maybe ByteString)
getPostParam = forall (m :: * -> *).
MonadSnap m =>
(ByteString -> Request -> Maybe [ByteString])
-> ByteString -> m (Maybe ByteString)
getParamFrom ByteString -> Request -> Maybe [ByteString]
rqPostParam
{-# INLINE getPostParam #-}
getQueryParam :: MonadSnap m
              => ByteString          
              -> m (Maybe ByteString)
getQueryParam :: forall (m :: * -> *).
MonadSnap m =>
ByteString -> m (Maybe ByteString)
getQueryParam = forall (m :: * -> *).
MonadSnap m =>
(ByteString -> Request -> Maybe [ByteString])
-> ByteString -> m (Maybe ByteString)
getParamFrom ByteString -> Request -> Maybe [ByteString]
rqQueryParam
{-# INLINE getQueryParam #-}
getParams :: MonadSnap m => m Params
getParams :: forall (m :: * -> *). MonadSnap m => m Params
getParams = forall (m :: * -> *). MonadSnap m => m Request
getRequest forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> Params
rqParams
getPostParams :: MonadSnap m => m Params
getPostParams :: forall (m :: * -> *). MonadSnap m => m Params
getPostParams = forall (m :: * -> *). MonadSnap m => m Request
getRequest forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> Params
rqPostParams
getQueryParams :: MonadSnap m => m Params
getQueryParams :: forall (m :: * -> *). MonadSnap m => m Params
getQueryParams = forall (m :: * -> *). MonadSnap m => m Request
getRequest forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> Params
rqQueryParams
getCookie :: MonadSnap m
          => ByteString
          -> m (Maybe Cookie)
getCookie :: forall (m :: * -> *). MonadSnap m => ByteString -> m (Maybe Cookie)
getCookie ByteString
name = forall (m :: * -> *) a. MonadSnap m => (Request -> m a) -> m a
withRequest forall a b. (a -> b) -> a -> b
$
    forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe a
listToMaybe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (\Cookie
c -> Cookie -> ByteString
cookieName Cookie
c forall a. Eq a => a -> a -> Bool
== ByteString
name) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> [Cookie]
rqCookies
readCookie :: (MonadSnap m, R.Readable a)
           => ByteString
           -> m a
readCookie :: forall (m :: * -> *) a.
(MonadSnap m, Readable a) =>
ByteString -> m a
readCookie ByteString
name = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (m :: * -> *) a. MonadSnap m => m a
pass (forall a (m :: * -> *).
(Readable a, MonadPlus m) =>
ByteString -> m a
R.fromBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cookie -> ByteString
cookieValue) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *). MonadSnap m => ByteString -> m (Maybe Cookie)
getCookie ByteString
name
expireCookie :: (MonadSnap m) => Cookie -> m ()
expireCookie :: forall (m :: * -> *). MonadSnap m => Cookie -> m ()
expireCookie Cookie
cookie = do
  let old :: UTCTime
old = Day -> DiffTime -> UTCTime
UTCTime (Integer -> Day
ModifiedJulianDay Integer
0) DiffTime
0
  forall (m :: * -> *). MonadSnap m => (Response -> Response) -> m ()
modifyResponse forall a b. (a -> b) -> a -> b
$ Cookie -> Response -> Response
addResponseCookie
                 forall a b. (a -> b) -> a -> b
$ Cookie
cookie { cookieValue :: ByteString
cookieValue = ByteString
""
                          , cookieExpires :: Maybe UTCTime
cookieExpires = (forall a. a -> Maybe a
Just UTCTime
old) }
setTimeout :: MonadSnap m => Int -> m ()
setTimeout :: forall (m :: * -> *). MonadSnap m => Int -> m ()
setTimeout = forall (m :: * -> *). MonadSnap m => (Int -> Int) -> m ()
modifyTimeout forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const
extendTimeout :: MonadSnap m => Int -> m ()
extendTimeout :: forall (m :: * -> *). MonadSnap m => Int -> m ()
extendTimeout = forall (m :: * -> *). MonadSnap m => (Int -> Int) -> m ()
modifyTimeout forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
max
modifyTimeout :: MonadSnap m => (Int -> Int) -> m ()
modifyTimeout :: forall (m :: * -> *). MonadSnap m => (Int -> Int) -> m ()
modifyTimeout Int -> Int
f = do
    (Int -> Int) -> IO ()
m <- forall (m :: * -> *). MonadSnap m => m ((Int -> Int) -> IO ())
getTimeoutModifier
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ (Int -> Int) -> IO ()
m Int -> Int
f
getTimeoutModifier :: MonadSnap m => m ((Int -> Int) -> IO ())
getTimeoutModifier :: forall (m :: * -> *). MonadSnap m => m ((Int -> Int) -> IO ())
getTimeoutModifier = forall (m :: * -> *) a. MonadSnap m => Snap a -> m a
liftSnap forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM SnapState -> (Int -> Int) -> IO ()
_snapModifyTimeout Snap SnapState
sget