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

Safe HaskellNone
LanguageHaskell2010

SecondTransfer.Utils.HTTPHeaders

Contents

Description

Utilities for working with headers.

Synopsis

Simple manipulation

These transformations are simple enough that don't require going away from the list representation (see type Headers)

lowercaseHeaders :: Headers -> Headers

HTTP headers are case-insensitive, so we can use lowercase versions everywhere

headersAreLowercase :: Headers -> Bool

Checks that headers are lowercase

fetchHeader :: Headers -> HeaderName -> Maybe HeaderValue

Looks for a given header

Transformations based on maps

Many operations benefit from transforming the list to a map with custom sorting and doing a set of operations on that representation.

data HeaderEditor

Abstract data-type. Use fromList to get one of these from Headers. The underlying representation admits better asymptotics.

Instances

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.

Introducing and removing the HeaderEditor

fromList :: Headers -> HeaderEditor

O(n*log n) Builds the editor from a list.

toList :: HeaderEditor -> Headers

O(n) Takes the HeaderEditor back to Headers. Notice that these headers are good for both HTTP1.1 and HTTP2, as combined headers won't be merged. It will even work for Cookie headers.

Access to a particular header

headerLens :: ByteString -> Lens' HeaderEditor (Maybe ByteString)

headerLens header_name represents a lens into the headers, and you can use it then to add, alter and() remove headers. It uses the same semantics than replaceHeaderValue

replaceHeaderValue :: HeaderEditor -> HeaderName -> Maybe HeaderValue -> HeaderEditor

replaceHeaderValue headers header_name maybe_header_value looks for header_name. If header_name is found and maybe_header_value is nothing, it returns a new headers list with the header deleted. If header_name is found and header_value is Just new_value, it returns a new list with the header containing the new value. If header_name is not in headers and maybe_header_value is Nothing, it returns the original headers list. If header_name is not in headers and maybe_header_value is Just new_value, it returns a new list where the last element is (header_name, new_value)

HTTP utilities

replaceHostByAuthority :: HeaderEditor -> HeaderEditor

Replaces a "host" HTTP/1.1 header by an ":authority" HTTP/2 header. The list is expected to be already in lowercase, so nothing will happen if there the header name portion is "Host" instead of "host".

Notice that having a Host header in an HTTP/2 message is perfectly valid in certain circumstances, check Section 8.1.2.3 of the spec for details.

introduceDateHeader :: HeaderEditor -> IO HeaderEditor

Given a header editor, introduces a Date header. This function has a side-effect: to get the current time

combineAuthorityAndHost :: HeaderEditor -> HeaderEditor

Combines ":authority" and "host", giving priority to the first. This is used when proxying HTTP2 to HTTP1.1. It leaves whichever header of highest priority is present

removeConnectionHeaders :: Headers -> Headers

Remove connection-specific headers as required by HTTP/2

fusionHeaders :: HeaderName -> ByteString -> Headers -> Headers

Fusion values for a specific header, using a provided separator.