http2-1.6.3: HTTP/2 library including frames, priority queues and HPACK

Safe Haskell | None
Language | Haskell2010

Network.HPACK

Contents

- Encoding and decoding
- Encoding and decoding with token
- DynamicTable
- Strategy for encoding
- Errors
- Headers
- Value table
- Basic types

Description

HPACK(https://tools.ietf.org/html/rfc7541) encoding and decoding a header list.

Synopsis

- encodeHeader :: EncodeStrategy -> Size -> DynamicTable -> HeaderList -> IO ByteString
- decodeHeader :: DynamicTable -> ByteString -> IO HeaderList
- encodeTokenHeader :: Buffer -> BufferSize -> EncodeStrategy -> Bool -> DynamicTable -> TokenHeaderList -> IO (TokenHeaderList, Int)
- decodeTokenHeader :: DynamicTable -> ByteString -> IO (TokenHeaderList, ValueTable)
- data DynamicTable
- defaultDynamicTableSize :: Int
- newDynamicTableForEncoding :: Size -> IO DynamicTable
- newDynamicTableForDecoding :: Size -> Size -> IO DynamicTable
- clearDynamicTable :: DynamicTable -> IO ()
- withDynamicTableForEncoding :: Size -> (DynamicTable -> IO a) -> IO a
- withDynamicTableForDecoding :: Size -> Size -> (DynamicTable -> IO a) -> IO a
- setLimitForEncoding :: Size -> DynamicTable -> IO ()
- data CompressionAlgo
  - = Naive
  - | Static
  - | Linear
- data EncodeStrategy = EncodeStrategy {
  - compressionAlgo :: !CompressionAlgo
  - useHuffman :: !Bool
  }
- defaultEncodeStrategy :: EncodeStrategy
- data DecodeError
  - = IndexOverrun Index
  - | EosInTheMiddle
  - | IllegalEos
  - | TooLongEos
  - | EmptyEncodedString
  - | TooSmallTableSize
  - | TooLargeTableSize
  - | IllegalTableSizeUpdate
  - | HeaderBlockTruncated
  - | IllegalHeaderName
- data BufferOverrun = BufferOverrun
- type HeaderList = [Header]
- type Header = (HeaderName, HeaderValue)
- type HeaderName = ByteString
- type HeaderValue = ByteString
- type TokenHeaderList = [TokenHeader]
- type TokenHeader = (Token, HeaderValue)
- type ValueTable = Array Int (Maybe HeaderValue)
- getHeaderValue :: Token -> ValueTable -> Maybe HeaderValue
- toHeaderTable :: [(CI HeaderName, HeaderValue)] -> IO (TokenHeaderList, ValueTable)
- type Size = Int
- type Index = Int
- type Buffer = Ptr Word8
- type BufferSize = Int

# Encoding and decoding

encodeHeader #

Arguments

:: EncodeStrategy |
-> Size | The size of a temporary buffer.
-> DynamicTable |
-> HeaderList |
-> IO ByteString | An HPACK format

Converting `HeaderList` to the HPACK format. This function has overhead of allocating/freeing a temporary buffer. `BufferOverrun` will be thrown if the temporary buffer is too small.

decodeHeader #

Arguments

:: DynamicTable |
-> ByteString | An HPACK format
-> IO HeaderList |

Converting the HPACK format to `HeaderList`.

- Headers are decoded as is.
- `DecodeError` would be thrown if the HPACK format is broken.
- `BufferOverrun` will be thrown if the temporary buffer for Huffman decoding is too small.

# Encoding and decoding with token

encodeTokenHeader #

Arguments

:: Buffer |
-> BufferSize |
-> EncodeStrategy |
-> Bool | `True` at the first time, `False` when continued.
-> DynamicTable |
-> TokenHeaderList |
-> IO (TokenHeaderList, Int) | Leftover, filled length

Converting `TokenHeaderList` to the HPACK format directly in the buffer.

4th argument is relating to dynamic table size update. When calling this function for a new `TokenHeaderList`, it must be `True`. If `True` and set by `setLimitForEncoding`, dynamic table size update is generated at the beginning of the HPACK format.

The return value is a pair of leftover `TokenHeaderList` and how many bytes are filled in the buffer. If the leftover is empty, the encoding is finished. Otherwise, this function should be called with it again. 4th argument must be `False`.

decodeTokenHeader #

Arguments

:: DynamicTable |
-> ByteString | An HPACK format
-> IO (TokenHeaderList, ValueTable) |

Converting the HPACK format to `TokenHeaderList` and `ValueTable`.

- Multiple values of Cookie: are concatenated.
- If a pseudo header appears multiple times, `IllegalHeaderName` is thrown.
- If unknown pseudo headers appear, `IllegalHeaderName` is thrown.
- If pseudo headers are found after normal headers, `IllegalHeaderName` is thrown.
- If a header key contains capital letters, `IllegalHeaderName` is thrown.
- `DecodeError` would be thrown if the HPACK format is broken.
- `BufferOverrun` will be thrown if the temporary buffer for Huffman decoding is too small.

# DynamicTable

data DynamicTable #

Type for dynamic table.

defaultDynamicTableSize :: Int #

Default dynamic table size. The value is 4,096 bytes: an array has 128 entries.

    >>> defaultDynamicTableSize
    4096

newDynamicTableForEncoding #

Arguments

:: Size | The dynamic table size
-> IO DynamicTable |

Creating `DynamicTable` for encoding.

newDynamicTableForDecoding #

Arguments

:: Size | The dynamic table size
-> Size | The size of temporary buffer for Huffman decoding
-> IO DynamicTable |

Creating `DynamicTable` for decoding.

clearDynamicTable :: DynamicTable -> IO () #

Clearing `DynamicTable`. Currently, this frees the temporary buffer for Huffman decoding.

withDynamicTableForEncoding #

Arguments

:: Size | The dynamic table size
-> (DynamicTable -> IO a) |
-> IO a |

Creating `DynamicTable` for encoding, performing the action and clearing the `DynamicTable`.

withDynamicTableForDecoding #

Arguments

:: Size | The dynamic table size
-> Size | The size of temporary buffer for Huffman
-> (DynamicTable -> IO a) |
-> IO a |

Creating `DynamicTable` for decoding, performing the action and clearing the `DynamicTable`.

setLimitForEncoding :: Size -> DynamicTable -> IO () #

When SETTINGS_HEADER_TABLE_SIZE is received from a peer, its value should be set by this function.

# Strategy for encoding

data CompressionAlgo #

Compression algorithms for HPACK encoding.

Constructors

Naive | No compression
Static | Using indices in the static table only
Linear | Using indices

Instances

Eq CompressionAlgo # |
Methods (==) :: CompressionAlgo -> CompressionAlgo -> Bool # (/=) :: CompressionAlgo -> CompressionAlgo -> Bool #
Show CompressionAlgo # |
Methods showsPrec :: Int -> CompressionAlgo -> ShowS # show :: CompressionAlgo -> String # showList :: [CompressionAlgo] -> ShowS #

data EncodeStrategy #

Strategy for HPACK encoding.

Constructors

EncodeStrategy |
Fields compressionAlgo :: !CompressionAlgo Which compression algorithm is used. useHuffman :: !Bool Whether or not to use Huffman encoding for strings.

Instances

Eq EncodeStrategy # |
Methods (==) :: EncodeStrategy -> EncodeStrategy -> Bool # (/=) :: EncodeStrategy -> EncodeStrategy -> Bool #
Show EncodeStrategy # |
Methods showsPrec :: Int -> EncodeStrategy -> ShowS # show :: EncodeStrategy -> String # showList :: [EncodeStrategy] -> ShowS #

defaultEncodeStrategy :: EncodeStrategy #

Default `EncodeStrategy`.

    >>> defaultEncodeStrategy
    EncodeStrategy {compressionAlgo = Linear, useHuffman = False}

# Errors

data DecodeError #

Errors for decoder.

Constructors

IndexOverrun Index | Index is out of range
EosInTheMiddle | Eos appears in the middle of huffman string
IllegalEos | Non-eos appears in the end of huffman string
TooLongEos | Eos of huffman string is more than 7 bits
EmptyEncodedString | Encoded string has no length
TooSmallTableSize | A peer set the dynamic table size less than 32
TooLargeTableSize | A peer tried to change the dynamic table size over the limit
IllegalTableSizeUpdate | Table size update at the non-beginning
HeaderBlockTruncated |
IllegalHeaderName |

Instances

Eq DecodeError # |
Methods (==) :: DecodeError -> DecodeError -> Bool # (/=) :: DecodeError -> DecodeError -> Bool #
Show DecodeError # |
Methods showsPrec :: Int -> DecodeError -> ShowS # show :: DecodeError -> String # showList :: [DecodeError] -> ShowS #
Exception DecodeError # |
Methods toException :: DecodeError -> SomeException # fromException :: SomeException -> Maybe DecodeError # displayException :: DecodeError -> String #

data BufferOverrun #

Constructors

BufferOverrun | The buffer size is not enough

Instances

Eq BufferOverrun # |
Methods (==) :: BufferOverrun -> BufferOverrun -> Bool # (/=) :: BufferOverrun -> BufferOverrun -> Bool #
Show BufferOverrun # |
Methods showsPrec :: Int -> BufferOverrun -> ShowS # show :: BufferOverrun -> String # showList :: [BufferOverrun] -> ShowS #
Exception BufferOverrun # |
Methods toException :: BufferOverrun -> SomeException # fromException :: SomeException -> Maybe BufferOverrun # displayException :: BufferOverrun -> String #

# Headers

type HeaderList = [Header] #

Header list.

type Header = (HeaderName, HeaderValue) #

Header.

type HeaderName = ByteString #

Header name.

type HeaderValue = ByteString #

Header value.

type TokenHeaderList = [TokenHeader] #

type TokenHeader = (Token, HeaderValue) #

# Value table

type ValueTable = Array Int (Maybe HeaderValue) #

An array for `HeaderValue`.

getHeaderValue :: Token -> ValueTable -> Maybe HeaderValue #

Accessing `HeaderValue` with `Token`.

toHeaderTable :: [(CI HeaderName, HeaderValue)] -> IO (TokenHeaderList, ValueTable) #

Converting a header list of the http-types style to `TokenHeaderList` and `ValueTable`.

# Basic types

type Size = Int #

Size in bytes.

type Index = Int #

Index for table.

type Buffer = Ptr Word8 #

Buffer type.

type BufferSize = Int #

The size of buffer.