Skip to content

feat(https-outcalls): adopt the 0.2 HttpRequest builder, add a flexible outcall example - #1485

Merged
eichhorl merged 2 commits into
masterfrom
eichhorl/update-http_request-rust
Sep 16, 2026
Merged

eichhorl merged 2 commits into
masterfrom
eichhorl/update-http_request-rust

Conversation

@eichhorl

@eichhorl eichhorl commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Two related changes to the HTTPS outcall examples.

1. Migrate to the 0.2 builder. ic-cdk-management-canister 0.2.0 removed the free http_request in favour of an HttpRequest builder, which always uses pricing version 2 (pay-as-you-go). This migrates send_http_get, send_http_post and daily_planner, bumps their crate pin to 0.2, and rewrites the comments that only held under version 1.

Each call also declares what it expects:

.with_expected_roundtrip_time_ms(10_000)
.with_expected_transform_instructions(1_000_000)

Unset expectations reserve the worst case: a 60-second round trip, and the full 5-billion-instruction query limit for a transform that only clears headers. Read from the replica's own cost_http_request_v2 on a 13-node subnet, that was 94% of the attached cycles:

before after
send_http_get 5,329,580,997 135,581,004
send_http_post 473,484,344 73,945,883
daily_planner 34,002,045,662 28,808,045,669

The two byte expectations stay at their default. They share one per-node budget with delivery of the result, so a response that exceeds them fails the call after the request has already been made.

2. Add send_http_flexible. A new example for flexible_http_request, where a committee of nodes each make the request and the canister receives their individual responses instead of one the subnet agreed on. It asks for the current time, which changes faster than nodes could agree on it, and tallies the distinct answers. The replication counts come from subnet_self_node_count(), because total_requests must not exceed the subnet size. There is no transform, since nothing has to be made identical across nodes.

Considerations

  • Flexible outcalls are live. The feature flag flipped to Enabled on 2026-09-02 (c14df8a5b42), and both replica versions currently running across all 42 mainnet subnets contain it.
  • send_http_flexible is Rust only, so it does not meet AGENTS.md's "ship both variants" for new examples: Motoko needs mops-ic 5.0.0, which is unpublished. AGENTS.md also asks for DX team agreement to maintain a new example. Happy to split it into its own PR.
  • The 0.2 bump is scoped to the three migrated examples. The other 18 pinning 0.1.1 don't call the removed functions, and ^0.1.1 still resolves for them.
  • daily_planner leaves max_response_bytes unset, so it still reserves for delivering 2MB and stays above its version 1 cost.
  • dfinity/developer-docs quotes three regions from the migrated examples. The markers are unchanged, but its .sources/examples pin needs bumping after merge. The guide's "Flexible request" section has no code yet, so the new snippet gets wired up in that same follow-up.

Verification

cargo check --target wasm32-unknown-unknown clean on all four. All four deploy and call the live endpoints in ghcr.io/dfinity/icp-dev-env-rust:v2.2.1: send_http_get PASS, send_http_post PASS, daily_planner 6/6, send_http_flexible 2/2.

A committee of nodes each make the request and the canister receives their
individual responses, instead of one the subnet reached consensus on, so
reconciling them is the canister's job. This asks postman-echo.com for the
current time, which changes faster than nodes could ever agree on it, and
tallies the distinct answers.

Notable for readers: the replication counts are derived from
subnet_self_node_count, since total_requests must not exceed the subnet size;
there is no transform, because nothing has to be made identical across nodes;
and each response's status is checked on its own, because no node had to agree
with any other.

Rust only for now. Flexible outcalls need mops-ic 5.0.0, which is not
published yet.
@eichhorl
eichhorl requested a review from a team as a code owner September 16, 2026 13:04
@eichhorl eichhorl changed the title feat(http_request): adopt the ic-cdk-management-canister 0.2 HttpRequest builder feat(https-outcalls): adopt the 0.2 HttpRequest builder, add a flexible outcall example Sep 16, 2026
@eichhorl
eichhorl merged commit 1a9a024 into master Sep 16, 2026
12 checks passed
@eichhorl
eichhorl deleted the eichhorl/update-http_request-rust branch September 16, 2026 14:38
eichhorl added a commit to dfinity/developer-docs that referenced this pull request Sep 17, 2026
## Summary

Documents the two new HTTPS outcall features: `flexible_http_request`
and pay-as-you-go pricing (version `2`).

**Interface specification**

- New `flexible_http_request` management canister method. A committee of
nodes return their individual HTTP responses instead of the subnet
reaching consensus on one. Takes an optional `replication` argument
(`min_responses`, `max_responses`, `total_requests`), and returns either
the responses or a structured error carrying a global error code and
per-node resource reports.
- New optional `pricing_version` field on `http_request` (`1` or `2`).
Version `1` is now deprecated; version `2` prices the resources a call
consumes rather than `max_response_bytes`.
- New `ic0.cost_http_request_v2` and `ic0.subnet_self_node_count` System
APIs.
- Non-replicated outcalls are no longer described as experimental.
- `public/references/ic.did` and the interface-spec changelog updated to
match.

**Concepts, guide and reference**

- `concepts/https-outcalls.md`: the three outcall modes, and what each
pricing version charges for.
- `guides/backends/https-outcalls.mdx`: a mode comparison table, a
flexible request section with code, and a cycle costs section covering
both versions and the `with_expected_*` reservation setters.
- `references/cycle-costs.md`: the version `2` formulas, plus a separate
"What to attach" section.
- `guides/security/https-outcalls.md` and `dos-prevention.md`: flexible
mode's weaker integrity guarantee.

**Pins**

- `ic-cdk-management-canister` added to `upstream.json` as a second
`dfinity/cdk-rs` entry, pinned at 0.2.0. `ic-cdk` bumped to 0.20.3.
- `.sources/examples` repinned to `1a9a0249`, which carries the Rust
outcall examples migrated to the 0.2 builder and the new
`send_http_flexible` example (dfinity/examples#1485).

## Structural decisions

- **`cycle-costs.md` separates what a call is charged from what to
attach.** `ic0.cost_http_request_v2` deliberately quotes more than a
call settles at: it floors the response size at
`MAX_CANISTER_HTTP_REJECT_BYTES`, scales the fully-replicated consensus
fee, and reserves for the most expensive result the call could still
produce. Publishing the settle formula as the amount to attach would
under-fund calls, so the two are documented separately. The charged
formulas are validated against the upstream pricing unit tests.
- **`ic-cdk-management-canister` gets its own watched entry** rather
than riding on `ic-cdk`'s pin. It versions independently within the same
repo, and the `name` field in `upstream.json` exists for this case (the
recipes repo uses it for five entries).
`scripts/check-upstream-releases.mjs` derives a distinct slug, issue and
label from it.
- **The Rust and Motoko tabs show different pricing versions.** The Rust
`HttpRequest` builder always selects version `2`; Motoko's
`Call.httpRequest` still attaches the version `1` cost. That is a
packaging lag rather than a language difference, and the prose says so.
The flexible request section is Rust only for the same reason.

## Verification

- `npm run build` passes: 210 pages, no errors, with every `snippet=`
region resolving at the new examples pin.
- The pricing figures quoted in the guide were read from a probe
canister calling the replica's own `ic0.cost_http_request_v2`, rather
than computed from the published formulas.
- Flexible outcalls confirmed live: the feature flag flipped to
`Enabled` on 2026-09-02, and both replica versions currently running
across all 42 mainnet subnets contain that commit.

---------

Co-authored-by: Leo Eichhorn <leo.eichhorn@dfinity.org>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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