HTTP/2 framing, HPACK and connection state, I/O-free
0

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-h2 / lib / hpack.mli
6.2 kB 161 lines
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2019 Antonio Nuno Monteiro. Copyright (c) 2025 Anil Madhavapeddy 3 <anil@recoil.org>. 4 5 All rights reserved. 6 7 Redistribution and use in source and binary forms, with or without 8 modification, are permitted provided that the following conditions are met: 9 10 1. Redistributions of source code must retain the above copyright notice, this 11 list of conditions and the following disclaimer. 12 13 2. Redistributions in binary form must reproduce the above copyright notice, 14 this list of conditions and the following disclaimer in the documentation 15 and/or other materials provided with the distribution. 16 17 3. Neither the name of the copyright holder nor the names of its contributors 18 may be used to endorse or promote products derived from this software without 19 specific prior written permission. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 SPDX-License-Identifier: BSD-3-Clause 32 ---------------------------------------------------------------------------*) 33 34(** HPACK Header Compression per RFC 7541. 35 36 This module implements header compression for HTTP/2 as specified in 37 {{:https://datatracker.ietf.org/doc/html/rfc7541}RFC 7541}. 38 39 {2 Overview} 40 41 HPACK compresses HTTP headers by: 42 - Using static and dynamic tables to index frequently used headers 43 - Huffman encoding string literals 44 - Variable-length integer encoding 45 46 {2 Usage} 47 48 Create encoder/decoder contexts for each HTTP/2 connection: 49 {[ 50 open H2 51 52 let demo () = 53 let encoder = Hpack.Encoder.v 4096 in 54 let decoder = Hpack.Decoder.v 4096 in 55 let headers = 56 [ 57 { Hpack.name = ":method"; value = "GET"; sensitive = false }; 58 { Hpack.name = ":path"; value = "/"; sensitive = false }; 59 ] 60 in 61 let buf = Bytes.create 1024 in 62 let len = Hpack.Encoder.encode_headers encoder buf headers in 63 let block = Bytes.sub buf 0 len in 64 match Hpack.Decoder.decode decoder block with 65 | Ok _hs -> () 66 | Error Hpack.Decoding_error -> () 67 ]} *) 68 69(** {1 Types} *) 70 71type header = { 72 name : string; 73 (** Header field name (lowercase, or pseudo-header with colon prefix). *) 74 value : string; (** Header field value. *) 75 sensitive : bool; 76 (** If true, this header should never be indexed. Used for sensitive 77 values like cookies and authorization. *) 78} 79(** A header field with optional sensitivity flag. *) 80 81type error = Decoding_error (** HPACK decoding error. *) 82 83val pp_error : Format.formatter -> error -> unit 84(** Pretty printer for errors. *) 85 86(** {1 Decoder} 87 88 HPACK decoder with dynamic table context. *) 89module Decoder : sig 90 type t 91 (** Decoder context maintaining dynamic table state. *) 92 93 val v : ?max_header_list_size:int -> int -> t 94 (** [v ?max_header_list_size max_capacity] creates a decoder with the given 95 maximum dynamic table capacity in bytes (default 4096). 96 97 [max_header_list_size] bounds the total decoded header-list size: the sum 98 over decoded fields of [String.length name + String.length value + 32], 99 the SETTINGS_MAX_HEADER_LIST_SIZE metric (RFC 9113 Section 6.5.2). 100 {!decode} returns [Error Decoding_error] as soon as a block exceeds it, so 101 a compressed block that expands without limit -- an HPACK decompression 102 bomb (RFC 7541 Section 7.2) -- is rejected in bounded work rather than 103 allocated. Defaults to no limit. *) 104 105 val set_capacity : t -> int -> (unit, error) result 106 (** [set_capacity t capacity] updates the dynamic table capacity. Returns 107 [Error Decoding_error] if capacity exceeds max_capacity. *) 108 109 val decode : t -> bytes -> (header list, error) result 110 (** [decode t buf] decodes a header block fragment. Returns headers in 111 transmission order. 112 113 Per RFC 7541, decoding updates the dynamic table state, so the same 114 decoder must be used for all header blocks on a connection. *) 115end 116 117(** {1 Encoder} 118 119 HPACK encoder with dynamic table context. *) 120module Encoder : sig 121 type t 122 (** Encoder context maintaining dynamic table state. *) 123 124 val v : int -> t 125 (** [v capacity] creates an encoder with the given dynamic table capacity in 126 bytes (default 4096). *) 127 128 val set_capacity : t -> int -> unit 129 (** [set_capacity t capacity] updates the dynamic table capacity. This may 130 evict entries if the new capacity is smaller. *) 131 132 val encode_headers : t -> bytes -> header list -> int 133 (** [encode_headers t buf headers] encodes headers into [buf]. Returns the 134 number of bytes written. 135 136 The buffer must be large enough for the encoded output. A safe estimate is 137 16KB for typical header blocks. 138 139 Per RFC 7541, encoding updates the dynamic table state, so the same 140 encoder must be used for all header blocks on a connection. *) 141end 142 143(** {1 Huffman Encoding} 144 145 Low-level Huffman encoding/decoding per RFC 7541 Appendix B. *) 146module Huffman : sig 147 val encoded_length : string -> int 148 (** [encoded_length s] returns the Huffman-encoded length in bytes. *) 149 150 val encode : bytes -> int -> string -> int 151 (** [encode buf off s] encodes [s] using Huffman coding. Returns the number of 152 bytes written. *) 153 154 val decode : string -> (string, error) result 155 (** [decode s] decodes a Huffman-encoded string. *) 156end 157 158(** {1 Constants} *) 159 160val default_table_size : int 161(** Default dynamic table size: 4096 bytes. *)