second-transfer-0.10.0.4: Second Transfer HTTP/2 web server

Safe HaskellNone
LanguageHaskell2010

SecondTransfer.MainLoop.CoherentWorker

Description

A CoherentWorker is one that doesn't need to compute everything at once... This one is simpler than the SPDY one, because it enforces certain order....

Synopsis

Documentation

getHeaderFromFlatList :: Headers -> ByteString -> Maybe ByteString

Gets a single header from the list

nullFooter :: Source AwareWorkerStack ByteString -> DataAndConclusion

If you want to skip the footers, i.e., they are empty, use this function to convert an ordinary Source to a DataAndConclusion.

type HeaderName = ByteString

The name part of a header

type HeaderValue = ByteString

The value part of a header

type Header = (HeaderName, HeaderValue)

The complete header

type Headers = [Header]

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 FinalizationHeaders = Headers

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.

data Request

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 Footers = FinalizationHeaders

Finalization headers

data Perception

Data related to the request

Constructors

Perception 

Fields

_streamId_Pr :: Int

The HTTP/2 stream id. Or the serial number of the request in an HTTP/1.1 session.

_sessionId_Pr :: Int

A number uniquely identifying the session. This number is unique and the same for each TPC connection that a client opens using a given protocol.

_startedTime_Pr :: TimeSpec

Monotonic time close to when the request was first seen in the processing pipeline.

_protocol_Pr :: HttpProtocolVersion

Which protocol is serving the request

_anouncedProtocols_Pr :: Maybe [ByteString]

For new connections, probably a list of announced protocols

_peerAddress_Pr :: Maybe HashableSockAddr

tuple with something like the IPv4 number for the requesting host

data Effect

Sometimes a response needs to be handled a bit specially, for example by reporting delivery details back to the worker

Constructors

Effect 

Fields

_fragmentDeliveryCallback_Ef :: Maybe FragmentDeliveryCallback

A callback to be called whenever a data-packet for this stream is .

_priorityEffect_Ef :: PriorityEffect

In certain circunstances a stream can use an internal priority, not given by the browser and the protocol. Lowest values here are given more priority. Default (when Nothing) is given zero. Cases with negative numbers also work.

_interrupt_Ef :: Maybe InterruptEffect

There are situations when it is desirable to close a stream or the entire connection. Use this member to indicate that.

Instances

type AwareWorker = Request -> IO PrincipalStream

Main type of this library. You implement one of these for your server. 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.

It is important that you consume the data in the cases where there is an input stream, otherwise the memory is lost for the duration of the request, and a malicious client can use that.

Also, notice that when handling requests your worker can be interrupted with an asynchronous exception of type StreamCancelledException, if the peer cancels the stream

type AwareWorkerStack = ResourceT IO

Has kind * -> * Used to allow for registered cleanup functions to be safely called, evenspecially in the event of a BrowserUser hanging-up the connection before the worker has finished doing its work. Alleviates the need for handling async. execeptions.

data 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... they will be pushed to the client.

type PushedStreams = [IO PushedStream]

A list of pushed streams. Notice that a list of IO computations is required here. These computations only happen when and if the streams are pushed to the client. The lazy nature of Haskell helps to avoid unneeded computations if the streams are not going to be sent to the client.

data 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 DataAndConclusion = ConduitM () ByteString AwareWorkerStack Footers

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 CoherentWorker = TupledRequest -> IO TupledPrincipalStream

A CoherentWorker is a simplified callback that you can implement to handle requests. Then you can convert it to an AwareWorker with tupledPrincipalStreamToPrincipalStream.

type InputDataStream = Source AwareWorkerStack ByteString

This is a Source conduit (see Haskell Data.Conduit library from Michael Snoyman) that you can use to retrieve the data sent by the peer piece-wise.

type TupledPrincipalStream = (Headers, PushedStreams, DataAndConclusion)

A tuple representing the data alone that you usually need to give as a response, that is, the headers in the response (including the HTTP/2 :status), any pushed streams, a stream with the response data and the footers.

type TupledRequest = (Headers, Maybe InputDataStream)

A tuple representing the data alone usually needed to create a response. That is, the headers (including HTTP/2 :path, :authority, etc) and maybe an input data stream for requests that include it, that is, POST and PUT.

type FragmentDeliveryCallback = Int -> TimeSpec -> IO ()

First argument is the ordinal of this data frame, second an approximation of when the frame was delivered, according to the monotonic clock. Do not linger in this call, it may delay some important thread

data InterruptEffect

Types of interrupt effects that can be signaled by aware workers. These include whole connection shutdowns and stream resets. In all the cases, the reason given will be NO_ERROR.

Constructors

InterruptConnectionAfter_IEf

Close and send GoAway after this stream finishes delivery

InterruptConnectionNow_IEf

Close and send GoAway without delivering this stream. This implies that other fields of the PrincipalStream record will be ignored.

data PriorityEffect

Valid priority effects

In certain circunstances a stream can use an internal priority, not given by the browser and the protocol. Lowest values here are given more priority. Default (when Nothing) is given zero. Cases with negative numbers also work. Since higher numbers mean *lower* priority, we often call this number *calm*, so that higher numbers mean higher calm.

Notice that SecondTransfer still assigns "system priorities" to frames which are used before the priorities computed by this mechanism.

Constructors

NoEffect_PrEf

Leaves on default priorities

Uniform_PrEf !Int

Assigns a uniform priority to all data in this stream

PerYield_PrEf Int [(Word, Word)]

Starts with the given priority, and as the sender crosses each byte boundary in the first part of the pair, the calm is raised (e.g., the priority is lowered), by the positive number given as second part of the pair

tupledPrincipalStreamToPrincipalStream :: TupledPrincipalStream -> PrincipalStream

Convert between the two types of callback.