-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/

-- | HTTP senmatics libarry
--   
--   Version-independent common parts of HTTP
@package http-semantics
@version 0.3.0

module Network.HTTP.Semantics.Server.Internal

-- | Request from client.
newtype Request
Request :: InpObj -> Request

-- | Response from server.
newtype Response
Response :: OutObj -> Response

-- | Additional information.
data Aux
Aux :: Handle -> SockAddr -> SockAddr -> Aux

-- | Time handle for the worker processing this request and response.
[auxTimeHandle] :: Aux -> Handle

-- | Local socket address copied from Config.
[auxMySockAddr] :: Aux -> SockAddr

-- | Remove socket address copied from Config.
[auxPeerSockAddr] :: Aux -> SockAddr
instance GHC.Internal.Show.Show Network.HTTP.Semantics.Server.Internal.Request
instance GHC.Internal.Show.Show Network.HTTP.Semantics.Server.Internal.Response

module Network.HTTP.Semantics.Client.Internal

-- | Request from client.
newtype Request
Request :: OutObj -> Request

-- | Response from server.
newtype Response
Response :: InpObj -> Response

-- | Additional information.
data Aux
Aux :: IO Int -> Aux

-- | How many streams can be created without blocking.
[auxPossibleClientStreams] :: Aux -> IO Int
instance GHC.Internal.Show.Show Network.HTTP.Semantics.Client.Internal.Request
instance GHC.Internal.Show.Show Network.HTTP.Semantics.Client.Internal.Response

-- | Library for HTTP Semantics (RFC9110), version-independent
--   common parts. For low-level headers, Token is used. For
--   upper-level headers, HeaderName should be used.
module Network.HTTP.Semantics

-- | How many bytes to read
type ByteCount = Int64

-- | Offset for file.
type FileOffset = Int64
data OutBodyIface
OutBodyIface :: (forall x. () => IO x -> IO x) -> (Builder -> IO ()) -> (Builder -> IO ()) -> (Maybe SomeException -> IO ()) -> IO () -> OutBodyIface

-- | Unmask exceptions in the thread spawned for the request body
--   
--   This is used in the client: we spawn the new thread for the request
--   body with exceptions masked, and provide the body of
--   OutBodyStreamingIface with a callback to unmask them again
--   (typically after installing an exception handler).
--   
--   Unmasking in the server is a no-op, as here the scope of the thread
--   that is spawned for the server is the entire handler, not just the
--   response streaming body.
[outBodyUnmask] :: OutBodyIface -> forall x. () => IO x -> IO x

-- | Push a new chunk
--   
--   In http2, there is no direct correspondence between chunks
--   and the resulting DATA frames sent: the chunks are collected
--   (written to an internal write buffer) until we can fill a frame.
--   
--   See also outBodyFlush.
[outBodyPush] :: OutBodyIface -> Builder -> IO ()

-- | Push the final chunk
--   
--   Using this function instead of outBodyPush can be used to
--   guarantee that the final HTTP2 DATA frame is marked end-of-stream;
--   with outBodyPush it may happen that an additional empty DATA
--   frame is used for this purpose. Additionally, after calling this
--   function, outBodyCancel will be a no-op.
[outBodyPushFinal] :: OutBodyIface -> Builder -> IO ()

-- | Cancel the stream
--   
--   Sends a RST_STREAM to the peer. If cancelling as the result
--   of an exception, a Just should be provided which specifies the
--   exception which will be stored locally as the reason for cancelling
--   the stream; in this case, the error code sent with the
--   RST_STREAM will be INTERNAL_ERROR (see
--   https://datatracker.ietf.org/doc/html/rfc7540#section-7). If
--   Nothing is given, the error code will be CANCEL.
--   
--   If there is a partially constructed DATA frame at the time of
--   cancellation, this frame is discarded. If this is undesirable, you
--   should call outBodyFlush prior to cancelling.
[outBodyCancel] :: OutBodyIface -> Maybe SomeException -> IO ()

-- | Flush
--   
--   This can be used to emit a DATA frame with the data collected so far
--   (using outBodyPush), even if that DATA frame has not yet
--   reached the maximum frame size. Calling outBodyFlush
--   unnecessarily can therefore result in excessive overhead from frame
--   headers.
--   
--   If no data is available to send, this is a no-op.
[outBodyFlush] :: OutBodyIface -> IO ()

-- | Trailers maker. A chunks of the response body is passed with
--   Just. The maker should update internal state with the
--   ByteString and return the next trailers maker. When response
--   body reaches its end, Nothing is passed and the maker should
--   generate trailers. An example:
--   
--   
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   
--   
--   Usage example:
--   
--   
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | "http" or "https".
type Scheme = ByteString

-- | Authority.
type Authority = String

-- | Path.
type Path = ByteString

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec

-- | Input object
data InpObj
InpObj :: TokenHeaderTable -> Maybe Int -> InpBody -> IORef (Maybe TokenHeaderTable) -> InpObj

-- | Accessor for headers.
[inpObjHeaders] :: InpObj -> TokenHeaderTable

-- | Accessor for body length specified in content-length:.
[inpObjBodySize] :: InpObj -> Maybe Int

-- | Accessor for body.
[inpObjBody] :: InpObj -> InpBody

-- | Accessor for trailers.
[inpObjTrailers] :: InpObj -> IORef (Maybe TokenHeaderTable)

-- | Output object
data OutObj
OutObj :: [Header] -> OutBody -> TrailersMaker -> OutObj

-- | Accessor for header.
[outObjHeaders] :: OutObj -> [Header]

-- | Accessor for outObj body.
[outObjBody] :: OutObj -> OutBody

-- | Accessor for trailers maker.
[outObjTrailers] :: OutObj -> TrailersMaker
type InpBody = IO (ByteString, Bool)
data OutBody
OutBodyNone :: OutBody

-- | Streaming body takes a write action and a flush action.
OutBodyStreaming :: ((Builder -> IO ()) -> IO () -> IO ()) -> OutBody

-- | Generalization of OutBodyStreaming.
OutBodyStreamingIface :: (OutBodyIface -> IO ()) -> OutBody
OutBodyBuilder :: Builder -> OutBody
OutBodyFile :: FileSpec -> OutBody

-- | Field name. Internal usage only.
type FieldName = ByteString

-- | Field value.
type FieldValue = ByteString

-- | TokenBased header.
type TokenHeader = (Token, FieldValue)

-- | TokenBased header list.
type TokenHeaderList = [TokenHeader]

-- | A pair of token list and value table.
type TokenHeaderTable = (TokenHeaderList, ValueTable)

-- | An array to get FieldValue quickly. getHeaderValue
--   should be used. Internally, the key is tokenIx.
type ValueTable = Array Int Maybe FieldValue

-- | Accessing FieldValue with Token.
getFieldValue :: Token -> ValueTable -> Maybe FieldValue

-- | A pair of token list and value table.

-- | Deprecated: use TokenHeaderTable instead
type HeaderTable = (TokenHeaderList, ValueTable)

-- | Header value.

-- | Deprecated: use FieldValue instead
type HeaderValue = ByteString

-- | Accessing FieldValue with Token.

-- | Deprecated: use geFieldValue instead
getHeaderValue :: Token -> ValueTable -> Maybe FieldValue

-- | Internal representation for header keys.
data Token
Token :: Int -> Bool -> Bool -> HeaderName -> Token

-- | Index for value table
[tokenIx] :: Token -> Int

-- | should be indexed in HPACK
[shouldBeIndexed] :: Token -> Bool

-- | is this a pseudo header key?
[isPseudo] :: Token -> Bool

-- | Case insensitive header key
[tokenKey] :: Token -> HeaderName

-- | Extracting a case insensitive header key from a token.
tokenCIKey :: Token -> ByteString

-- | Extracting a folded header key from a token.
tokenFoldedKey :: Token -> ByteString

-- | Making a token from a header key.
--   
--   
--   >>> toToken ":authority" == tokenAuthority
--   True
--   
--   >>> toToken "foo"
--   Token {tokenIx = 73, shouldBeIndexed = True, isPseudo = False, tokenKey = "foo"}
--   
--   >>> toToken ":bar"
--   Token {tokenIx = 73, shouldBeIndexed = True, isPseudo = True, tokenKey = ":bar"}
--   
toToken :: ByteString -> Token

-- | Minimum token index.
minTokenIx :: Int

-- | Maximun token index defined in the static table.
maxStaticTokenIx :: Int

-- | Maximum token index.
maxTokenIx :: Int

-- | Token index for tokenCookie.
cookieTokenIx :: Int

-- | Is this token ix to be held in the place holder?
isMaxTokenIx :: Int -> Bool

-- | Is this token ix for Cookie?
isCookieTokenIx :: Int -> Bool

-- | Is this token ix for a header not defined in the static table?
isStaticTokenIx :: Int -> Bool

-- | Is this token for a header not defined in the static table?
isStaticToken :: Token -> Bool
tokenAuthority :: Token
tokenMethod :: Token
tokenPath :: Token
tokenScheme :: Token
tokenStatus :: Token
tokenAcceptCharset :: Token
tokenAcceptEncoding :: Token
tokenAcceptLanguage :: Token
tokenAcceptRanges :: Token
tokenAccept :: Token
tokenAccessControlAllowOrigin :: Token
tokenAge :: Token
tokenAllow :: Token
tokenAuthorization :: Token
tokenCacheControl :: Token
tokenContentDisposition :: Token
tokenContentEncoding :: Token
tokenContentLanguage :: Token
tokenContentLength :: Token
tokenContentLocation :: Token
tokenContentRange :: Token
tokenContentType :: Token
tokenCookie :: Token
tokenDate :: Token
tokenEtag :: Token
tokenExpect :: Token
tokenExpires :: Token
tokenFrom :: Token
tokenHost :: Token
tokenIfMatch :: Token
tokenIfModifiedSince :: Token
tokenIfNoneMatch :: Token
tokenIfRange :: Token
tokenIfUnmodifiedSince :: Token
tokenLastModified :: Token
tokenLink :: Token
tokenLocation :: Token
tokenMaxForwards :: Token
tokenProxyAuthenticate :: Token
tokenProxyAuthorization :: Token
tokenRange :: Token
tokenReferer :: Token
tokenRefresh :: Token
tokenRetryAfter :: Token
tokenServer :: Token
tokenSetCookie :: Token
tokenStrictTransportSecurity :: Token
tokenTransferEncoding :: Token
tokenUserAgent :: Token
tokenVary :: Token
tokenVia :: Token
tokenWwwAuthenticate :: Token

-- | A place holder to hold header keys not defined in the static table. |
--   For Warp
tokenConnection :: Token
tokenTE :: Token
tokenMax :: Token

-- | For QPACK
tokenAccessControlAllowCredentials :: Token
tokenAccessControlAllowHeaders :: Token
tokenAccessControlAllowMethods :: Token
tokenAccessControlExposeHeaders :: Token
tokenAccessControlRequestHeaders :: Token
tokenAccessControlRequestMethod :: Token
tokenAltSvc :: Token
tokenContentSecurityPolicy :: Token
tokenEarlyData :: Token
tokenExpectCt :: Token
tokenForwarded :: Token
tokenOrigin :: Token
tokenPurpose :: Token
tokenTimingAllowOrigin :: Token
tokenUpgradeInsecureRequests :: Token
tokenXContentTypeOptions :: Token
tokenXForwardedFor :: Token
tokenXFrameOptions :: Token
tokenXXssProtection :: Token

module Network.HTTP.Semantics.Server

-- | Server type. Server takes a HTTP request, should generate a HTTP
--   response and push promises, then should give them to the sending
--   function. The sending function would throw exceptions so that they can
--   be logged.
--   
--   The sending function must only be called once.
type Server = Request -> Aux -> Response -> [PushPromise] -> IO () -> IO ()

-- | Request from client.
data Request

-- | Getting the method from a request.
requestMethod :: Request -> Maybe Method

-- | Getting the path from a request.
requestPath :: Request -> Maybe Path

-- | Getting the authority from a request.
requestAuthority :: Request -> Maybe Authority

-- | Getting the scheme from a request.
requestScheme :: Request -> Maybe Scheme

-- | Getting the headers from a request.
requestHeaders :: Request -> TokenHeaderTable

-- | Getting the body size from a request.
requestBodySize :: Request -> Maybe Int

-- | Reading a chunk of the request body. An empty ByteString
--   returned when finished.
getRequestBodyChunk :: Request -> IO ByteString

-- | Generalization of getRequestBodyChunk which also returns if the
--   ByteString is the final one
getRequestBodyChunk' :: Request -> IO (ByteString, Bool)

-- | Reading request trailers. This function must be called after
--   getRequestBodyChunk returns an empty.
getRequestTrailers :: Request -> IO (Maybe TokenHeaderTable)

-- | Additional information.
data Aux

-- | Time handle for the worker processing this request and response.
auxTimeHandle :: Aux -> Handle

-- | Local socket address copied from Config.
auxMySockAddr :: Aux -> SockAddr

-- | Remove socket address copied from Config.
auxPeerSockAddr :: Aux -> SockAddr

-- | Response from server.
data Response

-- | Creating response without body.
responseNoBody :: Status -> ResponseHeaders -> Response

-- | Creating response with file.
responseFile :: Status -> ResponseHeaders -> FileSpec -> Response

-- | Creating response with streaming.
responseStreaming :: Status -> ResponseHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Response

-- | Creating response with builder.
responseBuilder :: Status -> ResponseHeaders -> Builder -> Response
data OutBodyIface
OutBodyIface :: (forall x. () => IO x -> IO x) -> (Builder -> IO ()) -> (Builder -> IO ()) -> (Maybe SomeException -> IO ()) -> IO () -> OutBodyIface

-- | Unmask exceptions in the thread spawned for the request body
--   
--   This is used in the client: we spawn the new thread for the request
--   body with exceptions masked, and provide the body of
--   OutBodyStreamingIface with a callback to unmask them again
--   (typically after installing an exception handler).
--   
--   Unmasking in the server is a no-op, as here the scope of the thread
--   that is spawned for the server is the entire handler, not just the
--   response streaming body.
[outBodyUnmask] :: OutBodyIface -> forall x. () => IO x -> IO x

-- | Push a new chunk
--   
--   In http2, there is no direct correspondence between chunks
--   and the resulting DATA frames sent: the chunks are collected
--   (written to an internal write buffer) until we can fill a frame.
--   
--   See also outBodyFlush.
[outBodyPush] :: OutBodyIface -> Builder -> IO ()

-- | Push the final chunk
--   
--   Using this function instead of outBodyPush can be used to
--   guarantee that the final HTTP2 DATA frame is marked end-of-stream;
--   with outBodyPush it may happen that an additional empty DATA
--   frame is used for this purpose. Additionally, after calling this
--   function, outBodyCancel will be a no-op.
[outBodyPushFinal] :: OutBodyIface -> Builder -> IO ()

-- | Cancel the stream
--   
--   Sends a RST_STREAM to the peer. If cancelling as the result
--   of an exception, a Just should be provided which specifies the
--   exception which will be stored locally as the reason for cancelling
--   the stream; in this case, the error code sent with the
--   RST_STREAM will be INTERNAL_ERROR (see
--   https://datatracker.ietf.org/doc/html/rfc7540#section-7). If
--   Nothing is given, the error code will be CANCEL.
--   
--   If there is a partially constructed DATA frame at the time of
--   cancellation, this frame is discarded. If this is undesirable, you
--   should call outBodyFlush prior to cancelling.
[outBodyCancel] :: OutBodyIface -> Maybe SomeException -> IO ()

-- | Flush
--   
--   This can be used to emit a DATA frame with the data collected so far
--   (using outBodyPush), even if that DATA frame has not yet
--   reached the maximum frame size. Calling outBodyFlush
--   unnecessarily can therefore result in excessive overhead from frame
--   headers.
--   
--   If no data is available to send, this is a no-op.
[outBodyFlush] :: OutBodyIface -> IO ()

-- | Generalization of responseStreaming.
responseStreamingIface :: Status -> ResponseHeaders -> (OutBodyIface -> IO ()) -> Response

-- | Getter for response body size. This value is available for file body.
responseBodySize :: Response -> Maybe Int

-- | Trailers maker. A chunks of the response body is passed with
--   Just. The maker should update internal state with the
--   ByteString and return the next trailers maker. When response
--   body reaches its end, Nothing is passed and the maker should
--   generate trailers. An example:
--   
--   
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   
--   
--   Usage example:
--   
--   
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Setting TrailersMaker to Response.
setResponseTrailersMaker :: Response -> TrailersMaker -> Response

-- | HTTP/2 push promise or sever push. Pseudo REQUEST headers in push
--   promise is automatically generated. Then, a server push is sent
--   according to promiseResponse.
data PushPromise
PushPromise :: ByteString -> Response -> PushPromise

-- | Accessor for a URL path in a push promise (a virtual request from a
--   server). E.g. "/style/default.css".
[promiseRequestPath] :: PushPromise -> ByteString

-- | Accessor for response actually pushed from a server.
[promiseResponse] :: PushPromise -> Response

-- | Creating push promise. The third argument is traditional, not used.
pushPromise :: ByteString -> Response -> Int -> PushPromise

-- | Path.
type Path = ByteString

-- | Authority.
type Authority = String

-- | "http" or "https".
type Scheme = ByteString

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec

-- | Offset for file.
type FileOffset = Int64

-- | How many bytes to read
type ByteCount = Int64

-- | Reading n bytes.
type ReadN = Int -> IO ByteString

-- | Naive implementation for readN.
--   
--   NOTE: This function is intended to be used by a single thread
--   only. (It is probably quite rare anyway to want concurrent reads from
--   the same network socket.)
defaultReadN :: Socket -> IORef (Maybe ByteString) -> ReadN

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Position read based on Handle.
defaultPositionReadMaker :: PositionReadMaker

module Network.HTTP.Semantics.Client

-- | Client type.
type Client a = SendRequest -> Aux -> IO a

-- | Send a request and receive its response.
type SendRequest = forall r. () => Request -> Response -> IO r -> IO r

-- | Request from client.
data Request

-- | Creating request without body.
requestNoBody :: Method -> Path -> RequestHeaders -> Request

-- | Creating request with file.
requestFile :: Method -> Path -> RequestHeaders -> FileSpec -> Request

-- | Creating request with streaming.
requestStreaming :: Method -> Path -> RequestHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Request

-- | Like requestStreaming, but run the action with exceptions
--   masked
requestStreamingUnmask :: Method -> Path -> RequestHeaders -> ((forall x. () => IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()) -> Request

-- | Creating request with builder.
requestBuilder :: Method -> Path -> RequestHeaders -> Builder -> Request
data OutBodyIface
OutBodyIface :: (forall x. () => IO x -> IO x) -> (Builder -> IO ()) -> (Builder -> IO ()) -> (Maybe SomeException -> IO ()) -> IO () -> OutBodyIface

-- | Unmask exceptions in the thread spawned for the request body
--   
--   This is used in the client: we spawn the new thread for the request
--   body with exceptions masked, and provide the body of
--   OutBodyStreamingIface with a callback to unmask them again
--   (typically after installing an exception handler).
--   
--   Unmasking in the server is a no-op, as here the scope of the thread
--   that is spawned for the server is the entire handler, not just the
--   response streaming body.
[outBodyUnmask] :: OutBodyIface -> forall x. () => IO x -> IO x

-- | Push a new chunk
--   
--   In http2, there is no direct correspondence between chunks
--   and the resulting DATA frames sent: the chunks are collected
--   (written to an internal write buffer) until we can fill a frame.
--   
--   See also outBodyFlush.
[outBodyPush] :: OutBodyIface -> Builder -> IO ()

-- | Push the final chunk
--   
--   Using this function instead of outBodyPush can be used to
--   guarantee that the final HTTP2 DATA frame is marked end-of-stream;
--   with outBodyPush it may happen that an additional empty DATA
--   frame is used for this purpose. Additionally, after calling this
--   function, outBodyCancel will be a no-op.
[outBodyPushFinal] :: OutBodyIface -> Builder -> IO ()

-- | Cancel the stream
--   
--   Sends a RST_STREAM to the peer. If cancelling as the result
--   of an exception, a Just should be provided which specifies the
--   exception which will be stored locally as the reason for cancelling
--   the stream; in this case, the error code sent with the
--   RST_STREAM will be INTERNAL_ERROR (see
--   https://datatracker.ietf.org/doc/html/rfc7540#section-7). If
--   Nothing is given, the error code will be CANCEL.
--   
--   If there is a partially constructed DATA frame at the time of
--   cancellation, this frame is discarded. If this is undesirable, you
--   should call outBodyFlush prior to cancelling.
[outBodyCancel] :: OutBodyIface -> Maybe SomeException -> IO ()

-- | Flush
--   
--   This can be used to emit a DATA frame with the data collected so far
--   (using outBodyPush), even if that DATA frame has not yet
--   reached the maximum frame size. Calling outBodyFlush
--   unnecessarily can therefore result in excessive overhead from frame
--   headers.
--   
--   If no data is available to send, this is a no-op.
[outBodyFlush] :: OutBodyIface -> IO ()

-- | Generalized version of requestStreaming,
requestStreamingIface :: Method -> Path -> RequestHeaders -> (OutBodyIface -> IO ()) -> Request

-- | Trailers maker. A chunks of the response body is passed with
--   Just. The maker should update internal state with the
--   ByteString and return the next trailers maker. When response
--   body reaches its end, Nothing is passed and the maker should
--   generate trailers. An example:
--   
--   
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   
--   
--   Usage example:
--   
--   
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Setting TrailersMaker to Response.
setRequestTrailersMaker :: Request -> TrailersMaker -> Request

-- | Response from server.
data Response

-- | Getting the status of a response.
responseStatus :: Response -> Maybe Status

-- | Getting the headers from a response.
responseHeaders :: Response -> TokenHeaderTable

-- | Getting the body size from a response.
responseBodySize :: Response -> Maybe Int

-- | Reading a chunk of the response body. An empty ByteString
--   returned when finished.
getResponseBodyChunk :: Response -> IO ByteString

-- | Generalization of getResponseBodyChunk which also returns if
--   the ByteString is the final one
getResponseBodyChunk' :: Response -> IO (ByteString, Bool)

-- | Reading response trailers. This function must be called after
--   getResponseBodyChunk returns an empty.
getResponseTrailers :: Response -> IO (Maybe TokenHeaderTable)

-- | Additional information.
data Aux

-- | How many streams can be created without blocking.
auxPossibleClientStreams :: Aux -> IO Int

-- | "http" or "https".
type Scheme = ByteString

-- | Authority.
type Authority = String

-- | HTTP method (flat ByteString type).
type Method = ByteString

-- | Path.
type Path = ByteString

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec

-- | Offset for file.
type FileOffset = Int64

-- | How many bytes to read
type ByteCount = Int64

-- | Reading n bytes.
type ReadN = Int -> IO ByteString

-- | Naive implementation for readN.
--   
--   NOTE: This function is intended to be used by a single thread
--   only. (It is probably quite rare anyway to want concurrent reads from
--   the same network socket.)
defaultReadN :: Socket -> IORef (Maybe ByteString) -> ReadN

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Position read based on Handle.
defaultPositionReadMaker :: PositionReadMaker

module Network.HTTP.Semantics.IO

-- | Reading n bytes.
type ReadN = Int -> IO ByteString

-- | Naive implementation for readN.
--   
--   NOTE: This function is intended to be used by a single thread
--   only. (It is probably quite rare anyway to want concurrent reads from
--   the same network socket.)
defaultReadN :: Socket -> IORef (Maybe ByteString) -> ReadN

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Position read based on Handle.
defaultPositionReadMaker :: PositionReadMaker
data Next
Next :: BytesFilled -> Bool -> Maybe DynaNext -> Next
CancelNext :: Maybe SomeException -> Next

-- | Write part of a streaming response to the write buffer
--   
--   In http2 this will be used to construct a single HTTP2
--   DATA frame (see discussion of the maximum number of bytes,
--   below).
type DynaNext = Buffer -> Int -> IO Next
type BytesFilled = Int
data StreamingChunk

-- | Indicate that the stream is finished
StreamingFinished :: Maybe CleanupStream -> StreamingChunk

-- | Indicate that the stream is cancelled
StreamingCancelled :: Maybe SomeException -> StreamingChunk

-- | Flush the stream
--   
--   This will cause the write buffer to be written to the network socket,
--   without waiting for more data.
StreamingFlush :: StreamingChunk

-- | Construct a DATA frame, optionally terminating the stream
StreamingBuilder :: Builder -> IsEndOfStream -> StreamingChunk
data IsEndOfStream

-- | The stream is not yet terminated
NotEndOfStream :: IsEndOfStream

-- | The stream is terminated
--   
--   In addition to indicating that the stream is terminated, we can also
--   specify an optional Cleanup handler to be run.
EndOfStream :: Maybe CleanupStream -> IsEndOfStream

-- | Action to run prior to terminating the stream
type CleanupStream = IO ()
fillBuilderBodyGetNext :: Builder -> DynaNext
fillFileBodyGetNext :: PositionRead -> FileOffset -> ByteCount -> Sentinel -> DynaNext
fillStreamBodyGetNext :: IO (Maybe StreamingChunk) -> DynaNext

-- | Trailers maker. A chunks of the response body is passed with
--   Just. The maker should update internal state with the
--   ByteString and return the next trailers maker. When response
--   body reaches its end, Nothing is passed and the maker should
--   generate trailers. An example:
--   
--   
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   
--   
--   Usage example:
--   
--   
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Running trailers-maker.
--   
--   
--   bufferIO buf siz $ \bs -> tlrmkr (Just bs)
--   
runTrailersMaker :: TrailersMaker -> Buffer -> Int -> IO NextTrailersMaker
