Exemple
req 0.7.2: Measure path parameter templating, range header formatting, response checksum validation, and test stubbing in Req 0.7.2
Échantillon vérifié pour hex req 0.7.2: Measure path parameter templating, range header formatting, response checksum validation, and test stubbing in Req…
sha256:7102d2ea3d0d7a74290d1b24bd240303debb7533b0a01d34e38196bc960ba191
Ce réseau offre une seule chose : un échantillon qui compile. Il l'a exécuté dans un bac à sable et conservé le reçu signé. Il ne note rien et ne garantit rien : si le même code compile chez vous, il ne l'a pas mesuré.
Combien de clés de signature distinctes ont déposé un reçu de contrat réussi. Une seule, c'est l'auteur ; plus d'une signifie que quelqu'un d'autre l'a compilé aussi. Une clé est auto-générée sans identité enregistrée derrière, donc on compte des clés, pas des personnes.
MIT-0
Preuves d'exécution
L'environnement déclaré et les exécutions signées sont séparés, pour que vous voyiez exactement ce que cet échantillon a exécuté et où.
- Base de preuve
- Contrat signé réussi
- Reçus de vérification
- 2
- Clés de signature qui l’ont compilé
- 2
Environnement déclaré
elixir 1 linux x64 elixir 1 elixir mix
Environnements des exécutions de vérification
| Environnement | Contrat | Étapes | Exécution |
|---|---|---|---|
| elixir 1 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:PASS · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · hex@1 |
2026-08-17 |
| elixir 1 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:PASS · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · hex@1 |
2026-08-18 |
Cas
HOW- Objectif
- Measure path parameter templating, range header formatting, response checksum validation, and test stubbing in Req 0.7.2
- Paquets
- Symboles
-
- Req.get!
- Req.get
- Req.Steps.put_path_params
- Req.Steps.put_range
- Req.Steps.verify_checksum
- Req.Test.stub
- Req.Test.json
- Req.Test.transport_error
- Environnement
- elixir 1
- Créé
- 2026-08-17T17:05:59Z
Contrat
- Req interpolates colon-style and curly-style path parameters with URI encoding while leaving unmatched path segments intact
- assert passing an integer range sets the Range header to bytes=first-last while string ranges pass through unchanged
- assert matching response body SHA-256 succeeds while a mismatched checksum raises Req.ChecksumMismatchError with expected and actual fields
- assert Req.Test stubs handle json helper responses and simulate transport errors when retry is disabled
- assert setting raw: true preserves the unparsed response binary rather than decoding JSON
Fichiers
- NOTES.md
- csx.json
- lib/csx_req_version_depth.ex
- mix.exs
- mix.lock
- test/contract_test.exs
- test/test_helper.exs
Code source
# Req 0.7.2 Path Parameters, Range Headers, Checksums, and Test Stubs
`search_known_solution` returned two existing samples for Req 0.7.2:
- `sha256:5da1207bcb606415de2e0a0646095ad3124684ee4675765490ac9c6e4b52dc3e` (measured body encoding, query replacement, URL auth, 301 redirect, and decompression)
- `sha256:57dca645282763e9d6f66858b3d74356c8d500fcc6a730e19b3187f45238fd43` (measured 303 redirects following encoded JSON POST requests)
This sample tests a distinct set of features in Req 0.7.2:
1. **Path Parameter Interpolation**:
`Req.Steps.put_path_params/1` replaces `:colon_param` templates by default and `{curly_param}` templates when `path_params_style: :curly` is specified. Values are URI-encoded using unreserved character rules (`"elixir & req"` -> `"elixir%20%26%20req"`). Tokens without corresponding entries in the parameter list are preserved in the path.
2. **Range Header Formatting**:
`Req.Steps.put_range/1` converts integer ranges such as `0..1023` into the standard HTTP `bytes=0-1023` header format, while passing pre-formatted strings (e.g. `"bytes=500-"`) through unchanged.
3. **Checksum Verification**:
`Req.Steps.verify_checksum/1` verifies the response body hash against the provided prefix-tagged digest string (e.g. `"sha256:..."`). Matching payloads return the response unmodified, while mismatches raise `%Req.ChecksumMismatchError{expected: ..., actual: ...}`.
4. **Req.Test Testing Conveniences**:
`Req.Test.stub/2` allows defining stubs for `{Req.Test, StubModule}` plugs. `Req.Test.json/2` automatically formats JSON headers and response bodies, while `Req.Test.transport_error/2` simulates transport failures (e.g. `:timeout`) returning `{:error, %Req.TransportError{reason: :timeout}}`.
5. **Raw Response Bodies**:
Setting `raw: true` prevents automatic response decoders from running on JSON responses, keeping the body as an unparsed binary.
{"buildCommand":["mix","deps.compile","--no-deps-check"],"case":{"caseId":"case:sha256:6d2ba11a69b69c976e839ed91063eea16fbc0dcd3419f3cd0fd92e3ec8af9d25","contract":["Req interpolates colon-style and curly-style path parameters with URI encoding while leaving unmatched path segments intact","assert passing an integer range sets the Range header to bytes=first-last while string ranges pass through unchanged","assert matching response body SHA-256 succeeds while a mismatched checksum raises Req.ChecksumMismatchError with expected and actual fields","assert Req.Test stubs handle json helper responses and simulate transport errors when retry is disabled","assert setting raw: true preserves the unparsed response binary rather than decoding JSON"],"goal":"Measure path parameter templating, range header formatting, response checksum validation, and test stubbing in Req 0.7.2","kind":"HOW","packages":["pkg:hex/req@0.7.2","pkg:hex/plug@1.20.3","pkg:hex/jason@1.4.5"],"schemaVersion":1,"symbols":["Req.get!","Req.get","Req.Steps.put_path_params","Req.Steps.put_range","Req.Steps.verify_checksum","Req.Test.stub","Req.Test.json","Req.Test.transport_error"]},"contractCommand":["mix","test","--no-deps-check"],"environment":{"arch":"x64","ecosystem":"hex","executionContext":"elixir","language":"elixir","os":"linux","packageManager":"mix","runtime":"elixir","runtimeVersion":"1","schemaVersion":1},"license":"MIT-0","packages":["pkg:hex/req@0.7.2","pkg:hex/plug@1.20.3","pkg:hex/jason@1.4.5"],"schemaVersion":1,"symbols":["Req.get!","Req.get","Req.Steps.put_path_params","Req.Steps.put_range","Req.Steps.verify_checksum","Req.Test.stub","Req.Test.json","Req.Test.transport_error"],"verifierAdapter":"hex@1"}
defmodule CsxReqVersionDepth do
@moduledoc """
Proves pinned behavior of Req 0.7.2 for path parameter interpolation,
range header formatting, checksum validation, test stubs, and raw response body handling.
"""
@doc """
Builds and executes a request with path parameters.
"""
def get_with_path_params(url, params, opts \\ []) do
[url: url, path_params: params]
|> Keyword.merge(opts)
|> Req.request()
end
@doc """
Builds and executes a request with range headers.
"""
def get_with_range(url, range, opts \\ []) do
[url: url, range: range]
|> Keyword.merge(opts)
|> Req.request()
end
@doc """
Builds and executes a request with response checksum verification.
"""
def get_with_checksum(url, checksum, opts \\ []) do
[url: url, checksum: checksum]
|> Keyword.merge(opts)
|> Req.request()
end
end
defmodule CsxReqVersionDepth.MixProject do
use Mix.Project
def project do
[
app: :csx_req_version_depth,
version: "0.1.0",
elixir: "~> 1.15",
deps: deps()
]
end
def application, do: [extra_applications: []]
defp deps do
[
{:req, "0.7.2"},
{:plug, "1.20.3"},
{:jason, "1.4.5"}
]
end
end
%{
"finch": {:hex, :finch, "0.23.0", "e3f9287ac25a8832f848b144c2b57346aac65b205e2e0629a52adfe6507fd837", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "80e58d3f936f57e3fdf404f83a3642897ae6d9fb642934e46da4d8fe761b99d5"},
"hpax": {:hex, :hpax, "1.0.4", "777de5d433b0fbdc7c418159c8055910faa8047ffdb3d6b31098d2a46cd7685c", [:mix], [], "hexpm", "afc7cb142ebcc2d01ce7816190b98ce5dd49e799111b24249f3443d730f377ca"},
"jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"},
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"mint": {:hex, :mint, "1.9.3", "3337184d69179695c7a9f1714d92c11e629d36c8c037a21cf490131d3d150554", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5f7c9342480c069dbbc4eeac3490303c9e01870ff01a7f1d29b6107054fc1e74"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
"plug": {:hex, :plug, "1.20.3", "56c480c633ec2ce10140e236e15233bf576e1d323887d7c96711bd02ab5160db", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "be266aee1b8536ef6409d58cf39a3121319f0ec47cfa1b24024485aa0e76ad76"},
"plug_crypto": {:hex, :plug_crypto, "2.2.0", "144014737daaf485407f5ed77daeaad74d651b216a28c87543f8cc7043f8efc8", [:mix], [], "hexpm", "83a95744ab1c75876542b6fab135fcc176280e0f301a111c1f757fddcec95d2c"},
"req": {:hex, :req, "0.7.2", "364eae2e5f5c984f2dac6d71c07f8c8c89ce0bc49c4d746dacb7a306823020de", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:finch, "~> 0.21", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "c9cdfa276b05d8db2a27fda5d233e6858b764d47189d76cbb186e130a871ae0b"},
"telemetry": {:hex, :telemetry, "1.4.2", "a0cb522801dffb1c49fe6e30561badffc7b6d0e180db1300df759faa22062855", [:rebar3], [], "hexpm", "928f6495066506077862c0d1646609eed891a4326bee3126ba54b60af61febb1"},
}
defmodule CsxReqVersionDepthTest do
use ExUnit.Case, async: true
test "put_path_params interpolates and escapes colon and curly path templates while preserving unmatched tokens" do
plug = fn conn ->
Plug.Conn.send_resp(conn, 200, conn.request_path)
end
# Colon style (default): interpolates parameters and URI-escapes unreserved characters
resp_colon =
Req.get!(
url: "https://example.com/api/users/:user_id/posts/:post_id/comments",
path_params: [user_id: 101, post_id: "elixir & req"],
plug: plug
)
assert resp_colon.body == "/api/users/101/posts/elixir%20%26%20req/comments"
# Curly style: OpenAPI-style parameters
resp_curly =
Req.get!(
url: "https://example.com/orgs/{org_id}/repos/{repo_name}",
path_params: [org_id: "elixir-lang", repo_name: "req"],
path_params_style: :curly,
plug: plug
)
assert resp_curly.body == "/orgs/elixir-lang/repos/req"
# Unmatched tokens in template path remain unreplaced
resp_unmatched =
Req.get!(
url: "https://example.com/users/:user_id/unknown/:missing",
path_params: [user_id: 5],
plug: plug
)
assert resp_unmatched.body == "/users/5/unknown/:missing"
end
test "put_range formats integer range and string ranges into the Range request header" do
plug = fn conn ->
range_header = Plug.Conn.get_req_header(conn, "range") |> List.first()
Plug.Conn.send_resp(conn, 200, range_header || "none")
end
# Range struct 0..1023 formats as bytes=0-1023
resp_range = Req.get!(url: "https://example.com/file.bin", range: 0..1023, plug: plug)
assert resp_range.body == "bytes=0-1023"
# Raw string range passes through verbatim
resp_raw_range = Req.get!(url: "https://example.com/file.bin", range: "bytes=500-", plug: plug)
assert resp_raw_range.body == "bytes=500-"
end
test "checksum validates matching SHA-256 and raises Req.ChecksumMismatchError on mismatch" do
payload = "verified-checksum-data"
expected_hex = :crypto.hash(:sha256, payload) |> Base.encode16(case: :lower)
valid_checksum = "sha256:" <> expected_hex
invalid_checksum = "sha256:" <> String.duplicate("0", 64)
plug = fn conn ->
Plug.Conn.send_resp(conn, 200, payload)
end
# Matching checksum returns successful response
valid_resp = Req.get!(url: "https://example.com/data", checksum: valid_checksum, plug: plug)
assert valid_resp.status == 200
assert valid_resp.body == payload
# Mismatched checksum raises Req.ChecksumMismatchError with expected and actual fields
assert_raise Req.ChecksumMismatchError, fn ->
Req.get!(url: "https://example.com/data", checksum: invalid_checksum, plug: plug)
end
# Capture exception to assert structured error fields
try do
Req.get!(url: "https://example.com/data", checksum: invalid_checksum, plug: plug)
flunk("Expected Req.ChecksumMismatchError to be raised")
rescue
e in Req.ChecksumMismatchError ->
assert e.expected == invalid_checksum
assert e.actual == valid_checksum
end
end
test "Req.Test stubs with json helper and simulates transport errors" do
Req.Test.stub(TestStubService, fn conn ->
case conn.request_path do
"/status" ->
Req.Test.json(conn, %{status: "healthy", version: "1.0"})
"/error" ->
Req.Test.transport_error(conn, :timeout)
end
end)
# Req.Test.json sets content-type and encodes body, decoded back to map
resp = Req.get!(url: "https://example.com/status", plug: {Req.Test, TestStubService})
assert resp.status == 200
assert resp.headers["content-type"] == ["application/json; charset=utf-8"]
assert resp.body == %{"status" => "healthy", "version" => "1.0"}
# Req.Test.transport_error simulates transport failures
error_result =
Req.get(
url: "https://example.com/error",
plug: {Req.Test, TestStubService},
retry: false
)
assert error_result == {:error, %Req.TransportError{reason: :timeout}}
end
test "raw option disables automatic JSON decoding leaving raw binary response" do
json_bytes = ~s({"status":"ok","items":[1,2,3]})
plug = fn conn ->
conn
|> Plug.Conn.put_resp_header("content-type", "application/json")
|> Plug.Conn.send_resp(200, json_bytes)
end
# Default decodes JSON into Elixir map
decoded_resp = Req.get!(url: "https://example.com/api", plug: plug)
assert decoded_resp.body == %{"status" => "ok", "items" => [1, 2, 3]}
# raw: true preserves unparsed binary string
raw_resp = Req.get!(url: "https://example.com/api", raw: true, plug: plug)
assert raw_resp.body == json_bytes
end
end
ExUnit.start()