Network.HTTP.Semantics.Client

http-semantics-0.3.0: HTTP senmatics libarry

Safe Haskell | None
Language | Haskell2010

Network.HTTP.Semantics.Client

Contents

- HTTP client
- Request
- Creating request
  - Generalized streaming interface
  - Trailers maker
- Response
  - Accessing response
- Aux
- Types

Synopsis

- type Client a = SendRequest -> Aux -> IO a
- type SendRequest = forall r. Request -> (Response -> IO r) -> IO r
- data Request
- requestNoBody :: Method -> Path -> RequestHeaders -> Request
- requestFile :: Method -> Path -> RequestHeaders -> FileSpec -> Request
- requestStreaming :: Method -> Path -> RequestHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Request
- requestStreamingUnmask :: Method -> Path -> RequestHeaders -> ((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()) -> Request
- requestBuilder :: Method -> Path -> RequestHeaders -> Builder -> Request
- data OutBodyIface = OutBodyIface {
  - outBodyUnmask :: forall x. IO x -> IO x
  - outBodyPush :: Builder -> IO ()
  - outBodyPushFinal :: Builder -> IO ()
  - outBodyCancel :: Maybe SomeException -> IO ()
  - outBodyFlush :: IO ()
  }
- requestStreamingIface :: Method -> Path -> RequestHeaders -> (OutBodyIface -> IO ()) -> Request
- type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker
- data NextTrailersMaker
  - = NextTrailersMaker TrailersMaker
  - | Trailers [Header]
- defaultTrailersMaker :: TrailersMaker
- setRequestTrailersMaker :: Request -> TrailersMaker -> Request
- data Response
- responseStatus :: Response -> Maybe Status
- responseHeaders :: Response -> TokenHeaderTable
- responseBodySize :: Response -> Maybe Int
- getResponseBodyChunk :: Response -> IO ByteString
- getResponseBodyChunk' :: Response -> IO (ByteString, Bool)
- getResponseTrailers :: Response -> IO (Maybe TokenHeaderTable)
- data Aux
- auxPossibleClientStreams :: Aux -> IO Int
- type Scheme = ByteString
- type Authority = String
- type Method = ByteString
- type Path = ByteString
- data FileSpec = FileSpec FilePath FileOffset ByteCount
- type FileOffset = Int64
- type ByteCount = Int64
- type ReadN = Int -> IO ByteString
- defaultReadN :: Socket -> IORef (Maybe ByteString) -> ReadN
- type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount
- type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)
- data Sentinel
  - = Closer (IO ())
  - | Refresher (IO ())
- defaultPositionReadMaker :: PositionReadMaker

# HTTP client

type Client a = SendRequest -> Aux -> IO a #

Client type.

type SendRequest = forall r. Request -> (Response -> IO r) -> IO r #

Send a request and receive its response.

# Request

data Request #

Request from client.

#### Instances

Instances details

Show Request # |
Instance details Defined in Network.HTTP.Semantics.Client.Internal Methods showsPrec :: Int -> Request -> ShowS # show :: Request -> String # showList :: [Request] -> ShowS #

# Creating request

requestNoBody :: Method -> Path -> RequestHeaders -> Request #

Creating request without body.

requestFile :: Method -> Path -> RequestHeaders -> FileSpec -> Request #

Creating request with file.

requestStreaming :: Method -> Path -> RequestHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Request #

Creating request with streaming.

requestStreamingUnmask :: Method -> Path -> RequestHeaders -> ((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()) -> Request #

Like `requestStreaming`, but run the action with exceptions masked

requestBuilder :: Method -> Path -> RequestHeaders -> Builder -> Request #

Creating request with builder.

## Generalized streaming interface

data OutBodyIface #

Constructors

OutBodyIface |
Fields outBodyUnmask :: forall x. IO x -> IO x Unmask exceptions in the thread spawned for the request body This is used in the client: we spawn the new thread for the request body with exceptions masked, and provide the body of `OutBodyStreamingIface` with a callback to unmask them again (typically after installing an exception handler). Unmasking in the server is a no-op, as here the scope of the thread that is spawned for the server is the entire handler, not just the response streaming body. outBodyPush :: Builder -> IO () Push a new chunk In `http2`, there is no direct correspondence between chunks and the resulting `DATA` frames sent: the chunks are collected (written to an internal write buffer) until we can fill a frame. See also `outBodyFlush`. outBodyPushFinal :: Builder -> IO () Push the final chunk Using this function instead of `outBodyPush` can be used to guarantee that the final HTTP2 DATA frame is marked end-of-stream; with `outBodyPush` it may happen that an additional empty DATA frame is used for this purpose. Additionally, after calling this function, `outBodyCancel` will be a no-op. outBodyCancel :: Maybe SomeException -> IO () Cancel the stream Sends a `RST_STREAM` to the peer. If cancelling as the result of an exception, a `Just` should be provided which specifies the exception which will be stored locally as the reason for cancelling the stream; in this case, the error code sent with the `RST_STREAM` will be `INTERNAL_ERROR` (see https://datatracker.ietf.org/doc/html/rfc7540#section-7). If `Nothing` is given, the error code will be `CANCEL`. If there is a partially constructed `DATA` frame at the time of cancellation, this frame is discarded. If this is undesirable, you should call `outBodyFlush` prior to cancelling. outBodyFlush :: IO () Flush This can be used to emit a DATA frame with the data collected so far (using `outBodyPush`), even if that DATA frame has not yet reached the maximum frame size. Calling `outBodyFlush` unnecessarily can therefore result in excessive overhead from frame headers. If no data is available to send, this is a no-op.

requestStreamingIface :: Method -> Path -> RequestHeaders -> (OutBodyIface -> IO ()) -> Request #

Generalized version of `requestStreaming`,

## Trailers maker

type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker #

Trailers maker. A chunks of the response body is passed with `Just`. The maker should update internal state with the `ByteString` and return the next trailers maker. When response body reaches its end, `Nothing` is passed and the maker should generate trailers. An example:

    {-# LANGUAGE BangPatterns #-}
    import Data.ByteString (ByteString)
    import qualified Data.ByteString.Char8 as C8
    import Crypto.Hash (Context, SHA1) -- cryptonite
    import qualified Crypto.Hash as CH

    -- Strictness is important for Context.
    trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
    trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
      where
        !sha1 = C8.pack $ show $ CH.hashFinalize ctx
    trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
      where
        !ctx' = CH.hashUpdate ctx bs

Usage example:

    let h2rsp = responseFile ...
        maker = trailersMaker (CH.hashInit :: Context SHA1)
        h2rsp' = setResponseTrailersMaker h2rsp maker

data NextTrailersMaker #

Either the next trailers maker or final trailers.

Constructors

NextTrailersMaker TrailersMaker |
Trailers [Header] |

defaultTrailersMaker :: TrailersMaker #

TrailersMake to create no trailers.

setRequestTrailersMaker :: Request -> TrailersMaker -> Request #

Setting `TrailersMaker` to `Response`.

# Response

data Response #

Response from server.

#### Instances

Instances details

Show Response # |
Instance details Defined in Network.HTTP.Semantics.Client.Internal Methods showsPrec :: Int -> Response -> ShowS # show :: Response -> String # showList :: [Response] -> ShowS #

## Accessing response

responseStatus :: Response -> Maybe Status #

Getting the status of a response.

responseHeaders :: Response -> TokenHeaderTable #

Getting the headers from a response.

responseBodySize :: Response -> Maybe Int #

Getting the body size from a response.

getResponseBodyChunk :: Response -> IO ByteString #

Reading a chunk of the response body. An empty `ByteString` returned when finished.

getResponseBodyChunk' :: Response -> IO (ByteString, Bool) #

Generalization of `getResponseBodyChunk` which also returns if the `ByteString` is the final one

getResponseTrailers :: Response -> IO (Maybe TokenHeaderTable) #

Reading response trailers. This function must be called after `getResponseBodyChunk` returns an empty.

# Aux

data Aux #

Additional information.

auxPossibleClientStreams :: Aux -> IO Int #

How many streams can be created without blocking.

# Types

type Scheme = ByteString #

"http" or "https".

type Authority = String #

Authority.

type Method = ByteString #

HTTP method (flat `ByteString` type).

type Path = ByteString #

Path.

data FileSpec #

File specification.

Constructors

FileSpec FilePath FileOffset ByteCount |

#### Instances

Instances details

Show FileSpec # |
Instance details Defined in Network.HTTP.Semantics.Types Methods showsPrec :: Int -> FileSpec -> ShowS # show :: FileSpec -> String # showList :: [FileSpec] -> ShowS #
Eq FileSpec # |
Instance details Defined in Network.HTTP.Semantics.Types Methods (==) :: FileSpec -> FileSpec -> Bool # (/=) :: FileSpec -> FileSpec -> Bool #

type FileOffset = Int64 #

Offset for file.

type ByteCount = Int64 #

How many bytes to read

type ReadN = Int -> IO ByteString #

Reading n bytes.

defaultReadN :: Socket -> IORef (Maybe ByteString) -> ReadN #

Naive implementation for readN.

NOTE: This function is intended to be used by a single thread only. (It is probably quite rare anyway to want concurrent reads from the same network socket.)

type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount #

Position read for files.

type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel) #

Making a position read and its closer.

data Sentinel #

Constructors

Closer (IO ()) | Closing a file resource. Its refresher is automatiaclly generated by the internal timer.
Refresher (IO ()) | Refreshing a file resource while reading. Closing the file must be done by its own timer or something.

defaultPositionReadMaker :: PositionReadMaker #

Position read based on `Handle`.