-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Second Transfer HTTP/2 web server -- @package second-transfer @version 0.1.0.0 module SecondTransfer.Http2 -- | 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 :: CoherentWorker -> Attendant 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. 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 to notify -- the session that the connection has been broken. 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. Capture one IOProblem -- otherwise. 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
-- , DataAndConclusion
-- , tlsServeWithALPN
-- , http2Attendant
-- )
--
-- import Data.Conduit
--
--
-- saysHello :: DataAndConclusion
-- saysHello = do
-- yield "Hello world!\ns"
-- -- 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, so that it has access to the toy
-- -- certificates and keys defined there.
-- main = do
-- 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
-- where
-- http2_attendant = http2Attendant helloWorldWorker
--
--
-- CoherentWorker is 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 yourself or use one of the many Haskell libraries to
-- that end.
--
-- 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. 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 to notify -- the session that the connection has been broken. 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 :: 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. Capture one IOProblem -- otherwise. 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