Commit 41e8424
authored
fix(https-outcalls): correct max_response_bytes semantics and the 2MB default cost (#352)
Closes #351.
The issue reported two problems with how the HTTPS outcalls pages
describe `max_response_bytes`. Both are confirmed against the [interface
spec](https://github.com/dfinity/developer-docs/blob/main/docs/references/ic-interface-spec/management-canister.md)
and fixed here, along with several further defects found while fixing
them.
## What the issue reported
**1. Wrong byte figure.** `2,097,152` → `2,000,000`. The spec: *"the
default value of `2MB` (`2,000,000B`) is used as the limit."* Confirmed
in the replica as `MAX_CANISTER_HTTP_RESPONSE_BYTES = 2_000_000`.
**2. The limit is not body-scoped.** The spec defines the measured
quantity as *"the total number of bytes representing the names and
values of HTTP headers and the HTTP body."* Both pages now say headers
plus body.
**3. The transform bound** (raised in the issue body).
`max_response_bytes` is enforced **twice**: on the raw response as it
arrives, and again on the transform's output. A transform cannot rescue
a response that already exceeded the cap, because the first check runs
before the transform does; it only keeps the transform's own output
within the cap. Stated in the guide's transform section, where a reader
would form the "I'll strip headers to fit" plan, and in the concepts
Limitations bullet.
## Additional defects found
**4. The default-size cost was wrong on both pages.** Both said omitting
`max_response_bytes` costs *~21.5 billion cycles*. The formula already
published on `references/cycle-costs.md` gives:
```
49_140_000 + 10_400 * 2_000_000 = 20_849_140_000 (~20.85 billion)
```
Corrected to ~20.85 billion in both places. 21.5B matches neither the
decimal nor the binary reading, so it appears independently wrong rather
than downstream of the byte-figure error.
**5. `references/cycle-costs.md` said `max_response_bytes` defaults to
"2 MiB".** Same decimal-vs-binary error, on the page the other two link
to for exact pricing. Corrected, with the resulting cycle figure added.
**6. Both pages claimed a single ~30 second timeout, and the guide said
the call *traps*.** There are two timeouts and neither traps:
| Trigger | Reject | Message |
|---|---|---|
| Remote server silent for 30s | `SysFatal` | `Timeout expired` |
| Subnet produces no response within 60s | `SysTransient` | `Canister
http request timed out` |
Telling readers to expect a trap points them at the wrong error
handling.
**7. The Motoko cycle guidance was stale.** Both pages said *"In Motoko,
cycles must be attached explicitly with `await (with cycles = ...)`"*.
The `ic` package provides `Call.httpRequest`, which computes the exact
cost via `ic0.cost_http_request` and attaches it, matching the Rust
wrapper. The pages now also explain why a hand-picked margin is
counterproductive: attached cycles are held for the duration of the
call, so a margin caps outcall concurrency.
## Submodule bump
Item 7 could not be fixed in prose alone, because the embedded Motoko
snippets hardcoded `with cycles = 230_949_972_000`: correcting the text
would have left the page contradicting its own code. That was fixed
upstream first in dfinity/examples#1477, merged as `b4fe175`.
`.sources/examples` is bumped `d4ea422` → `b4fe175` here, so the
snippets now render `await Call.httpRequest(request)` and code and prose
agree.
The old pin predated the examples restructure, so all six `snippet=`
paths moved and are updated:
```
send_http_{get,post}/src/send_http_{get,post}_backend/main.mo -> send_http_{get,post}/backend/main.mo
send_http_{get,post}/src/send_http_{get,post}_backend/src/lib.rs -> send_http_{get,post}/backend/src/lib.rs
```
Region names (`transform`, `get_request`, `post_request`) are unchanged.
Per `.agents/submodule-bumping.md`: `guides/backends/https-outcalls.mdx`
is the only page using `CodeExample`, so no other page is affected by
the moves, and `examples` tracks master so it carries no
`.sources/VERSIONS` entry.
## Scope
Kept deliberately tight per `CONTRIBUTING.md`: `concepts/` stays
explanatory, and the spec's header limits (≤64 headers, ≤8 KiB per name
or value, ≤48 KiB total) are **not** added. The issue marked them
optional, and enumerating them duplicates content that belongs in the
interface spec and the `https-outcalls` skill.
## Verification
- `npm run validate`: no errors in the touched files.
- `build_and_deploy`: passing against the new submodule. This is the
meaningful check for the bump, since `remark-snippet` treats a missing
file or region as a hard build error.
- Before pushing the bump, all six file+region pairs were confirmed to
resolve at `b4fe175` by replicating the plugin's extraction logic.
## Related
- dfinity/icskills#361 carries the same corrections in the
`https-outcalls` skill, including the reject-message set these pages do
not enumerate.
- #254 (flexible outcalls) will invalidate the v1
pricing assumptions on these pages when it lands: `max_response_bytes`
is *ignored* under pricing v2, and `ic0.cost_http_request` is
deprecated. Flagged there with the specific lines, including that
`references/cycle-costs.md` needs both cost models rather than an edit
in place. As of `dfinity/ic@339d220a83` v2 is still gated off, so the
pages are correct today.1 parent 1a2e942 commit 41e8424
4 files changed
Lines changed: 18 additions & 16 deletions
File tree
- .sources
- docs
- concepts
- guides/backends
- references
Submodule examples updated 2454 files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
| 77 | + | |
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
84 | | - | |
| 84 | + | |
85 | 85 | | |
86 | 86 | | |
87 | | - | |
| 87 | + | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
| 21 | + | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
| 54 | + | |
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
| 64 | + | |
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
| 79 | + | |
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| |||
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | | - | |
| 109 | + | |
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
119 | | - | |
| 119 | + | |
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
| 136 | + | |
| 137 | + | |
136 | 138 | | |
137 | 139 | | |
138 | 140 | | |
139 | 141 | | |
140 | | - | |
| 142 | + | |
141 | 143 | | |
142 | | - | |
| 144 | + | |
143 | 145 | | |
144 | 146 | | |
145 | 147 | | |
| |||
152 | 154 | | |
153 | 155 | | |
154 | 156 | | |
155 | | - | |
| 157 | + | |
156 | 158 | | |
157 | 159 | | |
158 | 160 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
127 | | - | |
| 127 | + | |
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| |||
0 commit comments