-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Second Transfer HTTP/2 web server -- @package second-transfer @version 0.2.0.0 module SecondTransfer.Exception -- | Abstract exception. All HTTP/2 exceptions derive from here data HTTP2SessionException HTTP2SessionException :: e -> HTTP2SessionException -- | Abstract exception. Thrown when encoding/decoding of a frame fails data FramerException FramerException :: e -> FramerException -- | Thrown when the HTTP/2 connection prefix doesn't match the expected -- prefix. data BadPrefaceException BadPrefaceException :: BadPrefaceException instance Typeable HTTP2SessionException instance Typeable FramerException instance Typeable BadPrefaceException instance Show BadPrefaceException instance Exception BadPrefaceException instance Exception FramerException instance Show FramerException instance Exception HTTP2SessionException instance Show HTTP2SessionException module SecondTransfer.Http2 -- | Thrown when the HTTP/2 connection prefix doesn't match the expected -- prefix. data BadPrefaceException -- | The type of this function is equivalent to: -- --
-- http2Attendant :: CoherentWorker -> PushAction -> PullAction -> CloseAction -> IO () ---- -- Given a CoherentWorker, this function wraps it with flow -- control, multiplexing, and state maintenance needed to run an HTTP/2 -- session. http2Attendant :: SessionsContext -> CoherentWorker -> Attendant makeSessionsContext :: SessionsConfig -> IO SessionsContext -- | Creates a default sessions context. Modify as needed using the lenses -- interfaces defaultSessionsConfig :: SessionsConfig -- | Configuration information you can provide to the session maker. data SessionsConfig -- | Contains information that applies to all sessions created in the -- program. Use the lenses interface to access members of this struct. data SessionsContext -- | Callbacks that you can provide your sessions to notify you of -- interesting things happening in the server. data SessionsCallbacks -- | Used by this session engine to report an error at some component, in a -- particular session. type ErrorCallback = (SessionComponent, SessionCoordinates, SomeException) -> IO () -- | Lens to access sessionsCallbacks in the SessionsConfig object. sessionsCallbacks :: Lens' SessionsConfig SessionsCallbacks reportErrorCallback :: Iso' SessionsCallbacks (Maybe ErrorCallback) module SecondTransfer.MainLoop.Internal readNextChunkAndContinue :: Monad m => LengthCallback -> ByteString -> m ByteString -> m (ByteString, ByteString) http2FrameLength :: LengthCallback type OutputFrame = (EncodeInfo, FramePayload) type InputFrame = Frame module SecondTransfer.MainLoop -- | A function which takes three arguments: the first one says how to send -- data (on a socket or similar transport), and the second one how to -- receive data on said socket. The third argument encapsulates the -- sequence of steps needed for a clean shutdown. -- -- You can implement one of these to let somebody else supply the push, -- pull and close callbacks. In this library we supply callbacks for TLS -- sockets, so that you don't need to go through the drudgery of managing -- those yourself. -- -- Attendants encapsulate all the session book-keeping functionality, -- which for HTTP/2 is quite complicated. You use the function -- http2Attendant to create one of these from a -- CoherentWorker. type Attendant = PushAction -> PullAction -> CloseAction -> IO () -- | Callback type to pull data from a channel. The same as to PushAction -- applies to exceptions thrown from there. type PullAction = IO ByteString -- | Callback type to push data to a channel. Part of this interface is the -- abstract exception type IOProblem. Throw an instance of it from here -- to notify the session that the connection has been broken. There is no -- way to signal "normal termination", since HTTP/2's normal termination -- can be observed at a higher level when a GO_AWAY frame is seen. type PushAction = ByteString -> IO () -- | Callback that the session calls to realease resources associated with -- the channels. Take into account that your callback should be able to -- deal with non-clean shutdowns also, for example, if the connection to -- the remote peer is severed suddenly. type CloseAction = IO () -- | Throw exceptions derived from this (e.g, GenericIOProblem -- below) to have the HTTP/2 session to terminate gracefully. data IOProblem -- | A concrete case of the above exception. Throw one of this if you don't -- want to implement your own type. Use IOProblem in catch -- signatures. data GenericIOProblem -- | Simple function to open tlsServeWithALPN :: FilePath -> FilePath -> String -> [(String, Attendant)] -> Int -> IO () -- | Interruptible version of tlsServeWithALPN. Use the extra -- argument to notify the server of finishing. tlsServeWithALPNAndFinishOnRequest :: FilePath -> FilePath -> String -> [(String, Attendant)] -> Int -> MVar FinishRequest -> IO () -- | Exception inheriting from IOProblem. This is thrown by the -- OpenSSL subsystem to signal that the connection was broken or that -- otherwise there was a problem at the SSL layer. data TLSLayerGenericProblem TLSLayerGenericProblem :: String -> TLSLayerGenericProblem -- | Singleton type. Used in conjunction with an MVar. If the MVar -- is full, the fuction tlsServeWithALPNAndFinishOnRequest knows -- that it should finish at its earliest convenience and call the -- CloseAction for any open sessions. data FinishRequest FinishRequest :: FinishRequest -- | This library implements enough of the HTTP/2 to build compliant HTTP/2 -- servers. The library -- --
-- import SecondTransfer(
-- CoherentWorker
-- , Footers
-- , DataAndConclusion
-- , tlsServeWithALPN
-- , http2Attendant
-- )
-- import SecondTransfer.Http2(
-- makeSessionsContext
-- , defaultSessionsConfig
-- )
--
-- import Data.Conduit
--
--
-- saysHello :: DataAndConclusion
-- saysHello = do
-- yield "Hello world!"
-- -- No footers
-- return []
--
--
-- helloWorldWorker :: CoherentWorker
-- helloWorldWorker request = return (
-- [
-- (":status", "200")
-- ],
-- [], -- No pushed streams
-- saysHello
-- )
--
--
-- -- For this program to work, it should be run from the top of
-- -- the developement directory.
-- main = do
-- sessions_context <- makeSessionsContext defaultSessionsConfig
-- let
-- http2_attendant = http2Attendant sessions_context helloWorldWorker
-- tlsServeWithALPN
-- "tests/support/servercert.pem" -- Server certificate
-- "tests/support/privkey.pem" -- Certificate private key
-- "127.0.0.1" -- On which interface to bind
-- [
-- ("h2-14", http2_attendant), -- Protocols present in the ALPN negotiation
-- ("h2", http2_attendant) -- they may be slightly different, but for this
-- -- test it doesn't matter.
-- ]
-- 8000
--
--
-- CoherentWorker is the type of the basic callback function that
-- you need to implement. The callback is used to handle all requests to
-- the server on a given negotiated ALPN protocol. If you need routing
-- functionality (and you most certainly will need it), you need to build
-- that functionality inside the callback.
--
-- The above program uses a test certificate by a fake certificate
-- authority. The certificate is valid for the server name ("authority",
-- in HTTP/2 lingo) www.httpdos.com. So, in order for the above program
-- to run, you probably need to add an alias to your /etc/hosts file. You
-- also need very up-to-date versions of OpenSSL (I'm using OpenSSL
-- 1.0.2) to be compliant with the cipher suites demanded by HTTP/2. The
-- easiest way to test the above program is using a fairly recent version
-- of curl. If everything is allright, you should be able to do:
--
-- -- $ curl -k --http2 https://www.httpdos.com:8000/ -- Hello world! --module SecondTransfer -- | 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 = [(ByteString, 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 type Footers = FinalizationHeaders -- | 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 -- | 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 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) -- | 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 () ByteString IO Footers -- | 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 ByteString -- | 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 -- | A function which takes three arguments: the first one says how to send -- data (on a socket or similar transport), and the second one how to -- receive data on said socket. The third argument encapsulates the -- sequence of steps needed for a clean shutdown. -- -- You can implement one of these to let somebody else supply the push, -- pull and close callbacks. In this library we supply callbacks for TLS -- sockets, so that you don't need to go through the drudgery of managing -- those yourself. -- -- Attendants encapsulate all the session book-keeping functionality, -- which for HTTP/2 is quite complicated. You use the function -- http2Attendant to create one of these from a -- CoherentWorker. type Attendant = PushAction -> PullAction -> CloseAction -> IO () -- | Callback type to pull data from a channel. The same as to PushAction -- applies to exceptions thrown from there. type PullAction = IO ByteString -- | Callback type to push data to a channel. Part of this interface is the -- abstract exception type IOProblem. Throw an instance of it from here -- to notify the session that the connection has been broken. There is no -- way to signal "normal termination", since HTTP/2's normal termination -- can be observed at a higher level when a GO_AWAY frame is seen. type PushAction = ByteString -> IO () -- | Callback that the session calls to realease resources associated with -- the channels. Take into account that your callback should be able to -- deal with non-clean shutdowns also, for example, if the connection to -- the remote peer is severed suddenly. type CloseAction = IO () -- | The type of this function is equivalent to: -- --
-- http2Attendant :: CoherentWorker -> PushAction -> PullAction -> CloseAction -> IO () ---- -- Given a CoherentWorker, this function wraps it with flow -- control, multiplexing, and state maintenance needed to run an HTTP/2 -- session. http2Attendant :: SessionsContext -> CoherentWorker -> Attendant -- | Throw exceptions derived from this (e.g, GenericIOProblem -- below) to have the HTTP/2 session to terminate gracefully. data IOProblem -- | A concrete case of the above exception. Throw one of this if you don't -- want to implement your own type. Use IOProblem in catch -- signatures. data GenericIOProblem -- | Simple function to open tlsServeWithALPN :: FilePath -> FilePath -> String -> [(String, Attendant)] -> Int -> IO () -- | Interruptible version of tlsServeWithALPN. Use the extra -- argument to notify the server of finishing. tlsServeWithALPNAndFinishOnRequest :: FilePath -> FilePath -> String -> [(String, Attendant)] -> Int -> MVar FinishRequest -> IO () -- | Exception inheriting from IOProblem. This is thrown by the -- OpenSSL subsystem to signal that the connection was broken or that -- otherwise there was a problem at the SSL layer. data TLSLayerGenericProblem TLSLayerGenericProblem :: String -> TLSLayerGenericProblem -- | Singleton type. Used in conjunction with an MVar. If the MVar -- is full, the fuction tlsServeWithALPNAndFinishOnRequest knows -- that it should finish at its earliest convenience and call the -- CloseAction for any open sessions. data FinishRequest FinishRequest :: FinishRequest