Repository: anmonteiro/ocaml-h2
Pull request #243 (2024-06-23 21:26:37)

Use httpun-types
https://ocaml.org/p/httpun-types/latest


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index f03c54b..c735da8 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,9 @@ Unreleased
   ([#229](https://github.com/anmonteiro/ocaml-h2/pull/229))
 - h2-eio: don't require `Eio_unix.stream_socket_ty`, allowing the use of mock
   sockets ([#236](https://github.com/anmonteiro/gluten/pull/236))
+- h2: drop the dependency on `httpaf`, use
+  [`httpun-types`](https://ocaml.org/p/httpun-types/latest) instead
+([#243](https://github.com/anmonteiro/ocaml-h2/pull/243))
 
 0.11.0 2023-10-26
 --------------
diff --git a/README.md b/README.md
index 030312e..8380b01 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ It sets up a server that listens on 2 ports:
 
     If `h2` is negotiated, the example sets up a connection handler using
     `h2-lwt-unix`. Otherwise the connection handler will serve HTTP/1.1 traffic
-    using http/af.
+    using [httpun](https://github.com/anmonteiro/httpun).
 
 The ALPN example also provides a unikernel implementation with the same
 functionality that runs on [MirageOS](https://mirage.io).
diff --git a/dune-project b/dune-project
index d5d3180..90a62aa 100644
--- a/dune-project
+++ b/dune-project
@@ -40,7 +40,7 @@
  (synopsis
   "A high-performance, memory-efficient, and scalable HTTP/2 library for OCaml")
  (description
-  "h2 is an implementation of the HTTP/2 specification entirely in OCaml. It is based on the concepts in http/af, and therefore uses the Angstrom and Faraday libraries to implement the parsing and serialization layers of the HTTP/2 standard as a state machine that is agnostic to the underlying I/O specifics. It also preserves the same API as http/af wherever possible.")
+  "h2 is an implementation of the HTTP/2 specification entirely in OCaml. It is based on the concepts in httpun, and therefore uses the Angstrom and Faraday libraries to implement the parsing and serialization layers of the HTTP/2 standard as a state machine that is agnostic to the underlying I/O specifics. It also preserves the same API as httpun wherever possible.")
  (depends
   (ocaml
    (>= "4.08.0"))
@@ -53,8 +53,9 @@
   (bigstringaf
    (>= "0.5.0"))
   psq
-  (hpack (= :version))
-  httpaf
+  (hpack
+   (= :version))
+  httpun-types
   (alcotest :with-test)
   (yojson :with-test)
   (hex :with-test)))
diff --git a/examples/alpn/lib/dune b/examples/alpn/lib/dune
index 87ac4ee..b0794cc 100644
--- a/examples/alpn/lib/dune
+++ b/examples/alpn/lib/dune
@@ -1,4 +1,4 @@
 (library
  (name alpn_lib)
  (modules h2_handler http1_handler)
- (libraries h2 httpaf httpaf-lwt-unix h2-lwt-unix lwt))
+ (libraries h2 httpun httpun-lwt-unix h2-lwt-unix lwt))
diff --git a/examples/alpn/lib/http1_handler.ml b/examples/alpn/lib/http1_handler.ml
index 80f0e06..c1af029 100644
--- a/examples/alpn/lib/http1_handler.ml
+++ b/examples/alpn/lib/http1_handler.ml
@@ -1,4 +1,4 @@
-open Httpaf
+open Httpun
 
 let redirect_handler : Unix.sockaddr -> Reqd.t Gluten.reqd -> unit =
  fun _client_address { Gluten.reqd; _ } ->
diff --git a/examples/alpn/mirage/config.ml b/examples/alpn/mirage/config.ml
index 386eada..0cabb9a 100644
--- a/examples/alpn/mirage/config.ml
+++ b/examples/alpn/mirage/config.ml
@@ -13,11 +13,13 @@ let secrets = generic_kv_ro "../../../certificates"
 let server =
   let packages =
     [ package "tls-mirage"
-    ; package ~pin:"git+https://github.com/anmonteiro/httpaf#fork" "httpaf"
-    ; package ~pin:"git+https://github.com/anmonteiro/httpaf#fork" "httpaf-lwt"
+    ; package ~pin:"git+https://github.com/anmonteiro/httpun#master" "httpun"
     ; package
-        ~pin:"git+https://github.com/anmonteiro/httpaf#fork"
-        "httpaf-mirage"
+        ~pin:"git+https://github.com/anmonteiro/httpun#master"
+        "httpun-lwt"
+    ; package
+        ~pin:"git+https://github.com/anmonteiro/httpun#master"
+        "httpun-mirage"
     ; package ~pin:"file://../../.." "h2"
     ; package ~pin:"file://../../.." "h2-lwt"
     ; package ~pin:"file://../../.." "h2-mirage"
diff --git a/examples/alpn/mirage/http1_handler.ml b/examples/alpn/mirage/http1_handler.ml
index 1ce1131..fc66a08 100644
--- a/examples/alpn/mirage/http1_handler.ml
+++ b/examples/alpn/mirage/http1_handler.ml
@@ -1,4 +1,4 @@
-open Httpaf
+open Httpun
 
 let redirect_handler : Reqd.t Gluten.reqd -> unit =
  fun { Gluten.reqd; _ } ->
diff --git a/examples/alpn/mirage/unikernel.ml b/examples/alpn/mirage/unikernel.ml
index 1faf0ad..51fbe07 100644
--- a/examples/alpn/mirage/unikernel.ml
+++ b/examples/alpn/mirage/unikernel.ml
@@ -20,7 +20,7 @@
  *)
 open Lwt.Infix
 
-module type HTTP = Httpaf_mirage.Server
+module type HTTP = Httpun_mirage.Server
 module type HTTP2 = H2_mirage.Server
 
 module Dispatch (Http : HTTP) (Https : HTTP) (Http2 : HTTP2) = struct
@@ -53,8 +53,8 @@ struct
   module X509 = Tls_mirage.X509 (KEYS) (Clock)
   module TCP = S.TCPV4
   module TLS = Tls_mirage.Make (TCP)
-  module Http = Httpaf_mirage.Server (TCP)
-  module Https = Httpaf_mirage.Server (TLS)
+  module Http = Httpun_mirage.Server (TCP)
+  module Https = Httpun_mirage.Server (TLS)
   module Http2 = H2_mirage.Server (TLS)
   module D = Dispatch (Http) (Https) (Http2)
 
diff --git a/examples/alpn/unix/alpn_server_ssl.ml b/examples/alpn/unix/alpn_server_ssl.ml
index f56aa4b..d833b32 100644
--- a/examples/alpn/unix/alpn_server_ssl.ml
+++ b/examples/alpn/unix/alpn_server_ssl.ml
@@ -1,7 +1,7 @@
 open Alpn_lib
 
 let http1_handler =
-  Httpaf_lwt_unix.Server.SSL.create_connection_handler
+  Httpun_lwt_unix.Server.SSL.create_connection_handler
     ?config:None
     ~request_handler:Http1_handler.request_handler
     ~error_handler:Http1_handler.error_handler
@@ -17,7 +17,7 @@ let start_http_server () =
   Lwt.async (fun () ->
     Lwt_io.establish_server_with_client_socket
       listen_address
-      (Httpaf_lwt_unix.Server.create_connection_handler
+      (Httpun_lwt_unix.Server.create_connection_handler
          ?config:None
          ~request_handler:Http1_handler.redirect_handler
          ~error_handler:Http1_handler.redirect_error_handler)
diff --git a/examples/alpn/unix/alpn_server_tls.ml b/examples/alpn/unix/alpn_server_tls.ml
index 103a08c..56d6b4a 100644
--- a/examples/alpn/unix/alpn_server_tls.ml
+++ b/examples/alpn/unix/alpn_server_tls.ml
@@ -1,7 +1,7 @@
 open Alpn_lib
 
 let http1_handler =
-  Httpaf_lwt_unix.Server.TLS.create_connection_handler
+  Httpun_lwt_unix.Server.TLS.create_connection_handler
     ?config:None
     ~request_handler:Http1_handler.request_handler
     ~error_handler:Http1_handler.error_handler
@@ -18,7 +18,7 @@ let start_http_server () =
   Lwt.async (fun () ->
     Lwt_io.establish_server_with_client_socket
       listen_address
-      (Httpaf_lwt_unix.Server.create_connection_handler
+      (Httpun_lwt_unix.Server.create_connection_handler
          ?config:None
          ~request_handler:Http1_handler.redirect_handler
          ~error_handler:Http1_handler.redirect_error_handler)
diff --git a/examples/lwt/dune b/examples/lwt/dune
index 944f733..26ecbb7 100644
--- a/examples/lwt/dune
+++ b/examples/lwt/dune
@@ -5,7 +5,7 @@
 
 (executable
  (name lwt_h2c)
- (libraries h2 httpaf-lwt-unix h2-lwt-unix lwt.unix)
+ (libraries h2 httpun-lwt-unix h2-lwt-unix lwt.unix)
  (modules lwt_h2c))
 
 (alias
diff --git a/examples/lwt/lwt_h2c.ml b/examples/lwt/lwt_h2c.ml
index e9ebcb1..625989c 100644
--- a/examples/lwt/lwt_h2c.ml
+++ b/examples/lwt/lwt_h2c.ml
@@ -4,7 +4,7 @@ module Http2 = struct
   open H2
 
   let connection_handler :
-       Httpaf.Request.t
+       Httpun.Request.t
       -> Bigstringaf.t H2.IOVec.t list
       -> (Server_connection.t, string) result
     =
@@ -67,20 +67,23 @@ module Http2 = struct
       Body.Writer.close response_body
     in
     fun http_request request_body ->
+      let { Httpun.Request.headers; target; meth; _ } = http_request in
       H2.Server_connection.create_h2c
         ?config:None
-        ~http_request
+        ~headers
+        ~target
+        ~meth
         ~request_body
         ~error_handler
         request_handler
 end
 
 let connection_handler =
-  let module Body = Httpaf.Body in
-  let module Headers = Httpaf.Headers in
-  let module Reqd = Httpaf.Reqd in
-  let module Response = Httpaf.Response in
-  let module Status = Httpaf.Status in
+  let module Body = Httpun.Body in
+  let module Headers = Httpun.Headers in
+  let module Reqd = Httpun.Reqd in
+  let module Response = Httpun.Response in
+  let module Status = Httpun.Status in
   let upgrade_handler request upgrade () =
     let off = 0 in
     let len = 3 in
@@ -106,7 +109,7 @@ let connection_handler =
     Body.Writer.write_string body message;
     Body.Writer.close body
   in
-  let request_handler _addr (reqd : Httpaf.Reqd.t Gluten.reqd) =
+  let request_handler _addr (reqd : Httpun.Reqd.t Gluten.reqd) =
     let { Gluten.reqd; upgrade } = reqd in
     let headers =
       Headers.of_list [ "Connection", "Upgrade"; "Upgrade", "h2c" ]
@@ -114,7 +117,7 @@ let connection_handler =
     let request = Reqd.request reqd in
     Reqd.respond_with_upgrade reqd headers (upgrade_handler request upgrade)
   in
-  Httpaf_lwt_unix.Server.create_connection_handler
+  Httpun_lwt_unix.Server.create_connection_handler
     ?config:None
     ~request_handler
     ~error_handler:http_error_handler
diff --git a/flake.lock b/flake.lock
index 28f0b10..f0b0f49 100644
--- a/flake.lock
+++ b/flake.lock
@@ -41,11 +41,11 @@
         "nixpkgs": "nixpkgs_2"
       },
       "locked": {
-        "lastModified": 1714205373,
-        "narHash": "sha256-pJ23nukPsPDNLl6RfLk+DV0yOaDX9MB6+m4D69jA/6w=",
+        "lastModified": 1719173709,
+        "narHash": "sha256-ueHl65dnQ4xFOQUk5XH2UB/E5YlRb/7zDFPoef0Ggw0=",
         "owner": "anmonteiro",
         "repo": "nix-overlays",
-        "rev": "1d087211e4fe2e8f2ed2bae30c3fb012860a8943",
+        "rev": "d41c30fd3c30fb2d809b1d00675d945a21363388",
         "type": "github"
       },
       "original": {
@@ -56,17 +56,17 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1714145718,
-        "narHash": "sha256-imUdbvnjqEHGsMr2c5Y/Xd52wbnyy90sUVT4rTye0Ks=",
+        "lastModified": 1719146883,
+        "narHash": "sha256-DAyIfQgyqalov0DcEKRvDOUin7axELasaP6NCPt7UQA=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "cf80486d25bdf7859196f4960f66edaf88eb7c64",
+        "rev": "084f8df2f3ff80cdec6f515931036f63c5d2f36c",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "cf80486d25bdf7859196f4960f66edaf88eb7c64",
+        "rev": "084f8df2f3ff80cdec6f515931036f63c5d2f36c",
         "type": "github"
       }
     },
diff --git a/flake.nix b/flake.nix
index 379421e..0acc7e7 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,7 +10,7 @@
     flake-utils.lib.eachDefaultSystem (system:
       let
         pkgs = nixpkgs.legacyPackages."${system}".extend (self: super: {
-          ocamlPackages = super.ocaml-ng.ocamlPackages_5_1;
+          ocamlPackages = super.ocaml-ng.ocamlPackages_5_2;
         });
       in
       rec {
diff --git a/h2.opam b/h2.opam
index dda297b..c95de6e 100644
--- a/h2.opam
+++ b/h2.opam
@@ -3,7 +3,7 @@ opam-version: "2.0"
 synopsis:
   "A high-performance, memory-efficient, and scalable HTTP/2 library for OCaml"
 description:
-  "h2 is an implementation of the HTTP/2 specification entirely in OCaml. It is based on the concepts in http/af, and therefore uses the Angstrom and Faraday libraries to implement the parsing and serialization layers of the HTTP/2 standard as a state machine that is agnostic to the underlying I/O specifics. It also preserves the same API as http/af wherever possible."
+  "h2 is an implementation of the HTTP/2 specification entirely in OCaml. It is based on the concepts in httpun, and therefore uses the Angstrom and Faraday libraries to implement the parsing and serialization layers of the HTTP/2 standard as a state machine that is agnostic to the underlying I/O specifics. It also preserves the same API as httpun wherever possible."
 maintainer: ["Antonio Nuno Monteiro <anmonteiro@gmail.com>"]
 authors: ["Antonio Nuno Monteiro <anmonteiro@gmail.com>"]
 license: "BSD-3-clause"
@@ -18,7 +18,7 @@ depends: [
   "bigstringaf" {>= "0.5.0"}
   "psq"
   "hpack" {= version}
-  "httpaf"
+  "httpun-types"
   "alcotest" {with-test}
   "yojson" {with-test}
   "hex" {with-test}
diff --git a/lib/body.ml b/lib/body.ml
index 0d1001f..af071c3 100644
--- a/lib/body.ml
+++ b/lib/body.ml
@@ -77,7 +77,7 @@ module Reader = struct
       t.read_scheduled <- false;
       t.on_eof <- default_on_eof;
       t.on_read <- default_on_read;
-      let { Httpaf.IOVec.buffer; off; len } = iovec in
+      let { Httpun_types.IOVec.buffer; off; len } = iovec in
       Faraday.shift t.faraday len;
       on_read buffer ~off ~len;
       (* Application is done reading, we can give flow control tokens back to
@@ -160,8 +160,8 @@ module Writer = struct
     | `Yield | `Close -> 0
     | `Writev iovecs ->
       let buffered = t.buffered_bytes in
-      let iovecs = Httpaf.IOVec.shiftv iovecs !buffered in
-      let lengthv = Httpaf.IOVec.lengthv iovecs in
+      let iovecs = Httpun_types.IOVec.shiftv iovecs !buffered in
+      let lengthv = Httpun_types.IOVec.lengthv iovecs in
       let writev_len = if max_bytes < lengthv then max_bytes else lengthv in
       buffered := !buffered + writev_len;
       let frame_info = Writer.make_frame_info ~max_frame_size stream_id in
diff --git a/lib/client_connection.ml b/lib/client_connection.ml
index 1d3d9d1..2fa9cf9 100644
--- a/lib/client_connection.ml
+++ b/lib/client_connection.ml
@@ -214,12 +214,12 @@ let handle_push_promise_headers t respd headers =
      *   error (Section 5.4.2) of type PROTOCOL_ERROR. *)
     report_stream_error t respd.Stream.id Error_code.ProtocolError
   | `Valid (meth, path, scheme) ->
-    let meth = Httpaf.Method.of_string meth in
+    let meth = Httpun_types.Method.of_string meth in
     (match
        meth, Headers.get_pseudo headers "authority", Message.body_length headers
      with
-    | (#Httpaf.Method.standard as meth), _, _
-      when not Httpaf.Method.(is_cacheable meth && is_safe meth) ->
+    | (#Httpun_types.Method.standard as meth), _, _
+      when not Httpun_types.Method.(is_cacheable meth && is_safe meth) ->
       report_stream_error t respd.id Error_code.ProtocolError
     | _, _, `Fixed len when not (Int64.equal len 0L) ->
       (* From RFC7540§8.2:
@@ -1331,12 +1331,13 @@ let create_and_add_stream t ~error_handler =
 let create_h2c
     ?config
     ?push_handler
-    ~http_request
+    ~headers
+    ~target
+    ~meth
     ~error_handler
     (response_handler, response_error_handler)
   =
-  let { Httpaf.Request.target; meth; _ } = http_request in
-  match Headers.of_http1 http_request with
+  match Headers.of_http1 ~headers ~target ~meth with
   | Ok headers ->
     (* From RFC7540§3.2:
      *   Upon receiving the 101 response, the client MUST send a connection
diff --git a/lib/dune b/lib/dune
index 5c031b1..b56d9f2 100644
--- a/lib/dune
+++ b/lib/dune
@@ -1,4 +1,4 @@
 (library
  (name h2)
  (public_name h2)
- (libraries angstrom base64 faraday bigstringaf httpaf psq hpack))
+ (libraries angstrom base64 faraday bigstringaf httpun-types psq hpack))
diff --git a/lib/h2.ml b/lib/h2.ml
index f566d0f..ff89bb8 100644
--- a/lib/h2.ml
+++ b/lib/h2.ml
@@ -33,8 +33,8 @@
  *---------------------------------------------------------------------------*)
 
 module Headers = Headers
-module IOVec = Httpaf.IOVec
-module Method = Httpaf.Method
+module IOVec = Httpun_types.IOVec
+module Method = Httpun_types.Method
 module Reqd = Reqd
 module Request = Request
 module Response = Response
diff --git a/lib/h2.mli b/lib/h2.mli
index 32370ed..d2c79e6 100644
--- a/lib/h2.mli
+++ b/lib/h2.mli
@@ -33,18 +33,18 @@
  *---------------------------------------------------------------------------*)
 
 (** H2 is a high-performance, memory-efficient, and scalable HTTP/2
-    implementation for OCaml. It is based on the concepts in http/af, and
-    therefore uses the Angstrom and Faraday libraries to implement the parsing
-    and serialization layers of the HTTP/2 standard. It also preserves the same
-    API as http/af wherever possible.
+    implementation for OCaml. It is based on the concepts introduced http/af,
+  and therefore uses the Angstrom and Faraday libraries to implement the
+  parsing and serialization layers of the HTTP/2 standard. It preserves
+  the same API as httpun wherever possible.
 
-    Not unlike http/af, the user should be familiar with HTTP, and the basic
-    principles of memory management and vectorized IO in order to use this
-    library. *)
+  Not unlike httpun, the user should be familiar with HTTP, and the basic
+  principles of memory management and vectorized IO in order to use this
+  library. *)
 
 (** {2 Basic HTTP Types} *)
 
-module Method : module type of Httpaf.Method
+module Method : module type of Httpun_types.Method
 (** Request Method
 
     The request method token is the primary source of request semantics; it
@@ -54,7 +54,7 @@ module Method : module type of Httpaf.Method
     See {{:https://tools.ietf.org/html/rfc7231#section-4} RFC7231§4} for more
     details.
 
-    This module is a proxy to [Httpaf.Method] and is included in h2 for
+    This module is a proxy to [Httpun_types.Method] and is included in h2 for
     convenience. *)
 
 (** Response Status Codes
@@ -65,7 +65,7 @@ module Method : module type of Httpaf.Method
     See {{:https://tools.ietf.org/html/rfc7231#section-6} RFC7231§6} for more
     details.
 
-    This module is a strict superset of [Httpaf.Status]. Even though the HTTP/2
+    This module is a strict superset of [Httpun_types.Status]. Even though the HTTP/2
     specification removes support for the [Switching_protocols] status code, h2
     keeps it for the sake of higher level interaction between OCaml libraries
     that support both HTTP/1 and HTTP/2.
@@ -74,13 +74,13 @@ module Method : module type of Httpaf.Method
     more details. *)
 module Status : sig
   include
-    module type of Httpaf.Status
-    with type client_error := Httpaf.Status.client_error
-     and type standard := Httpaf.Status.standard
-     and type t := Httpaf.Status.t
+    module type of Httpun_types.Status
+    with type client_error := Httpun_types.Status.client_error
+     and type standard := Httpun_types.Status.standard
+     and type t := Httpun_types.Status.t
 
   type client_error =
-    [ Httpaf.Status.client_error
+    [ Httpun_types.Status.client_error
     | `Misdirected_request
     ]
   (** The 4xx (Client Error) class of status code indicates that the client
@@ -89,13 +89,13 @@ module Status : sig
       See {{:https://tools.ietf.org/html/rfc7231#section-6.5} RFC7231§6.5} for
       more details.
 
-      In addition to http/af, this type also includes the 421 (Misdirected
+      In addition to httpun, this type also includes the 421 (Misdirected
       Request) tag. See
       {{:https://tools.ietf.org/html/rfc7540#section-9.1.2} RFC7540§9.1.2} for
       more details. *)
 
   type standard =
-    [ Httpaf.Status.standard
+    [ Httpun_types.Status.standard
     | client_error
     ]
   (** The status codes defined in the HTTP/1.1 RFCs, excluding the
@@ -449,7 +449,7 @@ module Response : sig
     -> Status.t
     -> t
   (** [create ?headers status] creates an HTTP response with the given
-      parameters. Unlike the [Response] type in http/af, h2 does not define a
+      parameters. Unlike the [Response] type in httpun, h2 does not define a
       way for responses to carry reason phrases or protocol version.
 
       See
@@ -470,7 +470,7 @@ module Response : sig
   val pp_hum : Format.formatter -> t -> unit
 end
 
-module IOVec : module type of Httpaf.IOVec
+module IOVec : module type of Httpun_types.IOVec
 (** IOVec *)
 
 (** {2 Request Descriptor} *)
@@ -711,7 +711,9 @@ module Server_connection : sig
   val create_h2c :
      ?config:Config.t
     -> ?error_handler:error_handler
-    -> http_request:Httpaf.Request.t
+    -> headers:Httpun_types.Headers.t
+    -> target:string
+    -> meth:Httpun_types.Method.t
     -> ?request_body:Bigstringaf.t IOVec.t list
     -> request_handler
     -> (t, string) result
@@ -843,7 +845,9 @@ module Client_connection : sig
   val create_h2c :
      ?config:Config.t
     -> ?push_handler:(Request.t -> (response_handler, unit) result)
-    -> http_request:Httpaf.Request.t
+    -> headers:Httpun_types.Headers.t
+    -> target:string
+    -> meth:Httpun_types.Method.t
     -> error_handler:error_handler
     -> response_handler * error_handler
     -> (t, string) result
diff --git a/lib/headers.ml b/lib/headers.ml
index ccc73b6..a88d335 100644
--- a/lib/headers.ml
+++ b/lib/headers.ml
@@ -304,8 +304,8 @@ let is_valid_h2c_connection connection =
   | Some _, Some _ -> true
   | _ -> false
 
-let of_http1 { Httpaf.Request.headers; meth; target; _ } =
-  let module Headers = Httpaf.Headers in
+let of_http1 ~headers ~meth ~target =
+  let module Headers = Httpun_types.Headers in
   match Headers.get headers "host" with
   | Some host ->
     (* From RFC7540§8.1.2.3:
@@ -335,7 +335,7 @@ let of_http1 { Httpaf.Request.headers; meth; target; _ } =
             (name, value) :: acc)
         ~init:
           [ ":authority", host
-          ; ":method", Httpaf.Method.to_string meth
+          ; ":method", Httpun_types.Method.to_string meth
           ; ":path", target
           ; ":scheme", "https"
           ]
diff --git a/lib/reqd.ml b/lib/reqd.ml
index 46496b3..21ab47e 100644
--- a/lib/reqd.ml
+++ b/lib/reqd.ml
@@ -48,7 +48,8 @@ type response_state =
   | Fixed of
       { response : Response.t
       ; mutable iovec :
-          [ `String of string | `Bigstring of Bigstringaf.t ] Httpaf.IOVec.t
+          [ `String of string | `Bigstring of Bigstringaf.t ]
+            Httpun_types.IOVec.t
       }
   | Streaming of
       { response : Response.t
@@ -155,11 +156,13 @@ let send_fixed_response (t : t) s response data =
       match data with
       | `String s ->
         let len = String.length s in
-        let iovec = { Httpaf.IOVec.buffer = `String s; off = 0; len } in
+        let iovec = { Httpun_types.IOVec.buffer = `String s; off = 0; len } in
         iovec, len
       | `Bigstring b ->
         let len = Bigstringaf.length b in
-        let iovec = { Httpaf.IOVec.buffer = `Bigstring b; off = 0; len } in
+        let iovec =
+          { Httpun_types.IOVec.buffer = `Bigstring b; off = 0; len }
+        in
         iovec, len
     in
     let should_send_data = length <> 0 in
@@ -503,7 +506,7 @@ let flush_response_body (t : t) ~max_bytes =
       in
       let len_to_write = if is_partial_flush then max_bytes else len in
       write_buffer_data t.writer ~off ~len:len_to_write frame_info buffer;
-      r.iovec <- Httpaf.IOVec.shift iovec len_to_write;
+      r.iovec <- Httpun_types.IOVec.shift iovec len_to_write;
       if not is_partial_flush then close_stream t;
       len_to_write
     | Fixed _ | Waiting | Complete _ -> 0)
diff --git a/lib/request.ml b/lib/request.ml
index 2be579a..0291142 100644
--- a/lib/request.ml
+++ b/lib/request.ml
@@ -33,7 +33,7 @@
  *---------------------------------------------------------------------------*)
 
 type t =
-  { meth : Httpaf.Method.t
+  { meth : Httpun_types.Method.t
   ; target : string
   ; scheme : string
   ; headers : Headers.t
@@ -49,7 +49,7 @@ let pp_hum fmt { meth; target; scheme; headers } =
   Format.fprintf
     fmt
     "((method \"%a\") (target %S) (scheme %S) (headers %a))"
-    Httpaf.Method.pp_hum
+    Httpun_types.Method.pp_hum
     meth
     target
     scheme
diff --git a/lib/response.ml b/lib/response.ml
index 2f7a6c6..5805e70 100644
--- a/lib/response.ml
+++ b/lib/response.ml
@@ -45,7 +45,7 @@ let create ?(headers = Headers.empty) status = { status; headers }
 let body_length ~request_method { headers; _ } =
   match request_method with
   | `HEAD -> `Fixed 0L
-  | #Httpaf.Method.standard -> Message.body_length headers
+  | #Httpun_types.Method.standard -> Message.body_length headers
 
 let pp_hum fmt { status; headers } =
   let reason =
diff --git a/lib/serialize.ml b/lib/serialize.ml
index f676e46..e015341 100644
--- a/lib/serialize.ml
+++ b/lib/serialize.ml
@@ -33,7 +33,7 @@
  *---------------------------------------------------------------------------*)
 
 open Faraday
-module IOVec = Httpaf.IOVec
+module IOVec = Httpun_types.IOVec
 
 type frame_info =
   { flags : Flags.t
@@ -469,7 +469,7 @@ module Writer = struct
       hpack_encoder
       faraday
       { Headers.name = ":method"
-      ; value = Httpaf.Method.to_string meth
+      ; value = Httpun_types.Method.to_string meth
       ; sensitive = false
       };
     if meth <> `CONNECT
diff --git a/lib/server_connection.ml b/lib/server_connection.ml
index 31ceae6..8164cd9 100644
--- a/lib/server_connection.ml
+++ b/lib/server_connection.ml
@@ -297,7 +297,11 @@ let handle_headers t ~end_stream stream active_stream headers =
       | `Error e -> set_error_and_handle t reqd e ProtocolError
       | `Fixed _ | `Unknown ->
         let request =
-          Request.create ~scheme ~headers (Httpaf.Method.of_string meth) path
+          Request.create
+            ~scheme
+            ~headers
+            (Httpun_types.Method.of_string meth)
+            path
         in
         let request_body =
           if end_stream
@@ -1261,7 +1265,7 @@ let handle_h2c_request t headers request_body_iovecs =
         (create_push_stream t)
     in
     t.max_client_stream_id <- reqd.Stream.id;
-    let lengthv = Httpaf.IOVec.lengthv request_body_iovecs in
+    let lengthv = Httpun_types.IOVec.lengthv request_body_iovecs in
     let end_stream = lengthv = 0 in
     handle_headers t ~end_stream stream active_stream headers;
     let request = Reqd.request reqd in
@@ -1281,7 +1285,7 @@ let handle_h2c_request t headers request_body_iovecs =
       if not (Faraday.is_closed faraday)
       then (
         List.iter
-          (fun { Httpaf.IOVec.buffer; off; len } ->
+          (fun { Httpun_types.IOVec.buffer; off; len } ->
              Faraday.schedule_bigstring faraday ~off ~len buffer)
           request_body_iovecs;
         (* Close the request body, we're not expecting more input. *)
@@ -1305,11 +1309,12 @@ let handle_h2c_request t headers request_body_iovecs =
 let create_h2c
     ?(config = Config.default)
     ?(error_handler = default_error_handler)
-    ~http_request
+    ~headers
+    ~target
+    ~meth
     ?(request_body = [])
     request_handler
   =
-  let { Httpaf.Request.headers; _ } = http_request in
   (* From RFC7540§3.2.1:
    *   A request that upgrades from HTTP/1.1 to HTTP/2 MUST include exactly one
    *   HTTP2-Settings header field.
@@ -1318,7 +1323,7 @@ let create_h2c
    *   field is not present or if more than one is present. A server MUST NOT
    *   send this header field. *)
   match
-    Httpaf.Headers.(
+    Httpun_types.Headers.(
       get_multi headers "http2-settings", get_multi headers "connection")
   with
   | [ settings ], [ connection ] when Headers.is_valid_h2c_connection connection
@@ -1333,7 +1338,7 @@ let create_h2c
      *   other SETTINGS frame. Explicit acknowledgement of these settings
      *   (Section 6.5.3) is not necessary, since a 101 response serves as
      *   implicit acknowledgement. *)
-    (match Headers.of_http1 http_request with
+    (match Headers.of_http1 ~headers ~target ~meth with
     | Ok h2_headers ->
       (match Settings.of_base64 settings with
       | Ok upgrade_settings ->
diff --git a/lib/status.ml b/lib/status.ml
index f1863bd..914e3b8 100644
--- a/lib/status.ml
+++ b/lib/status.ml
@@ -37,18 +37,18 @@
  *   status code ([RFC7231], Section 6.2.2).
  *
  *   Note: While the above is true, we don't enforce in this library, as it
- *   makes unifying types with http/af much easier. `H2.Status.t` is, thus, a
- *   strict superset of `Httpaf.Status.t`. *)
+ *   makes unifying types with httpun much easier. `H2.Status.t` is, thus, a
+ *   strict superset of `Httpun_types.Status.t`. *)
 
 include (
-  Httpaf.Status :
-    module type of Httpaf.Status
-    with type client_error := Httpaf.Status.client_error
-     and type standard := Httpaf.Status.standard
-     and type t := Httpaf.Status.t)
+  Httpun_types.Status :
+    module type of Httpun_types.Status
+    with type client_error := Httpun_types.Status.client_error
+     and type standard := Httpun_types.Status.standard
+     and type t := Httpun_types.Status.t)
 
 type client_error =
-  [ Httpaf.Status.client_error
+  [ Httpun_types.Status.client_error
   | (* From RFC7540§9.1.2:
      *   The 421 (Misdirected Request) status code indicates that the request
      *   was directed at a server that is not able to produce a response. This
@@ -59,7 +59,7 @@ type client_error =
   ]
 
 type standard =
-  [ Httpaf.Status.standard
+  [ Httpun_types.Status.standard
   | client_error
   ]
 
@@ -76,47 +76,48 @@ type t =
  *   included in an HTTP/1.1 status line. *)
 let default_reason_phrase = function
   | `Misdirected_request -> "Misdirected Request"
-  | #Httpaf.Status.standard as t -> Httpaf.Status.default_reason_phrase t
+  | #Httpun_types.Status.standard as t ->
+    Httpun_types.Status.default_reason_phrase t
 
 let to_code = function
   | `Misdirected_request -> 421
-  | #Httpaf.Status.t as t -> Httpaf.Status.to_code t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.to_code t
 
 let unsafe_of_code = function
   | 421 -> `Misdirected_request
-  | c -> (Httpaf.Status.unsafe_of_code c :> t)
+  | c -> (Httpun_types.Status.unsafe_of_code c :> t)
 
 let of_code = function
   | 421 -> `Misdirected_request
-  | c -> (Httpaf.Status.of_code c :> t)
+  | c -> (Httpun_types.Status.of_code c :> t)
 
 let is_informational = function
   | `Misdirected_request -> false
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_informational t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_informational t
 
 let is_successful = function
   | `Misdirected_request -> false
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_successful t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_successful t
 
 let is_redirection = function
   | `Misdirected_request -> false
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_redirection t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_redirection t
 
 let is_client_error = function
   | `Misdirected_request -> true
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_client_error t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_client_error t
 
 let is_server_error = function
   | `Misdirected_request -> false
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_server_error t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_server_error t
 
 let is_error = function
   | `Misdirected_request -> true
-  | #Httpaf.Status.t as t -> Httpaf.Status.is_error t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.is_error t
 
 let to_string = function
   | `Misdirected_request -> "421"
-  | #Httpaf.Status.t as t -> Httpaf.Status.to_string t
+  | #Httpun_types.Status.t as t -> Httpun_types.Status.to_string t
 
 let of_string x = of_code (int_of_string x)
 let pp_hum fmt t = Format.fprintf fmt "%u" (to_code t)
diff --git a/nix/default.nix b/nix/default.nix
index 8728ca2..50774c4 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -33,7 +33,7 @@ let
         faraday
         base64
         psq
-        httpaf
+        httpun
       ] ++ [ h2Pkgs.hpack ];
     };
 
diff --git a/nix/shell.nix b/nix/shell.nix
index caf7beb..c7b8ba7 100644
--- a/nix/shell.nix
+++ b/nix/shell.nix
@@ -25,7 +25,14 @@ in
       ocamlPackages.dune-release
       git
     ] else [ ])
-    ++ (with ocamlPackages; [ merlin ocamlformat utop h2spec httpaf-lwt-unix tls-lwt ]);
+    ++ (with ocamlPackages; [
+      merlin
+      ocamlformat
+      utop
+      h2spec
+      httpun-lwt-unix
+      tls-lwt
+    ]);
 }).overrideAttrs (o: {
   propagatedBuildInputs = lib.filter
     (drv: drv.pname == null || !(lib.any (name: name == drv.pname) (lib.attrNames h2Drvs)))


Test patch:
diff --git a/lib_test/test_common.ml b/lib_test/test_common.ml
index 74c76ca..c826142 100644
--- a/lib_test/test_common.ml
+++ b/lib_test/test_common.ml
@@ -25,7 +25,7 @@ let hex_of_string s =
   String.uppercase_ascii hex
 
 let make_iovecs bs =
-  [ { Httpaf.IOVec.buffer = bs; off = 0; len = Bigstringaf.length bs } ]
+  [ { Httpun_types.IOVec.buffer = bs; off = 0; len = Bigstringaf.length bs } ]
 
 let write_frame ?padding t { Frame.frame_header; frame_payload } =
   let open Serialize in
diff --git a/lib_test/test_h2_client.ml b/lib_test/test_h2_client.ml
index c817d9a..3f9feb0 100644
--- a/lib_test/test_h2_client.ml
+++ b/lib_test/test_h2_client.ml
@@ -916,10 +916,13 @@ module Client_connection_tests = struct
     let f = Faraday.create 100 in
     Settings.write_settings_payload f settings_payload;
     let serialized_settings = Faraday.serialize_to_string f in
-    let http_request =
-      Httpaf.Request.create
+    let response_handler_called = ref false in
+    match
+      create_h2c
+        ~meth:`GET
+        ~target:"/"
         ~headers:
-          (Httpaf.Headers.of_list
+          (Httpun_types.Headers.of_list
              [ "Connection", "Upgrade, HTTP2-Settings"
              ; "Upgrade", "h2c"
              ; ( "HTTP2-Settings"
@@ -928,13 +931,6 @@ module Client_connection_tests = struct
                )
              ; "Host", "localhost"
              ])
-        `GET
-        "/"
-    in
-    let response_handler_called = ref false in
-    match
-      create_h2c
-        ~http_request
         ~error_handler:default_error_handler
         ((fun _ _ -> response_handler_called := true), fun _ -> assert false)
     with
diff --git a/lib_test/test_h2_server.ml b/lib_test/test_h2_server.ml
index 73c6268..7fe2f1c 100644
--- a/lib_test/test_h2_server.ml
+++ b/lib_test/test_h2_server.ml
@@ -907,10 +907,13 @@ module Server_connection_tests = struct
     let f = Faraday.create 100 in
     Settings.write_settings_payload f settings_payload;
     let serialized_settings = Faraday.serialize_to_string f in
-    let http_request =
-      Httpaf.Request.create
+    let request_handler_called = ref false in
+    match
+      create_h2c
+        ~meth:`GET
+        ~target:"/"
         ~headers:
-          (Httpaf.Headers.of_list
+          (Httpun_types.Headers.of_list
              [ "Connection", "Upgrade, HTTP2-Settings"
              ; "Upgrade", "h2c"
              ; ( "HTTP2-Settings"
@@ -919,12 +922,7 @@ module Server_connection_tests = struct
                )
              ; "Host", "localhost"
              ])
-        `GET
-        "/"
-    in
-    let request_handler_called = ref false in
-    match
-      create_h2c ~http_request (fun _ -> request_handler_called := true)
+        (fun _ -> request_handler_called := true)
     with
     | Ok t ->
       Alcotest.(check bool)
diff --git a/lib_test/test_priority.ml b/lib_test/test_priority.ml
index 3111465..def1e2b 100644
--- a/lib_test/test_priority.ml
+++ b/lib_test/test_priority.ml
@@ -346,7 +346,7 @@ let reprioritization_tests =
 
 let () =
   Alcotest.run
-    "httpaf unit tests"
+    "h2 unit tests"
     [ "Reprioritization tests", reprioritization_tests
     ; "Priority_Queue_Tests", priority_queue_tests
     ]
diff --git a/nix/ci/test.nix b/nix/ci/test.nix
index 7fa6e64..7e4e155 100644
--- a/nix/ci/test.nix
+++ b/nix/ci/test.nix
@@ -64,7 +64,7 @@ stdenv.mkDerivation {
   '';
   buildInputs =
     (lib.attrValues h2Drvs) ++
-    (with ocamlPackages; [ ocaml dune findlib ocamlformat httpaf-lwt-unix ]) ++
+    (with ocamlPackages; [ ocaml dune findlib ocamlformat httpun-lwt-unix ]) ++
     (with pkgs; [ lsof h2spec ]);
   checkInputs = with ocamlPackages; [ alcotest hex yojson ];
   doCheck = true;