second-transfer-0.4.0.0: hs-src/SecondTransfer/MainLoop/CoherentWorker.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FunctionalDependencies, FlexibleInstances, DeriveDataTypeable #-}
-- | A CoherentWorker is one that doesn't need to compute everything at once...
-- This one is simpler than the SPDY one, because it enforces certain order....
module SecondTransfer.MainLoop.CoherentWorker(
getHeaderFromFlatList
, HeaderName
, HeaderValue
, Header
, Headers
, FinalizationHeaders
, Request
, Footers
, CoherentWorker
, PrincipalStream
, PushedStreams
, PushedStream
, DataAndConclusion
, InputDataStream
, StreamCancelledException (..)
) where
import Control.Exception
import qualified Data.ByteString as B
import Data.Conduit
import Data.Foldable (find)
import Data.Typeable
-- | The name part of a header
type HeaderName = B.ByteString
-- | The value part of a header
type HeaderValue = B.ByteString
-- | The complete header
type Header = (HeaderName, HeaderValue)
-- |List of headers. The first part of each tuple is the header name
-- (be sure to conform to the HTTP/2 convention of using lowercase)
-- and the second part is the headers contents. This list needs to include
-- the special :method, :scheme, :authority and :path pseudo-headers for
-- requests; and :status (with a plain numeric value represented in ascii digits)
-- for responses.
type Headers = [Header]
-- |This is a Source conduit (see Haskell Data.Conduit library from Michael Snoyman)
-- that you can use to retrieve the data sent by the client piece-wise.
type InputDataStream = Source IO B.ByteString
-- | A request is a set of headers and a request body....
-- which will normally be empty, except for POST and PUT requests. But
-- this library enforces none of that.
type Request = (Headers, Maybe InputDataStream)
-- | Finalization headers. If you don't know what they are, chances are
-- that you don't need to worry about them for now. The support in this
-- library for those are at best sketchy.
type FinalizationHeaders = Headers
-- | Finalization headers
type Footers = FinalizationHeaders
-- | You use this type to answer a request. The `Headers` are thus response
-- headers and they should contain the :status pseudo-header. The `PushedStreams`
-- is a list of pushed streams...(I don't thaink that I'm handling those yet)
type PrincipalStream = (Headers, PushedStreams, DataAndConclusion)
-- | A source-like conduit with the data returned in the response. The
-- return value of the conduit is a list of footers. For now that list can
-- be anything (even bottom), I'm not handling it just yet.
type DataAndConclusion = ConduitM () B.ByteString IO Footers
-- | Main type of this library. You implement one of these for your server.
-- Basically this is a callback that the library calls as soon as it has
-- all the headers of a request. For GET requests that's the entire request
-- basically, but for POST and PUT requests this is just before the data
-- starts arriving to the server.
type CoherentWorker = Request -> IO PrincipalStream
-- | This exception will be raised inside a `CoherentWorker` when the underlying
-- stream is cancelled (STREAM_RESET in HTTP\/2). Do any necessary cleanup
-- in a handler, or simply use the fact that the exception is asynchronously
-- delivered
-- to your CoherentWorker Haskell thread, giving you an opportunity to
-- interrupt any blocked operations.
data StreamCancelledException = StreamCancelledException
deriving (Show, Typeable)
instance Exception StreamCancelledException
-- | A list of pushed streams
type PushedStreams = [ IO PushedStream ]
-- | A pushed stream, represented by a list of request headers,
-- a list of response headers, and the usual response body (which
-- may include final footers (not implemented yet)).
type PushedStream = (Headers, Headers, DataAndConclusion)
-- | Gets a single header from the list
getHeaderFromFlatList :: Headers -> B.ByteString -> Maybe B.ByteString
getHeaderFromFlatList unvl bs =
case find (\ (x,_) -> x==bs ) unvl of
Just (_, found_value) -> Just found_value
Nothing -> Nothing