Skip to content

feat: consistent response format for hackney 3.x#822

Merged
benoitc merged 10 commits intomasterfrom
fix/consistent-response-format
Jan 27, 2026
Merged

feat: consistent response format for hackney 3.x#822
benoitc merged 10 commits intomasterfrom
fix/consistent-response-format

Conversation

@benoitc
Copy link
Copy Markdown
Owner

@benoitc benoitc commented Jan 27, 2026

Summary

  • Always return body directly in response: {ok, Status, Headers, Body}
  • Remove/ignore with_body option (always behaves as with_body = true)
  • Add HTTP/2 async request support (was missing)
  • Remove deprecated functions: body/1, body/2, skip_body/1, stream_body/1
  • Update documentation and tests

Breaking Changes

Before (2.x) After (3.x)
{ok, S, H, Pid} = hackney:get(URL) {ok, S, H, Body} = hackney:get(URL)
{ok, Body} = hackney:body(Pid) Body already in response
with_body option Ignored (always true)
stream_body/1 for incremental reads Use async mode instead

Migration

Before (2.x):

{ok, 200, Headers, Pid} = hackney:get(URL),
{ok, Body} = hackney:body(Pid).

After (3.x):

{ok, 200, Headers, Body} = hackney:get(URL).

For streaming (async mode):

{ok, Ref} = hackney:get(URL, [], <<>>, [async]),
receive {hackney_response, Ref, {status, 200, _}} -> ok end,
receive {hackney_response, Ref, {headers, Headers}} -> ok end,
receive {hackney_response, Ref, Chunk} -> process(Chunk) end.
This is a breaking change that makes HTTP response handling consistent
across all protocols (HTTP/1.1, HTTP/2, HTTP/3).

Changes:
- Body is now always returned directly: {ok, Status, Headers, Body}
- The with_body option is deprecated and ignored
- Added HTTP/2 async request support
- Deprecated body/1, body/2, stream_body/1 functions
- Updated documentation and migration guide
- Updated all tests to work with the new API

Breaking changes:
- {ok, S, H, Pid} = hackney:get(URL) -> {ok, S, H, Body} = hackney:get(URL)
- hackney:body(Pid) no longer needed - body is in response
- For incremental streaming, use async mode instead of stream_body/1
These functions are no longer needed since body is now always returned
directly in the response tuple {ok, Status, Headers, Body}.

For incremental streaming, use async mode instead:
  {ok, Ref} = hackney:get(URL, [], <<>>, [async]),
  receive {hackney_response, Ref, {status, S, _}} -> ... end.

Functions removed:
- body/1, body/2: Body is now in response tuple
- stream_body/1: Use async mode for streaming
- skip_body/1: No longer needed when body auto-returns
Add HTTP/3 handler for peername operation in hackney_conn.erl.
When h3_conn is defined, delegates to hackney_quic:peername/1 to
retrieve the peer address for QUIC connections.
Add HTTP/3 handler for sockname operation in hackney_conn.erl.
When h3_conn is defined, delegates to hackney_quic:sockname/1 to
retrieve the local socket address for QUIC connections.
Add HTTP/3 handler for peercert operation in hackney_conn.erl.
Returns {error, not_supported} since QUIC/HTTP3 does not expose
the peer certificate through this API.
Add HTTP/3 handler for setopts operation in hackney_conn.erl.
When h3_conn is defined, delegates to hackney_quic:setopts/2 to
set socket options for QUIC connections.
Breaking changes:
- Response body returned directly in tuple for all protocols
- Removed deprecated body/1, body/2, stream_body/1, skip_body/1
- Auth headers stripped on cross-host redirects (CVE-2018-1000007)

See guides/MIGRATION.md for upgrade instructions.
- Add "Manual Connection Management" section to http_guide.md
  covering hackney:connect, hackney:send_request, and hackney:close
- Document protocol detection with hackney_conn:get_protocol
- Include comparison table for HTTP/1.1 vs HTTP/2 behavior
- Update http2_guide.md to use hackney:send_request instead of
  hackney_conn:request for consistency
- Update Mix dependency example to ~> 3.0 in README.md and GETTING_STARTED.md
- Update design.md title to reflect current version
- Update TODO.md to show completed 2.0 roadmap items
@benoitc benoitc merged commit 38d8baa into master Jan 27, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant