http2-3.0.0: Network/HTTP2/Server.hs
{-# LANGUAGE OverloadedStrings #-}
-- | HTTP\/2 server library.
--
-- Example:
--
-- > {-# LANGUAGE OverloadedStrings #-}
-- > module Main (main) where
-- >
-- > import qualified Control.Exception as E
-- > import Data.ByteString.Builder (byteString)
-- > import Network.HTTP.Types (ok200)
-- > import Network.Run.TCP (runTCPServer) -- network-run
-- >
-- > import Network.HTTP2.Server
-- >
-- > main :: IO ()
-- > main = runTCPServer Nothing "80" $ \s _peer -> runHTTP2Server s
-- > where
-- > runHTTP2Server s = E.bracket (allocSimpleConfig s 4096)
-- > freeSimpleConfig
-- > (\config -> run config server)
-- > server _req _aux sendResponse = sendResponse response []
-- > where
-- > response = responseBuilder ok200 header body
-- > header = [("Content-Type", "text/plain")]
-- > body = byteString "Hello, world!\n"
module Network.HTTP2.Server (
-- * Runner
run
-- * Runner arguments
, Config(..)
, allocSimpleConfig
, freeSimpleConfig
-- * HTTP\/2 server
, Server
-- * Request
, Request
-- ** Accessing request
, requestMethod
, requestPath
, requestAuthority
, requestScheme
, requestHeaders
, requestBodySize
, getRequestBodyChunk
, getRequestTrailers
-- * Aux
, Aux
, auxTimeHandle
-- * Response
, Response
-- ** Creating response
, responseNoBody
, responseFile
, responseStreaming
, responseBuilder
-- ** Accessing response
, responseBodySize
-- ** Trailers maker
, TrailersMaker
, NextTrailersMaker(..)
, defaultTrailersMaker
, setResponseTrailersMaker
-- * Push promise
, PushPromise
, pushPromise
, promiseRequestPath
, promiseResponse
, promiseWeight
, defaultWeight
-- * Types
, Path
, Authority
, Scheme
, FileSpec(..)
, FileOffset
, ByteCount
-- * RecvN
, defaultReadN
-- * Position read for files
, PositionReadMaker
, PositionRead
, Sentinel(..)
, defaultPositionReadMaker
) where
import Data.ByteString.Builder (Builder)
import Data.IORef (readIORef)
import qualified Network.HTTP.Types as H
import Imports
import Network.HPACK
import Network.HPACK.Token
import Network.HTTP2.Arch
import Network.HTTP2.Frame.Types
import Network.HTTP2.Server.Run (run)
import Network.HTTP2.Server.Types
----------------------------------------------------------------
-- | Getting the method from a request.
requestMethod :: Request -> Maybe H.Method
requestMethod (Request req) = getHeaderValue tokenMethod vt
where
(_,vt) = inpObjHeaders req
-- | Getting the path from a request.
requestPath :: Request -> Maybe Path
requestPath (Request req) = getHeaderValue tokenPath vt
where
(_,vt) = inpObjHeaders req
-- | Getting the authority from a request.
requestAuthority :: Request -> Maybe Authority
requestAuthority (Request req) = getHeaderValue tokenAuthority vt
where
(_,vt) = inpObjHeaders req
-- | Getting the scheme from a request.
requestScheme :: Request -> Maybe Scheme
requestScheme (Request req) = getHeaderValue tokenScheme vt
where
(_,vt) = inpObjHeaders req
-- | Getting the headers from a request.
requestHeaders :: Request -> HeaderTable
requestHeaders (Request req) = inpObjHeaders req
-- | Getting the body size from a request.
requestBodySize :: Request -> Maybe Int
requestBodySize (Request req) = inpObjBodySize req
-- | Reading a chunk of the request body.
-- An empty 'ByteString' returned when finished.
getRequestBodyChunk :: Request -> IO ByteString
getRequestBodyChunk (Request req) = inpObjBody req
-- | Reading request trailers.
-- This function must be called after 'getRequestBodyChunk'
-- returns an empty.
getRequestTrailers :: Request -> IO (Maybe HeaderTable)
getRequestTrailers (Request req) = readIORef (inpObjTrailers req)
----------------------------------------------------------------
-- | Creating response without body.
responseNoBody :: H.Status -> H.ResponseHeaders -> Response
responseNoBody st hdr = Response $ OutObj hdr' OutBodyNone defaultTrailersMaker
where
hdr' = setStatus st hdr
-- | Creating response with file.
responseFile :: H.Status -> H.ResponseHeaders -> FileSpec -> Response
responseFile st hdr fileSpec = Response $ OutObj hdr' (OutBodyFile fileSpec) defaultTrailersMaker
where
hdr' = setStatus st hdr
-- | Creating response with builder.
responseBuilder :: H.Status -> H.ResponseHeaders -> Builder -> Response
responseBuilder st hdr builder = Response $ OutObj hdr' (OutBodyBuilder builder) defaultTrailersMaker
where
hdr' = setStatus st hdr
-- | Creating response with streaming.
responseStreaming :: H.Status -> H.ResponseHeaders
-> ((Builder -> IO ()) -> IO () -> IO ())
-> Response
responseStreaming st hdr strmbdy = Response $ OutObj hdr' (OutBodyStreaming strmbdy) defaultTrailersMaker
where
hdr' = setStatus st hdr
----------------------------------------------------------------
-- | Getter for response body size. This value is available for file body.
responseBodySize :: Response -> Maybe Int
responseBodySize (Response (OutObj _ (OutBodyFile (FileSpec _ _ len)) _)) = Just (fromIntegral len)
responseBodySize _ = Nothing
-- | Setting 'TrailersMaker' to 'Response'.
setResponseTrailersMaker :: Response -> TrailersMaker -> Response
setResponseTrailersMaker (Response rsp) tm = Response rsp { outObjTrailers = tm }
----------------------------------------------------------------
-- | Creating push promise.
-- The third argument is traditional, not used.
pushPromise :: ByteString -> Response -> Weight -> PushPromise
pushPromise path rsp w = PushPromise path rsp w