1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
{-# 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" runHTTP2Server
-- > where
-- > runHTTP2Server s = E.bracket (allocSimpleConfig s 4096)
-- > freeSimpleConfig
-- > (\config -> run defaultServerConfig 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,
-- * Server configuration
ServerConfig,
defaultServerConfig,
numberOfWorkers,
connectionWindowSize,
settings,
-- * HTTP\/2 setting
Settings,
defaultSettings,
headerTableSize,
enablePush,
maxConcurrentStreams,
initialWindowSize,
maxFrameSize,
maxHeaderListSize,
-- * Common configuration
Config (..),
allocSimpleConfig,
freeSimpleConfig,
-- * HTTP\/2 server
Server,
-- * Request
Request,
-- ** Accessing request
requestMethod,
requestPath,
requestAuthority,
requestScheme,
requestHeaders,
requestBodySize,
getRequestBodyChunk,
getRequestTrailers,
-- * Aux
Aux,
auxTimeHandle,
auxMySockAddr,
auxPeerSockAddr,
-- * Response
Response,
-- ** Creating response
responseNoBody,
responseFile,
responseStreaming,
responseBuilder,
-- ** Accessing response
responseBodySize,
-- ** Trailers maker
TrailersMaker,
NextTrailersMaker (..),
defaultTrailersMaker,
setResponseTrailersMaker,
-- * Push promise
PushPromise,
pushPromise,
promiseRequestPath,
promiseResponse,
-- * 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.Frame.Types
import Network.HTTP2.H2
import Network.HTTP2.Server.Run (
ServerConfig (..),
defaultServerConfig,
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 _ = PushPromise path rsp
|