My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

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

Rename httpz to httpzo

- Rename directory httpz/ to httpzo/
- Update package name in dune-project and regenerate opam file
- Rename library and module from Httpz to Httpzo
- Update all internal module references
- Update CLI name, XDG config path, and server identity
- Update README.md package index

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+170 -170
+1 -1
README.md
··· 6 6 |------------|---------|----------| 7 7 | [**arod**](https://tangled.org/anil.recoil.org/arod) | arod | Webserver for Bushel content | 8 8 | [**braid**](https://github.com/avsm/braid) | braid | Build status tracker for opam overlay repositories | 9 - | [**httpz**](https://github.com/avsm/httpz.git) | httpz | HTTP/1.1 parser for OCaml 5 | 9 + | [**httpzo**](https://tangled.org/anil.recoil.org/httpzo) | httpzo | HTTP/1.1 parser for OCaml 5 | 10 10 | [**monopam**](https://tangled.org/anil.recoil.org/monopam.git) | monopam | Manage opam overlays with git subtree monorepos | 11 11 | [**ocaml-apubt**](https://tangled.org/anil.recoil.org/ocaml-apubt.git) | apubt | ActivityPub client library for OCaml with Eio | 12 12 | [**ocaml-atp**](https://tangled.org/anil.recoil.org/ocaml-atp.git) | atp | AT Protocol IPLD implementation for OCaml |
httpz/.gitignore httpzo/.gitignore
httpz/.ocamlformat httpzo/.ocamlformat
httpz/LICENSE.md httpzo/LICENSE.md
+10 -10
httpz/README.md httpzo/README.md
··· 1 - # httpz - Zero-Allocation HTTP/1.1 Parser for OxCaml 1 + # httpzo - Zero-Allocation HTTP/1.1 Parser for OxCaml 2 2 3 3 A high-performance HTTP/1.1 parser and serializer achieving zero heap 4 4 allocations using OxCaml's unboxed types (`int16#`, `int64#`, `char#`) and local allocations. ··· 15 15 16 16 ## Architecture 17 17 18 - httpz achieves zero-allocation parsing through: 18 + httpzo achieves zero-allocation parsing through: 19 19 20 20 1. **Unboxed records** (`#{...}`): Request, span, and header types are stack-allocated 21 21 2. **Unboxed primitives**: `int16#` for buffer offsets, `int64#` for content lengths, `char#` for byte comparisons ··· 25 25 26 26 ## Performance 27 27 28 - Benchmarks comparing httpz (OxCaml) vs httpe (Eio-based parser): 28 + Benchmarks comparing httpzo (OxCaml) vs httpe (Eio-based parser): 29 29 30 - | Request Size | httpz (ns/op) | httpe (ns/op) | Speedup | Allocation Reduction | 30 + | Request Size | httpzo (ns/op) | httpe (ns/op) | Speedup | Allocation Reduction | 31 31 |--------------|---------------|---------------|---------|---------------------| 32 32 | Small (35B) | 154 | 159 | 1.03x | 45x fewer words | 33 33 | Medium (439B)| 1,150 | 1,218 | 1.06x | 399x fewer words | ··· 58 58 59 59 ```bash 60 60 # Serve current directory on port 8080 61 - dune exec bin/httpz_server.exe 61 + dune exec bin/httpzo_server.exe 62 62 63 63 # Serve specific directory on custom port 64 - dune exec bin/httpz_server.exe -- -d /var/www -p 3000 64 + dune exec bin/httpzo_server.exe -- -d /var/www -p 3000 65 65 66 66 # Get help 67 - dune exec bin/httpz_server.exe -- -help 67 + dune exec bin/httpzo_server.exe -- -help 68 68 ``` 69 69 70 70 Features: ··· 77 77 ## Running Benchmarks 78 78 79 79 ```bash 80 - # Comparative benchmark (httpz vs httpe) 80 + # Comparative benchmark (httpzo vs httpe) 81 81 dune exec bench/bench_compare.exe 82 82 83 - # Detailed httpz benchmarks with core_bench 84 - dune exec bench/bench_httpz.exe -- -quota 2 83 + # Detailed httpzo benchmarks with core_bench 84 + dune exec bench/bench_httpzo.exe -- -quota 2 85 85 ``` 86 86 87 87 ## License
httpz/bench/bench_compare.ml httpzo/bench/bench_compare.ml
+34 -34
httpz/bench/bench_httpz.ml httpzo/bench/bench_httpz.ml
··· 1 - (* bench_httpz.ml - core_bench benchmarks for httpz HTTP parser *) 1 + (* bench_httpz.ml - core_bench benchmarks for httpzo HTTP parser *) 2 2 3 3 open Core 4 4 open Core_bench ··· 70 70 71 71 (* Benchmark helpers *) 72 72 73 - (* Helper to copy string into httpz bigarray buffer *) 73 + (* Helper to copy string into httpzo bigarray buffer *) 74 74 let copy_to_httpz_buffer buf data = 75 75 let len = String.length data in 76 76 for i = 0 to len - 1 do ··· 79 79 len 80 80 ;; 81 81 82 - let limits = Httpz.default_limits 83 - let i16 = Httpz.Buf_read.i16 82 + let limits = Httpzo.default_limits 83 + let i16 = Httpzo.Buf_read.i16 84 84 85 - (* Parse request using httpz - note: result is stack-allocated (local) *) 85 + (* Parse request using httpzo - note: result is stack-allocated (local) *) 86 86 let parse_request_httpz buf data = 87 87 let len = copy_to_httpz_buffer buf data in 88 - let #(status, req, headers) = Httpz.parse buf ~len:(i16 len) ~limits in 88 + let #(status, req, headers) = Httpzo.parse buf ~len:(i16 len) ~limits in 89 89 (* Extract values to prevent them from being optimized away *) 90 90 let _ = req.#body_off in 91 91 let _ = headers in ··· 95 95 (* Variant to test if List.length causes allocation *) 96 96 let parse_request_httpz_with_length buf data = 97 97 let len = copy_to_httpz_buffer buf data in 98 - let #(status, req, headers) = Httpz.parse buf ~len:(i16 len) ~limits in 98 + let #(status, req, headers) = Httpzo.parse buf ~len:(i16 len) ~limits in 99 99 let _ = req.#body_off in 100 100 let _ = List.length headers in 101 101 status ··· 109 109 110 110 (* Test parse only - assume data already in buffer *) 111 111 let just_parse_httpz buf len = 112 - let #(status, req, headers) = Httpz.parse buf ~len:(i16 len) ~limits in 112 + let #(status, req, headers) = Httpzo.parse buf ~len:(i16 len) ~limits in 113 113 let _ = req.#body_off in 114 114 let _ = headers in 115 115 status 116 116 ;; 117 117 118 118 (* Httpz parsing benchmarks *) 119 - let httpz_buf = Httpz.create_buffer () 119 + let httpz_buf = Httpzo.create_buffer () 120 120 let minimal_len = String.length minimal_request 121 121 122 122 (* Pre-populate buffer for parse-only test *) ··· 155 155 156 156 (* Httpz header lookup benchmarks *) 157 157 let httpz_header_benchmarks = 158 - let buf = Httpz.create_buffer () in 158 + let buf = Httpzo.create_buffer () in 159 159 let len = i16 (copy_to_httpz_buffer buf browser_request) in 160 160 [ Bench.Test.create ~name:"httpz_parse_and_find_host" (fun () -> 161 - let #(_status, _req, headers) = Httpz.parse buf ~len ~limits in 162 - ignore (Httpz.Header.find headers Httpz.Header_name.Host)) 161 + let #(_status, _req, headers) = Httpzo.parse buf ~len ~limits in 162 + ignore (Httpzo.Header.find headers Httpzo.Header_name.Host)) 163 163 ; Bench.Test.create ~name:"httpz_parse_and_is_keepalive" (fun () -> 164 - let #(_status, req, _headers) = Httpz.parse buf ~len ~limits in 164 + let #(_status, req, _headers) = Httpzo.parse buf ~len ~limits in 165 165 (* Now using cached keep_alive from request struct *) 166 166 ignore req.#keep_alive) 167 167 ; Bench.Test.create ~name:"httpz_parse_and_content_length" (fun () -> 168 - let #(_status, req, _headers) = Httpz.parse buf ~len ~limits in 168 + let #(_status, req, _headers) = Httpzo.parse buf ~len ~limits in 169 169 (* Now using cached content_length from request struct *) 170 170 ignore req.#content_length) 171 171 ] ··· 173 173 174 174 (* Httpz body handling benchmarks *) 175 175 let httpz_body_benchmarks = 176 - let buf = Httpz.create_buffer () in 176 + let buf = Httpzo.create_buffer () in 177 177 [ Bench.Test.create ~name:"httpz_body_100B" (fun () -> 178 178 let len = i16 (copy_to_httpz_buffer buf request_body_100) in 179 - let #(_status, req, _headers) = Httpz.parse buf ~len ~limits in 180 - let body = Httpz.Req.body_span ~len req in 179 + let #(_status, req, _headers) = Httpzo.parse buf ~len ~limits in 180 + let body = Httpzo.Req.body_span ~len req in 181 181 ignore body.#len) 182 182 ; Bench.Test.create ~name:"httpz_body_1KB" (fun () -> 183 183 let len = i16 (copy_to_httpz_buffer buf request_body_1k) in 184 - let #(_status, req, _headers) = Httpz.parse buf ~len ~limits in 185 - let body = Httpz.Req.body_span ~len req in 184 + let #(_status, req, _headers) = Httpzo.parse buf ~len ~limits in 185 + let body = Httpzo.Req.body_span ~len req in 186 186 ignore body.#len) 187 187 ; Bench.Test.create ~name:"httpz_body_10KB" (fun () -> 188 188 let len = i16 (copy_to_httpz_buffer buf request_body_10k) in 189 - let #(_status, req, _headers) = Httpz.parse buf ~len ~limits in 190 - let body = Httpz.Req.body_span ~len req in 189 + let #(_status, req, _headers) = Httpzo.parse buf ~len ~limits in 190 + let body = Httpzo.Req.body_span ~len req in 191 191 ignore body.#len) 192 192 ] 193 193 ;; ··· 197 197 let response_buf = Base_bigstring.create 4096 in 198 198 [ Bench.Test.create ~name:"httpz_write_status_line" (fun () -> 199 199 ignore 200 - (Httpz.Res.write_status_line 200 + (Httpzo.Res.write_status_line 201 201 response_buf 202 - ~off:(Httpz.Buf_write.i16 0) 203 - Httpz.Res.Success 204 - Httpz.Version.Http_1_1)) 202 + ~off:(Httpzo.Buf_write.i16 0) 203 + Httpzo.Res.Success 204 + Httpzo.Version.Http_1_1)) 205 205 ; Bench.Test.create ~name:"httpz_write_response_headers" (fun () -> 206 206 let off = 207 - Httpz.Res.write_status_line 207 + Httpzo.Res.write_status_line 208 208 response_buf 209 - ~off:(Httpz.Buf_write.i16 0) 210 - Httpz.Res.Success 211 - Httpz.Version.Http_1_1 209 + ~off:(Httpzo.Buf_write.i16 0) 210 + Httpzo.Res.Success 211 + Httpzo.Version.Http_1_1 212 212 in 213 - let off = Httpz.Res.write_header_name response_buf ~off Httpz.Header_name.Content_type "application/json" in 214 - let off = Httpz.Res.write_content_length response_buf ~off 1024 in 215 - let off = Httpz.Res.write_connection response_buf ~off ~keep_alive:true in 216 - let off = Httpz.Res.write_crlf response_buf ~off in 213 + let off = Httpzo.Res.write_header_name response_buf ~off Httpzo.Header_name.Content_type "application/json" in 214 + let off = Httpzo.Res.write_content_length response_buf ~off 1024 in 215 + let off = Httpzo.Res.write_connection response_buf ~off ~keep_alive:true in 216 + let off = Httpzo.Res.write_crlf response_buf ~off in 217 217 ignore off) 218 218 ] 219 219 ;; 220 220 221 221 (* Httpz throughput benchmarks *) 222 222 let httpz_throughput_benchmarks = 223 - let buf = Httpz.create_buffer () in 223 + let buf = Httpzo.create_buffer () in 224 224 let iterations = 1000 in 225 225 [ Bench.Test.create ~name:"httpz_1k_simple" (fun () -> 226 226 for _ = 1 to iterations do
+1 -1
httpz/bench/dune httpzo/bench/dune
··· 1 1 ; Benchmarks temporarily disabled - to be ported to Eio 2 2 ; (executables 3 3 ; (names bench_httpz bench_compare) 4 - ; (libraries httpz base core core_bench)) 4 + ; (libraries httpzo base core core_bench))
httpz/bench/vendor/dune httpzo/bench/vendor/dune
httpz/bench/vendor/httpe.ml httpzo/bench/vendor/httpe.ml
-5
httpz/bin/dune
··· 1 - (executable 2 - (name httpz_server) 3 - (public_name httpz) 4 - (package httpz) 5 - (libraries httpz eio eio_main cmdliner xdge tomlt tomlt.unix))
+10 -10
httpz/bin/httpz_server.ml httpzo/bin/httpz_server.ml
··· 1 - (* httpz_server.ml - Minimal CLI for httpz static file server *) 1 + (* httpz_server.ml - Minimal CLI for httpzo static file server *) 2 2 3 3 open Cmdliner 4 4 ··· 45 45 46 46 (* Build limits from config file and defaults *) 47 47 let build_limits ?config () = 48 - let defaults = Httpz.default_limits in 48 + let defaults = Httpzo.default_limits in 49 49 match config with 50 50 | None -> defaults 51 51 | Some c -> 52 - { Httpz.Buf_read.max_content_length = 52 + { Httpzo.Buf_read.max_content_length = 53 53 Option.value c.max_content_length ~default:defaults.max_content_length 54 54 ; max_header_size = 55 55 Option.value c.max_header_size ~default:defaults.max_header_size ··· 82 82 let limits = build_limits ?config:file_config () in 83 83 let fs = Eio.Stdenv.fs env in 84 84 let root = Eio.Path.(fs / root_str) in 85 - let config = Httpz.Server.{ port; root; limits } in 85 + let config = Httpzo.Server.{ port; root; limits } in 86 86 Eio.Switch.run @@ fun sw -> 87 - Httpz.Server.run ~net:(Eio.Stdenv.net env) ~sw config 87 + Httpzo.Server.run ~net:(Eio.Stdenv.net env) ~sw config 88 88 89 89 (* Cmdliner term *) 90 90 let main_term = 91 91 let run port root = 92 92 Eio_main.run @@ fun env -> 93 93 let fs = Eio.Stdenv.fs env in 94 - let xdg = Xdge.create fs "httpz" in 94 + let xdg = Xdge.create fs "httpzo" in 95 95 run_server env xdg port root 96 96 in 97 97 Term.(const run $ port_arg $ root_arg) 98 98 99 99 let cmd = 100 - let doc = "Static file server using httpz" in 100 + let doc = "Static file server using httpzo" in 101 101 let man = [ 102 102 `S Manpage.s_description; 103 103 `P "Serves static files over HTTP/1.1 with support for:"; ··· 106 106 `I ("If-None-Match", "Conditional requests returning 304"); 107 107 `I ("Keep-alive", "Connection reuse for HTTP/1.1"); 108 108 `S Manpage.s_files; 109 - `P "Configuration is read from $(b,~/.config/httpz/config.toml) or \ 109 + `P "Configuration is read from $(b,~/.config/httpzo/config.toml) or \ 110 110 the path specified by $(b,XDG_CONFIG_HOME)."; 111 111 `P "Example config.toml:"; 112 112 `Pre "port = 8080\n\ 113 113 root = \"/var/www/html\"\n\ 114 114 max_content_length = 104857600"; 115 115 `S Manpage.s_environment; 116 - `P "$(b,HTTPZ_CONFIG_DIR): Override configuration directory."; 116 + `P "$(b,HTTPZO_CONFIG_DIR): Override configuration directory."; 117 117 `P "$(b,XDG_CONFIG_HOME): XDG base directory for config files."; 118 118 ] in 119 - let info = Cmd.info "httpz" ~version:"0.1" ~doc ~man in 119 + let info = Cmd.info "httpzo" ~version:"0.1" ~doc ~man in 120 120 Cmd.v info main_term 121 121 122 122 let () = exit (Cmd.eval cmd)
httpz/dune httpzo/dune
+4 -4
httpz/dune-project httpzo/dune-project
··· 1 - (lang dune 3.20) 2 - (name httpz) 1 + (lang dune 3.21) 2 + (name httpzo) 3 3 4 4 (generate_opam_files true) 5 5 6 - (source (github avsm/httpz)) 7 6 (license ISC) 8 7 (authors "Anil Madhavapeddy") 9 8 (maintainers "anil@recoil.org") 9 + (source (tangled anil.recoil.org/httpzo)) 10 10 11 11 (package 12 - (name httpz) 12 + (name httpzo) 13 13 (synopsis "HTTP/1.1 parser for OCaml 5") 14 14 (description 15 15 "A high-performance HTTP/1.1 parser and serializer for OCaml 5. Includes
+4 -4
httpz/httpz.opam httpzo/httpzo.opam
··· 7 7 maintainer: ["anil@recoil.org"] 8 8 authors: ["Anil Madhavapeddy"] 9 9 license: "ISC" 10 - homepage: "https://github.com/avsm/httpz" 11 - bug-reports: "https://github.com/avsm/httpz/issues" 10 + homepage: "https://tangled.org/anil.recoil.org/httpzo" 11 + bug-reports: "https://tangled.org/anil.recoil.org/httpzo/issues" 12 12 depends: [ 13 - "dune" {>= "3.20"} 13 + "dune" {>= "3.21"} 14 14 "ocaml" {>= "5.1"} 15 15 "base" 16 16 "base_bigstring" ··· 37 37 "@doc" {with-doc} 38 38 ] 39 39 ] 40 - dev-repo: "git+https://github.com/avsm/httpz.git" 40 + dev-repo: "git+https://tangled.org/anil.recoil.org/httpzo" 41 41 x-maintenance-intent: ["(latest)"]
httpz/lib/buf_read.ml httpzo/lib/buf_read.ml
httpz/lib/buf_read.mli httpzo/lib/buf_read.mli
httpz/lib/buf_write.ml httpzo/lib/buf_write.ml
httpz/lib/buf_write.mli httpzo/lib/buf_write.mli
+1 -1
httpz/lib/chunk.ml httpzo/lib/chunk.ml
··· 175 175 | _ -> false 176 176 ;; 177 177 178 - (* Parse a single trailer header, similar to httpz.ml:parse_header *) 178 + (* Parse a single trailer header, similar to httpzo.ml:parse_header *) 179 179 let parse_trailer_header buf ~pos ~len = 180 180 let colon_pos = ref pos in 181 181 while !colon_pos < len && Buf_read.is_token_char (Buf_read.peek buf !colon_pos) do
httpz/lib/chunk.mli httpzo/lib/chunk.mli
httpz/lib/date.ml httpzo/lib/date.ml
httpz/lib/date.mli httpzo/lib/date.mli
+3 -3
httpz/lib/dune httpzo/lib/dune
··· 1 1 (library 2 - (name httpz) 3 - (public_name httpz) 2 + (name httpzo) 3 + (public_name httpzo) 4 4 (modules 5 5 buf_read 6 6 buf_write ··· 19 19 range 20 20 request_parse 21 21 server 22 - httpz) 22 + httpzo) 23 23 (libraries base base_bigstring unix eio magic-mime))
httpz/lib/err.ml httpzo/lib/err.ml
httpz/lib/err.mli httpzo/lib/err.mli
httpz/lib/etag.ml httpzo/lib/etag.ml
httpz/lib/etag.mli httpzo/lib/etag.mli
httpz/lib/header.ml httpzo/lib/header.ml
httpz/lib/header.mli httpzo/lib/header.mli
httpz/lib/header_name.ml httpzo/lib/header_name.ml
httpz/lib/header_name.mli httpzo/lib/header_name.mli
+1 -1
httpz/lib/httpz.ml httpzo/lib/httpzo.ml
··· 1 - (* httpz.ml - HTTP/1.1 parser for OCaml 5 *) 1 + (* httpzo.ml - HTTP/1.1 parser for OCaml 5 *) 2 2 3 3 module Buf_read = Buf_read 4 4 module Buf_write = Buf_write
+1 -1
httpz/lib/httpz.mli httpzo/lib/httpzo.mli
··· 1 - (** Httpz - HTTP/1.1 request parser for OCaml 5. 1 + (** Httpzo - HTTP/1.1 request parser for OCaml 5. 2 2 3 3 Parses HTTP/1.1 requests from a 32KB bigarray buffer. 4 4
httpz/lib/method.ml httpzo/lib/method.ml
httpz/lib/method.mli httpzo/lib/method.mli
httpz/lib/parser.ml httpzo/lib/parser.ml
httpz/lib/parser.mli httpzo/lib/parser.mli
httpz/lib/range.ml httpzo/lib/range.ml
httpz/lib/range.mli httpzo/lib/range.mli
httpz/lib/req.ml httpzo/lib/req.ml
httpz/lib/req.mli httpzo/lib/req.mli
httpz/lib/request_parse.ml httpzo/lib/request_parse.ml
httpz/lib/res.ml httpzo/lib/res.ml
httpz/lib/res.mli httpzo/lib/res.mli
+3 -3
httpz/lib/server.ml httpzo/lib/server.ml
··· 1 - (* server.ml - Eio static file server using httpz *) 1 + (* server.ml - Eio static file server using httpzo *) 2 2 3 3 open Eio.Std 4 4 ··· 54 54 (* Write common response headers *) 55 55 let write_common_headers buf ~off ~keep_alive = 56 56 let off = Date.write_date_header buf ~off (now ()) in 57 - let off = Res.write_header_name buf ~off Header_name.Server "httpz/0.1" in 57 + let off = Res.write_header_name buf ~off Header_name.Server "httpzo/0.1" in 58 58 Res.write_connection buf ~off ~keep_alive 59 59 60 60 (* Write response headers for a full file response *) ··· 414 414 415 415 (* Run server *) 416 416 let run ~net ~sw config = 417 - traceln "httpz serving on http://localhost:%d/" config.port; 417 + traceln "httpzo serving on http://localhost:%d/" config.port; 418 418 traceln " Supports: Range requests, ETag, If-None-Match"; 419 419 let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, config.port) in 420 420 let sock = Eio.Net.listen net ~sw ~backlog:128 ~reuse_addr:true addr in
httpz/lib/server.mli httpzo/lib/server.mli
httpz/lib/span.ml httpzo/lib/span.ml
httpz/lib/span.mli httpzo/lib/span.mli
httpz/lib/version.ml httpzo/lib/version.ml
httpz/lib/version.mli httpzo/lib/version.mli
httpz/spec/RFC_COMPLIANCE.md httpzo/spec/RFC_COMPLIANCE.md
httpz/spec/rfc7230.txt httpzo/spec/rfc7230.txt
httpz/spec/rfc7231.txt httpzo/spec/rfc7231.txt
httpz/spec/rfc7232.txt httpzo/spec/rfc7232.txt
httpz/spec/rfc7233.txt httpzo/spec/rfc7233.txt
httpz/spec/rfc7234.txt httpzo/spec/rfc7234.txt
httpz/spec/rfc7235.txt httpzo/spec/rfc7235.txt
-3
httpz/test/dune
··· 1 - (test 2 - (name test_httpz) 3 - (libraries httpz base))
+89 -89
httpz/test/test_httpz.ml httpzo/test/test_httpz.ml
··· 1 - (* test_httpz.ml - Tests for the Httpz parser *) 1 + (* test_httpz.ml - Tests for the Httpzo parser *) 2 2 open Base 3 3 4 - let limits = Httpz.default_limits 4 + let limits = Httpzo.default_limits 5 5 6 6 let copy_to_buffer buf s = 7 7 let len = String.length s in ··· 14 14 (* Helper to parse a request and assert success. *) 15 15 let parse_ok buf request = 16 16 let len = copy_to_buffer buf request in 17 - let (status, req, headers) = Httpz.parse buf ~len ~limits in 18 - if Poly.( <> ) status Httpz.Buf_read.Complete 19 - then failwith (Printf.sprintf "Expected Ok, got %s" (Httpz.Buf_read.status_to_string status)); 17 + let (status, req, headers) = Httpzo.parse buf ~len ~limits in 18 + if Poly.( <> ) status Httpzo.Buf_read.Complete 19 + then failwith (Printf.sprintf "Expected Ok, got %s" (Httpzo.Buf_read.status_to_string status)); 20 20 (len, req, headers) 21 21 ;; 22 22 23 23 let test_simple_get () = 24 - let buf = Httpz.create_buffer () in 24 + let buf = Httpzo.create_buffer () in 25 25 let request = 26 26 "GET /index.html HTTP/1.1\r\nHost: example.com\r\nContent-Length: 0\r\n\r\n" 27 27 in 28 28 let (_len, req, headers) = parse_ok buf request in 29 - assert (Poly.( = ) req.meth Httpz.Method.Get); 30 - assert (Httpz.Span.equal buf req.target "/index.html"); 31 - assert (Poly.( = ) req.version Httpz.Version.Http_1_1); 29 + assert (Poly.( = ) req.meth Httpzo.Method.Get); 30 + assert (Httpzo.Span.equal buf req.target "/index.html"); 31 + assert (Poly.( = ) req.version Httpzo.Version.Http_1_1); 32 32 assert (Int64.( = ) req.content_length 0L); 33 33 assert (List.length headers = 1); 34 34 (match headers with 35 35 | [ hdr0 ] -> 36 - assert (Poly.( = ) hdr0.Httpz.Header.name Httpz.Header.Name.Host); 37 - assert (Httpz.Span.equal buf hdr0.Httpz.Header.value "example.com") 36 + assert (Poly.( = ) hdr0.Httpzo.Header.name Httpzo.Header.Name.Host); 37 + assert (Httpzo.Span.equal buf hdr0.Httpzo.Header.value "example.com") 38 38 | _ -> assert false); 39 39 Stdlib.print_endline "test_simple_get: PASSED" 40 40 ;; 41 41 42 42 let test_post_with_body () = 43 - let buf = Httpz.create_buffer () in 43 + let buf = Httpzo.create_buffer () in 44 44 let request = 45 45 "POST /api/data HTTP/1.1\r\n\ 46 46 Host: api.example.com\r\n\ ··· 50 50 {\"key\":\"val\"}" 51 51 in 52 52 let (len, req, headers) = parse_ok buf request in 53 - assert (Poly.( = ) req.meth Httpz.Method.Post); 54 - assert (Httpz.Span.equal buf req.target "/api/data"); 55 - assert (Poly.( = ) req.version Httpz.Version.Http_1_1); 53 + assert (Poly.( = ) req.meth Httpzo.Method.Post); 54 + assert (Httpzo.Span.equal buf req.target "/api/data"); 55 + assert (Poly.( = ) req.version Httpzo.Version.Http_1_1); 56 56 assert (List.length headers = 2); 57 57 assert (req.body_off = len - 13); 58 58 assert (Int64.( = ) req.content_length 13L); ··· 60 60 ;; 61 61 62 62 let test_unknown_method () = 63 - let buf = Httpz.create_buffer () in 63 + let buf = Httpzo.create_buffer () in 64 64 let request = "PURGE /cache HTTP/1.1\r\nHost: cdn.example.com\r\n\r\n" in 65 65 let len = copy_to_buffer buf request in 66 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 67 - assert (Poly.( = ) status Httpz.Buf_read.Invalid_method); 66 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 67 + assert (Poly.( = ) status Httpzo.Buf_read.Invalid_method); 68 68 Stdlib.print_endline "test_unknown_method: PASSED" 69 69 ;; 70 70 71 71 let test_unknown_header () = 72 - let buf = Httpz.create_buffer () in 72 + let buf = Httpzo.create_buffer () in 73 73 let request = 74 74 "GET / HTTP/1.1\r\nHost: example.com\r\nX-Custom-Header: custom-value\r\n\r\n" 75 75 in ··· 77 77 assert (List.length headers = 2); 78 78 (match headers with 79 79 | [ hdr0; _ ] -> 80 - (match hdr0.Httpz.Header.name with 81 - | Httpz.Header.Name.Other -> 80 + (match hdr0.Httpzo.Header.name with 81 + | Httpzo.Header.Name.Other -> 82 82 assert ( 83 - Httpz.Span.equal_caseless buf hdr0.Httpz.Header.name_span "x-custom-header") 83 + Httpzo.Span.equal_caseless buf hdr0.Httpzo.Header.name_span "x-custom-header") 84 84 | _ -> assert false); 85 - assert (Httpz.Span.equal buf hdr0.Httpz.Header.value "custom-value") 85 + assert (Httpzo.Span.equal buf hdr0.Httpzo.Header.value "custom-value") 86 86 | _ -> assert false); 87 87 Stdlib.print_endline "test_unknown_header: PASSED" 88 88 ;; 89 89 90 90 let test_partial () = 91 - let buf = Httpz.create_buffer () in 91 + let buf = Httpzo.create_buffer () in 92 92 let request = "GET /index.html HTTP/1.1\r\nHost: exam" in 93 93 let len = copy_to_buffer buf request in 94 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 95 - assert (Poly.( = ) status Httpz.Buf_read.Partial); 94 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 95 + assert (Poly.( = ) status Httpzo.Buf_read.Partial); 96 96 Stdlib.print_endline "test_partial: PASSED" 97 97 ;; 98 98 99 99 let test_http10 () = 100 - let buf = Httpz.create_buffer () in 100 + let buf = Httpzo.create_buffer () in 101 101 let request = "GET / HTTP/1.0\r\n\r\n" in 102 102 let (_len, req, headers) = parse_ok buf request in 103 - assert (Poly.( = ) req.version Httpz.Version.Http_1_0); 103 + assert (Poly.( = ) req.version Httpzo.Version.Http_1_0); 104 104 assert (List.length headers = 0); 105 105 Stdlib.print_endline "test_http10: PASSED" 106 106 ;; 107 107 108 108 let test_keep_alive () = 109 - let buf = Httpz.create_buffer () in 109 + let buf = Httpzo.create_buffer () in 110 110 let request1 = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" in 111 111 let (_len1, req1, _headers1) = parse_ok buf request1 in 112 112 assert req1.keep_alive; ··· 117 117 ;; 118 118 119 119 let test_chunked () = 120 - let buf = Httpz.create_buffer () in 120 + let buf = Httpzo.create_buffer () in 121 121 let request = 122 122 "POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n" 123 123 in ··· 128 128 ;; 129 129 130 130 let test_find_header () = 131 - let buf = Httpz.create_buffer () in 131 + let buf = Httpzo.create_buffer () in 132 132 let request = "GET / HTTP/1.1\r\nHost: example.com\r\nAccept: text/html\r\n\r\n" in 133 133 let (_len, _req, headers) = parse_ok buf request in 134 - (match Httpz.Header.find headers Httpz.Header.Name.Host with 135 - | Some hdr -> assert (Httpz.Span.equal buf hdr.Httpz.Header.value "example.com") 134 + (match Httpzo.Header.find headers Httpzo.Header.Name.Host with 135 + | Some hdr -> assert (Httpzo.Span.equal buf hdr.Httpzo.Header.value "example.com") 136 136 | None -> assert false); 137 - (match Httpz.Header.find headers Httpz.Header.Name.Content_length with 137 + (match Httpzo.Header.find headers Httpzo.Header.Name.Content_length with 138 138 | Some _ -> assert false 139 139 | None -> ()); 140 140 Stdlib.print_endline "test_find_header: PASSED" 141 141 ;; 142 142 143 143 let test_missing_host_http11 () = 144 - let buf = Httpz.create_buffer () in 144 + let buf = Httpzo.create_buffer () in 145 145 let request = "GET / HTTP/1.1\r\n\r\n" in 146 146 let len = copy_to_buffer buf request in 147 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 148 - assert (Poly.( = ) status Httpz.Buf_read.Missing_host_header); 147 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 148 + assert (Poly.( = ) status Httpzo.Buf_read.Missing_host_header); 149 149 Stdlib.print_endline "test_missing_host_http11: PASSED" 150 150 ;; 151 151 152 152 let test_ambiguous_framing () = 153 - let buf = Httpz.create_buffer () in 153 + let buf = Httpzo.create_buffer () in 154 154 let request = 155 155 "POST /upload HTTP/1.1\r\nHost: example.com\r\nContent-Length: 10\r\nTransfer-Encoding: chunked\r\n\r\n" 156 156 in 157 157 let len = copy_to_buffer buf request in 158 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 159 - assert (Poly.( = ) status Httpz.Buf_read.Ambiguous_framing); 158 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 159 + assert (Poly.( = ) status Httpzo.Buf_read.Ambiguous_framing); 160 160 Stdlib.print_endline "test_ambiguous_framing: PASSED" 161 161 ;; 162 162 163 163 let test_content_length_overflow () = 164 - let buf = Httpz.create_buffer () in 164 + let buf = Httpzo.create_buffer () in 165 165 let small_limits = 166 - { Httpz.Buf_read.max_content_length = 1000L 166 + { Httpzo.Buf_read.max_content_length = 1000L 167 167 ; max_header_size = 16384 168 168 ; max_header_count = 100 169 169 ; max_chunk_size = 16777216 ··· 171 171 in 172 172 let request = "POST /upload HTTP/1.1\r\nHost: example.com\r\nContent-Length: 1000000\r\n\r\n" in 173 173 let len = copy_to_buffer buf request in 174 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits:small_limits in 175 - assert (Poly.( = ) status Httpz.Buf_read.Content_length_overflow); 174 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits:small_limits in 175 + assert (Poly.( = ) status Httpzo.Buf_read.Content_length_overflow); 176 176 Stdlib.print_endline "test_content_length_overflow: PASSED" 177 177 ;; 178 178 179 179 let test_bare_cr () = 180 - let buf = Httpz.create_buffer () in 180 + let buf = Httpzo.create_buffer () in 181 181 let request = "GET / HTTP/1.1\r\nHost: example\rcom\r\n\r\n" in 182 182 let len = copy_to_buffer buf request in 183 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 184 - assert (Poly.( = ) status Httpz.Buf_read.Bare_cr_detected); 183 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 184 + assert (Poly.( = ) status Httpzo.Buf_read.Bare_cr_detected); 185 185 Stdlib.print_endline "test_bare_cr: PASSED" 186 186 ;; 187 187 188 188 let test_unsupported_transfer_encoding () = 189 - let buf = Httpz.create_buffer () in 189 + let buf = Httpzo.create_buffer () in 190 190 let request = 191 191 "POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: gzip\r\n\r\n" 192 192 in 193 193 let len = copy_to_buffer buf request in 194 - let (status, _req, _headers) = Httpz.parse buf ~len ~limits in 195 - assert (Poly.( = ) status Httpz.Buf_read.Unsupported_transfer_encoding); 194 + let (status, _req, _headers) = Httpzo.parse buf ~len ~limits in 195 + assert (Poly.( = ) status Httpzo.Buf_read.Unsupported_transfer_encoding); 196 196 Stdlib.print_endline "test_unsupported_transfer_encoding: PASSED" 197 197 ;; 198 198 199 199 let test_transfer_encoding_identity () = 200 - let buf = Httpz.create_buffer () in 200 + let buf = Httpzo.create_buffer () in 201 201 let request = 202 202 "POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: identity\r\n\r\n" 203 203 in ··· 207 207 ;; 208 208 209 209 let test_expect_continue () = 210 - let buf = Httpz.create_buffer () in 210 + let buf = Httpzo.create_buffer () in 211 211 let request = 212 212 "POST /upload HTTP/1.1\r\nHost: example.com\r\nExpect: 100-continue\r\nContent-Length: 1000\r\n\r\n" 213 213 in ··· 218 218 ;; 219 219 220 220 let test_expect_continue_absent () = 221 - let buf = Httpz.create_buffer () in 221 + let buf = Httpzo.create_buffer () in 222 222 let request = "POST /upload HTTP/1.1\r\nHost: example.com\r\nContent-Length: 100\r\n\r\n" in 223 223 let (_len, req, _headers) = parse_ok buf request in 224 224 assert (not req.expect_continue); ··· 227 227 228 228 let test_write_chunk_header () = 229 229 let dst = Base_bigstring.create 100 in 230 - let off = Httpz.Res.write_chunk_header dst ~off:0 ~size:255 in 230 + let off = Httpzo.Res.write_chunk_header dst ~off:0 ~size:255 in 231 231 let written = Base_bigstring.To_string.sub dst ~pos:0 ~len:off in 232 232 assert (String.( = ) written "ff\r\n"); 233 - let off2 = Httpz.Res.write_chunk_header dst ~off:0 ~size:0 in 233 + let off2 = Httpzo.Res.write_chunk_header dst ~off:0 ~size:0 in 234 234 let written2 = Base_bigstring.To_string.sub dst ~pos:0 ~len:off2 in 235 235 assert (String.( = ) written2 "0\r\n"); 236 - let off3 = Httpz.Res.write_chunk_header dst ~off:0 ~size:4096 in 236 + let off3 = Httpzo.Res.write_chunk_header dst ~off:0 ~size:4096 in 237 237 let written3 = Base_bigstring.To_string.sub dst ~pos:0 ~len:off3 in 238 238 assert (String.( = ) written3 "1000\r\n"); 239 239 Stdlib.print_endline "test_write_chunk_header: PASSED" ··· 241 241 242 242 let test_write_final_chunk () = 243 243 let dst = Base_bigstring.create 100 in 244 - let off = Httpz.Res.write_final_chunk dst ~off:0 in 244 + let off = Httpzo.Res.write_final_chunk dst ~off:0 in 245 245 let written = Base_bigstring.To_string.sub dst ~pos:0 ~len:off in 246 246 assert (String.( = ) written "0\r\n\r\n"); 247 247 Stdlib.print_endline "test_write_final_chunk: PASSED" 248 248 ;; 249 249 250 250 let test_chunk_parse () = 251 - let buf = Httpz.create_buffer () in 251 + let buf = Httpzo.create_buffer () in 252 252 let data = "5\r\nhello\r\n0\r\n\r\n" in 253 253 let len = copy_to_buffer buf data in 254 - let (status1, chunk1) = Httpz.Chunk.parse buf ~off:0 ~len in 255 - assert (Poly.( = ) status1 Httpz.Chunk.Complete); 254 + let (status1, chunk1) = Httpzo.Chunk.parse buf ~off:0 ~len in 255 + assert (Poly.( = ) status1 Httpzo.Chunk.Complete); 256 256 assert (chunk1.data_len = 5); 257 - let (status2, _chunk2) = Httpz.Chunk.parse buf ~off:chunk1.next_off ~len in 258 - assert (Poly.( = ) status2 Httpz.Chunk.Done); 257 + let (status2, _chunk2) = Httpzo.Chunk.parse buf ~off:chunk1.next_off ~len in 258 + assert (Poly.( = ) status2 Httpzo.Chunk.Done); 259 259 Stdlib.print_endline "test_chunk_parse: PASSED" 260 260 ;; 261 261 262 262 let test_etag_parse () = 263 - let buf = Httpz.create_buffer () in 263 + let buf = Httpzo.create_buffer () in 264 264 let etag_str = "\"xyzzy\"" in 265 265 let len = copy_to_buffer buf etag_str in 266 - let sp = Httpz.Span.make ~off:0 ~len in 267 - let (status, etag) = Httpz.Etag.parse buf sp in 268 - assert (Poly.( = ) status Httpz.Etag.Valid); 266 + let sp = Httpzo.Span.make ~off:0 ~len in 267 + let (status, etag) = Httpzo.Etag.parse buf sp in 268 + assert (Poly.( = ) status Httpzo.Etag.Valid); 269 269 assert (not etag.weak); 270 - assert (String.equal (Httpz.Etag.to_string buf etag) "xyzzy"); 270 + assert (String.equal (Httpzo.Etag.to_string buf etag) "xyzzy"); 271 271 let weak_str = "W/\"weak-tag\"" in 272 272 let len2 = copy_to_buffer buf weak_str in 273 - let sp2 = Httpz.Span.make ~off:0 ~len:len2 in 274 - let (status2, etag2) = Httpz.Etag.parse buf sp2 in 275 - assert (Poly.( = ) status2 Httpz.Etag.Valid); 273 + let sp2 = Httpzo.Span.make ~off:0 ~len:len2 in 274 + let (status2, etag2) = Httpzo.Etag.parse buf sp2 in 275 + assert (Poly.( = ) status2 Httpzo.Etag.Valid); 276 276 assert etag2.weak; 277 - assert (String.equal (Httpz.Etag.to_string buf etag2) "weak-tag"); 277 + assert (String.equal (Httpzo.Etag.to_string buf etag2) "weak-tag"); 278 278 Stdlib.print_endline "test_etag_parse: PASSED" 279 279 ;; 280 280 281 281 let test_date_parse_imf () = 282 - let buf = Httpz.create_buffer () in 282 + let buf = Httpzo.create_buffer () in 283 283 let date_str = "Sun, 06 Nov 1994 08:49:37 GMT" in 284 284 let len = copy_to_buffer buf date_str in 285 - let sp = Httpz.Span.make ~off:0 ~len in 286 - let (status, ts) = Httpz.Date.parse buf sp in 287 - assert (Poly.( = ) status Httpz.Date.Valid); 285 + let sp = Httpzo.Span.make ~off:0 ~len in 286 + let (status, ts) = Httpzo.Date.parse buf sp in 287 + assert (Poly.( = ) status Httpzo.Date.Valid); 288 288 assert (Float.( = ) ts 784111777.0); 289 289 Stdlib.print_endline "test_date_parse_imf: PASSED" 290 290 ;; 291 291 292 292 let test_date_format () = 293 293 let ts = 784111777.0 in 294 - let formatted = Httpz.Date.format ts in 294 + let formatted = Httpzo.Date.format ts in 295 295 assert (String.equal formatted "Sun, 06 Nov 1994 08:49:37 GMT"); 296 296 Stdlib.print_endline "test_date_format: PASSED" 297 297 ;; 298 298 299 299 let test_range_parse_single () = 300 - let buf = Httpz.create_buffer () in 301 - let ranges = Array.create ~len:Httpz.Range.max_ranges Httpz.Range.empty in 300 + let buf = Httpzo.create_buffer () in 301 + let ranges = Array.create ~len:Httpzo.Range.max_ranges Httpzo.Range.empty in 302 302 let range_str = "bytes=0-499" in 303 303 let len = copy_to_buffer buf range_str in 304 - let sp = Httpz.Span.make ~off:0 ~len in 305 - let (status, count) = Httpz.Range.parse buf sp ranges in 306 - assert (Poly.( = ) status Httpz.Range.Valid); 304 + let sp = Httpzo.Span.make ~off:0 ~len in 305 + let (status, count) = Httpzo.Range.parse buf sp ranges in 306 + assert (Poly.( = ) status Httpzo.Range.Valid); 307 307 assert (count = 1); 308 308 let r = Array.get ranges 0 in 309 - assert (Httpz.Range.is_range r); 309 + assert (Httpzo.Range.is_range r); 310 310 assert (Int64.( = ) r.start 0L); 311 311 assert (Int64.( = ) r.end_ 499L); 312 312 Stdlib.print_endline "test_range_parse_single: PASSED" 313 313 ;; 314 314 315 315 let test_range_satisfiable () = 316 - let buf = Httpz.create_buffer () in 317 - let ranges = Array.create ~len:Httpz.Range.max_ranges Httpz.Range.empty in 318 - let resolved = Array.create ~len:Httpz.Range.max_ranges Httpz.Range.empty_resolved in 316 + let buf = Httpzo.create_buffer () in 317 + let ranges = Array.create ~len:Httpzo.Range.max_ranges Httpzo.Range.empty in 318 + let resolved = Array.create ~len:Httpzo.Range.max_ranges Httpzo.Range.empty_resolved in 319 319 let range_str = "bytes=0-499" in 320 320 let len = copy_to_buffer buf range_str in 321 - let sp = Httpz.Span.make ~off:0 ~len in 322 - let (_, count) = Httpz.Range.parse buf sp ranges in 323 - let (result, res_count) = Httpz.Range.evaluate ranges ~count ~resource_length:1000L resolved in 324 - assert (Poly.( = ) result Httpz.Range.Single_range); 321 + let sp = Httpzo.Span.make ~off:0 ~len in 322 + let (_, count) = Httpzo.Range.parse buf sp ranges in 323 + let (result, res_count) = Httpzo.Range.evaluate ranges ~count ~resource_length:1000L resolved in 324 + assert (Poly.( = ) result Httpzo.Range.Single_range); 325 325 assert (res_count = 1); 326 326 let r = Array.get resolved 0 in 327 327 assert (Int64.( = ) r.start 0L);
+5
httpzo/bin/dune
··· 1 + (executable 2 + (name httpz_server) 3 + (public_name httpzo) 4 + (package httpzo) 5 + (libraries httpzo eio eio_main cmdliner xdge tomlt tomlt.unix))
+3
httpzo/test/dune
··· 1 + (test 2 + (name test_httpz) 3 + (libraries httpzo base))