Hackney Development Guide
View SourceThis guide covers development setup, testing, and contributing to hackney.
Prerequisites
- Erlang/OTP 27 or later
- rebar3 3.24.0 or later
- CMake 3.14 or later
- Go (for building BoringSSL)
- zlib development headers
Platform-specific requirements
macOS:
brew install erlang cmake go zlib
Ubuntu/Debian:
sudo apt-get install erlang cmake golang zlib1g-dev build-essential
FreeBSD:
pkg install erlang-runtime28 rebar3 cmake git gmake go llvm18
Building
Clone the repository with submodules:
git clone --recursive https://github.com/benoitc/hackney.git
cd hackney
Build the project:
rebar3 compile
This will:
- Compile all Erlang source files
- Build the QUIC NIF (BoringSSL + lsquic + hackney_quic)
Running Tests
Run all tests:
rebar3 eunit
Run specific test modules:
rebar3 eunit --module=hackney_quic_tests
rebar3 eunit --module=hackney_http3_tests
Running tests with httpbin
Some tests require the httpbin server. Start it before running tests:
pip3 install httpbin gunicorn
gunicorn -b 127.0.0.1:8000 httpbin:app &
rebar3 eunit
Local Docker Testing
A Dockerfile is provided for testing on Linux locally, which mirrors the GitHub CI environment.
Building the Docker image
docker build -f Dockerfile.test -t hackney-test .
Running tests in Docker
Run all tests:
docker run --rm hackney-test
Run specific test modules:
docker run --rm hackney-test bash -c "rebar3 eunit --module=hackney_quic_tests"
Interactive debugging in Docker
Start an interactive shell:
docker run --rm -it hackney-test bash
Then you can:
- Run tests manually:
rebar3 eunit - Start an Erlang shell:
rebar3 shell - Inspect the build:
ls -la priv/
Debugging with core dumps
Enable core dumps for debugging segfaults:
docker run --rm --ulimit core=-1 hackney-test bash -c "
ulimit -c unlimited
rebar3 eunit || (ls -la core* 2>/dev/null; gdb -batch -ex bt /usr/local/bin/erl core*)
"
QUIC/HTTP3 Development
The QUIC implementation uses:
- BoringSSL - Google's fork of OpenSSL (required for QUIC TLS 1.3)
- lsquic - LiteSpeed QUIC library
NIF Source Files
c_src/hackney_quic_nif.c- NIF entry pointsc_src/quic_conn.c- Connection managementc_src/quic_conn.h- Connection structures and declarationsc_src/atoms.h- Atom definitions
Building the NIF
The NIF is built automatically by rebar3 using CMake. To rebuild from scratch:
rm -rf _build/cmake priv/*.so
rebar3 compile
CMake Configuration
The CMake build is configured in c_src/CMakeLists.txt. Key options:
CMAKE_BUILD_TYPE- Release (default) or DebugCMAKE_POSITION_INDEPENDENT_CODE- Always ON for NIF shared library
Debugging the NIF
Build with debug symbols:
rm -rf _build/cmake
CMAKE_BUILD_TYPE=Debug rebar3 compile
Use LLDB/GDB to debug:
lldb -- erl -pa _build/default/lib/*/ebin
Code Style
Erlang
- Follow standard Erlang conventions
- Use edoc for function documentation
- Keep lines under 100 characters
C
- Use C17 standard
- Use
enif_alloc/enif_freefor memory allocation (not malloc/free) - Always check return values
- Use atomic operations for thread-safe flags
Submitting Changes
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run tests locally and in Docker
- Commit with clear messages
- Push and create a pull request
Commit Message Format
type: short description
Longer description if needed.Types: fix, feat, docs, test, refactor, ci, chore
Continuous Integration
CI runs on:
- Linux x86_64 (OTP 27.2, 28.0)
- Linux ARM64 (OTP 27.2)
- macOS ARM64 (OTP 27)
- FreeBSD 14.2 (OTP 28)
All CI jobs must pass before merging.