8000 Replace HTTPoison with Req in the ACMEv2 client by neilberkman · Pull Request #8 · dominicletz/certmagex · GitHub
[go: up one dir, main page]

Skip to content

Replace HTTPoison with Req in the ACMEv2 client - #8

Merged
dominicletz merged 1 commit into
dominicletz:masterfrom
neilberkman:req-http-client
Jul 9, 2026
Merged

dominicletz merged 1 commit into
dominicletz:masterfrom
neilberkman:req-http-client

Conversation

@neilberkman
Copy link
Copy Markdown
Contributor

All of the ACMEv2 client's HTTP calls are plain GET/POST, so Req (Finch-based) is a drop-in for HTTPoison. This drops the httpoison → hackney chain entirely; the hackney 1.x line that httpoison ~> 2.0 pins has several open advisories (SSRF / CRLF / header injection), fixed only in hackney 4.x.

Two ways to clear those advisories — this PR is the larger one, so flagging both:

  1. Minimal: bump httpoison ~> 2.0 → ~> 3.0 (httpoison 3.0 uses the patched hackney 4.x). One-line change; happy to send that instead if you prefer to keep httpoison.
  2. This PR: move to Req and drop the chain.

What changed:

  • request/5 uses Req.request! with decode_body: false (callers Jason.decode the raw JSON/JOSE body themselves), retry: false (the function already loops on failure), and redirect: false (HTTPoison parity — an ACME POST binds the request URL into the JWS protected header, so a transparently re-POSTed redirect would fail signature validation anyway).
  • Replay-Nonce / Location response headers are read via Req.Response.get_header/2 (Req lowercases response header names).
  • status_code → status and %HTTPoison.Response{} → %Req.Response{} at all call sites; mixed string/atom request-header keys are normalized for Req.
  • Fixes a latent retry bug that predates this change: the recursive retry call passed (uri, method) into a (method, uri) head, so every retried request was malformed.
  • Dep swap: httpoison ~> 2.0 → req ~> 0.5.

One compatibility note: Req's dependency chain (finch) requires Elixir 1.15+, while mix.exs declares ~> 1.13. CI (1.15) is unaffected, but merging this effectively raises the supported floor — you may want to bump the elixir: requirement alongside.

Verified: mix test, credo, and format pass; a smoke test against Let's Encrypt staging (directory + newNonce + Replay-Nonce extraction) confirms the exact Req option set works against a real ACME server. Full signed issuance would still be worth a staging run with a live HTTP-01 challenge before a release.

All HTTP calls in the ACMEv2 client are plain GET/POST, so Req (Finch-based)
is a drop-in for HTTPoison:

- request/5 uses Req.request! with decode_body: false (callers Jason.decode
  the raw JSON/JOSE body themselves), retry: false (the function already
  loops on failure), and redirect: false (HTTPoison parity; an ACME POST
  binds the request URL into the JWS protected header, so a transparently
  re-POSTed redirect would fail signature validation anyway).
- Replay-Nonce / Location response headers are read via
  Req.Response.get_header/2 (Req lowercases response header names).
- status_code -> status and %HTTPoison.Response{} -> %Req.Response{} at all
  call sites; mixed string/atom request-header keys normalized for Req.
- Fixes a latent retry bug: the recursive retry call passed (uri, method)
  into a (method, uri) head, so every retried request was malformed.
- Dep swap: httpoison ~> 2.0 -> req ~> 0.5, dropping the hackney tree.

Verified: mix test, credo, format; smoke test against Let's Encrypt staging
(directory + newNonce + Replay-Nonce extraction) with the exact Req options.
@gemini-code-assist
Copy link
Copy Markdown

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@dominicletz
Copy link
Copy Markdown
Owner

I do prefer Req as well

@dominicletz
dominicletz merged commit beabe5c into dominicletz:master Jul 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0