Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# NEWS

4.5.0 - 2026-07-04
------------------

### Added

- HTTP QUERY method (RFC 10008) as a first-class method: `hackney:query/1..4`
helpers and `hackney:request(query, ...)`. QUERY is safe and idempotent and
carries a request body like POST. It works over HTTP/1.1, HTTP/2, and
HTTP/3 with every request body mode (binary, streamed, async, connection
API).

4.4.5 - 2026-06-18
------------------

Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ hackney:delete(URL).
hackney:head(URL).
hackney:options(URL).
hackney:patch(URL, Headers, Body).
hackney:query(URL, Headers, Body).
```

`QUERY` (RFC 10008) is a safe, idempotent method for read-only operations
that need a request body:

```erlang
hackney:query(
URL,
[{<<"content-type">>, <<"application/json">>}],
Json,
Options
).
```

### Connection Pooling
Expand Down
25 changes: 25 additions & 0 deletions guides/http_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ ok = hackney:finish_send_body(Ref),
{ok, Status, RespHeaders, Ref} = hackney:start_response(Ref).
```

## QUERY Requests

QUERY (RFC 10008) is a safe, idempotent method for read-only operations that
need a request body, for example a structured query too large or too
sensitive for the URL. Use it like a POST: the body travels the same way
over HTTP/1.1, HTTP/2, and HTTP/3.

```erlang
hackney:query(
URL,
[{<<"content-type">>, <<"application/json">>}],
Json,
Options
).
```

The generic form works too:

```erlang
hackney:request(query, URL, Headers, Body, Options).
```

Every request body format above (binary, form, multipart, streaming) works
with QUERY.

## Response Handling

### Read Full Body
Expand Down
2 changes: 1 addition & 1 deletion src/hackney.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{application, hackney,
[
{description, "Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support"},
{vsn, "4.4.5"},
{vsn, "4.5.0"},
{registered, [hackney_pool]},
{applications, [kernel,
stdlib,
Expand Down
4 changes: 3 additions & 1 deletion src/hackney.erl
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,9 @@ request(Method, URL, Headers, Body) ->
%% @doc Make a request.
%%
%% Args:
%% - Method: HTTP method (get, post, put, delete, etc.)
%% - Method: HTTP method (get, post, put, delete, query, etc.).
%% `query' is the RFC 10008 QUERY method: safe and idempotent, with a
%% request body allowed like post.
%% - URL: Full URL or parsed hackney_url record
%% - Headers: List of headers
%% - Body: Request body (binary, iolist, {form, KVs}, {file, Path}, etc.)
Expand Down
1 change: 1 addition & 0 deletions src/hackney_h3.erl
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ method_to_binary(delete) -> <<"DELETE">>;
method_to_binary(head) -> <<"HEAD">>;
method_to_binary(options) -> <<"OPTIONS">>;
method_to_binary(patch) -> <<"PATCH">>;
method_to_binary(query) -> <<"QUERY">>;
method_to_binary(Method) when is_atom(Method) ->
string:uppercase(atom_to_binary(Method));
method_to_binary(Method) when is_binary(Method) ->
Expand Down
3 changes: 3 additions & 0 deletions src/hackney_methods.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@
?METHOD_TPL(patch).
?METHOD_TPL(purge).

%% RFC-10008
?METHOD_TPL(query).

-undef(METHOD_TPL).
Loading
Loading