LocalWords: HPACK

June 6, 2026 ยท View on GitHub

#+TITLE: HTTP/2 in Common Lisp

[[https://github.com/zellerin/http2/actions/workflows/test.yml/badge.svg]]

This is version 2.1 of an implementation of HTTP/2 protocol as described in RFC9113 (and RFC7540 before) and RFC7541 (HPACK). It provides both high-level interfaces (client, threaded server and polling server) as well as ways to fine tune its behaviour for better performance or specific use cases.

For quick start, quickload "http2" and run #+begin_src lisp (http2/client:retrieve-url "https://example.com") #+end_src to fetch a HTTP/2 resource, and #+begin_src lisp (http2/server:start 8443)

(define-exact-handler "/" (send-text-handler "Hello World")) #+end_src to start an empty TLS server and serve a "Hello world" page.

Check [[https://doc.zellerin.cz/http2/#HTTP2:@TUTORIALS%20MGL-PAX:SECTION][tutorials]] that show in more detail how to use the client or the server.

See [[./Changelog.org][Changelog]] for changes in this version; some might be incompatible, apologies. There are quite a few fixes there as well. Thanks to John Mallery for discussion, bug reports, ideas, and fixes in this version.

** Demo pages

Simple demo can be started by running : sbcl --script scaffolding/run-server.lisp

It opens two web servers, multi-threaded one https://localhost:8080/demo/ and a polling one on https://localhost:8081/demo. Both should be functionally equivalent with a different backend. Both provide a /demo/test page that tests some more tricky parts of the backend in the browser.

** Status In quicklisp. Documentation is on [[https://doc.zellerin.cz/http2/][separate page]].

Implements both thread-per-client and poll-based single threaded server (that may be actually faster).

Tested primarily on sbcl, occasionally on ecl. I am told it runs on Lispworks as well.

Almost all low level parts of the listed standards are implemented, not necessary documented or declared stable.

** Missing pieces See [[./Changelog.org]] for planned changes.

  • No handling of priorities is implemented. This is more or less OK, as these are only suggestions, and they are more or less dropped in RFC9113 anyway. But nothing from RFC9218 is implemented neither (except for the setting).
  • Push promises are not implemented in the client. This is OK, they are disabled by default (settings)
  • Some checks on behaviour of the peer are not enforced
  • Quite a few things are out of scope and left to application to handle. Cookie handling, GET parameters extraction, ...

** Dependencies

The core library used trivial-gray-streams to implement streams over data frames. Server and client libraries have [[https://doc.zellerin.cz/http2/reference.html#HTTP2:@SYSTEMS-AND-PACKAGES%20MGL-PAX:SECTION][other dependencies]], but not extensive

** Speed & scaling The code was not written with speed as primary concern. Measurements depend on many tunable factor both on the client and the server (including platform).

Anyway, run or modify the [[file:scaffolding/speed-test.lisp][speed test code]] for your results. : sbcl --script scaffolding/speed-test.lisp

** License Licensed by MIT license.

Some comments are taken over from the RFCs above and copyrighted by RFC contributors. I read the copyright licenses for RFC that this is allowed.

** Related software There is an Akamai code on https://github.com/akamai/cl-http2-protocol that supported bigger parts of the drafted HTTP/2 protocol in 2014; apparently hard if not impossible to run now. It used NPN instead of ALPN.

LocalWords: HPACK