Skip to content
This repository was archived by the owner on Aug 24, 2026. It is now read-only.

feat: allow PATCH in http_request for non-replicated calls - #6245

Closed
ggreif wants to merge 1 commit into
dfinity:masterfrom
ggreif:feat/http-outcall-patch-method
Closed

feat: allow PATCH in http_request for non-replicated calls#6245
ggreif wants to merge 1 commit into
dfinity:masterfrom
ggreif:feat/http-outcall-patch-method

Conversation

@ggreif

@ggreif ggreif commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Resolves #6244.

Adds the PATCH HTTP method to the canister http_request (HTTPS outcalls) management-canister interface, mirroring the PUT/DELETE addition in #6199.

What

  • ic.did: method variant → variant { get; head; post; put; delete; patch }.
  • ic-interface-spec.md: document PATCH alongside PUT/DELETE as supported in non-replicated mode only.
  • interface-spec-changelog.md: new 0.62.0 entry.

Why

PATCH is pervasive in modern REST APIs for partial updates (Google Calendar, GitHub, Stripe, …). It is currently the only common verb missing after PUT/DELETE landed, which blocks canisters from calling those endpoints. The concrete driver is a generated Motoko client for the Google Calendar API, whose partial-update operations (events.patch, calendars.patch, acl.patch, calendarList.patch) are otherwise un-callable.

Why non-replicated only

Same rationale as PUT/DELETE: in replicated mode an outcall is issued once per replica, so a mutation would hit the remote N times, and mutation responses rarely agree byte-for-byte across replicas. PATCH additionally is not guaranteed idempotent (RFC 5789 §2) — it is idempotent only for field-merge bodies — which makes the non-replicated restriction even more appropriate. The existing is_replicated machinery already covers it; no new mechanism is introduced.

Notes

  • Spec/docs change only. The corresponding runtime implementation lives in dfinity/ic.
  • Draft pending the runtime side / IC-team review.

🤖 Generated with Claude Code

Mirrors dfinity#6199 (PUT/DELETE). PATCH is a mutation, so like PUT/DELETE it is
restricted to non-replicated mode (a replicated outcall is sent once per
replica; PATCH is not guaranteed idempotent per RFC 5789). Requested in dfinity#6244.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the interface-spec Changes to the IC Interface Specification label Jun 3, 2026
@ggreif ggreif changed the title feat: allow PATCH in http_request for non-replicated calls feat: allow PATCH in http_request for non-replicated calls Jun 3, 2026
@@ -1,5 +1,8 @@
## Changelog {#changelog}

### 0.62.0 (2025-06-03) {$0_62_0}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The date should be updated and this PR merged when the feature is rolled out on mainnet.

@mraszyk mraszyk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM I'll approve when the feature is rolled out to prevent accidental merging.

@ggreif
ggreif marked this pull request as ready for review June 3, 2026 15:02
@ggreif
ggreif requested review from a team as code owners June 3, 2026 15:02
@ggreif

ggreif commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

LGTM I'll approve when the feature is rolled out to prevent accidental merging.

Thank you @mraszyk, the implementation PR sits right here: dfinity/ic#10378!

pull Bot pushed a commit to mikeyhodl/ic that referenced this pull request Jun 5, 2026
…dfinity#10378)

## What

Adds the `PATCH` HTTP method to canister HTTPS outcalls
(`http_request`), following the `PUT`/`DELETE` rollout in dfinity#8715 / dfinity#8717.

`PATCH` variants are added across every HTTP-method enum and conversion
in the outcall path:

- `ic_management_canister_types_private::HttpMethod` and the public
`ic-management-canister-types` `HttpMethod` (+ `tests/ic.did` candid +
fixture)
- `CanisterHttpMethod` (+ the `state.metadata.v1` protobuf enum, its
`.proto`, and the generated Rust)
- the `https_outcalls` service `.proto`, the adapter method mapping
(`rpc_server.rs`), and the client (`client.rs`)
- the pocket-ic REST `CanisterHttpMethod` and the pocket-ic-server
mapping

## Rejected in the execution layer until rollout

Per review, and following the staged approach from dfinity#8715: this PR
**plumbs** `PATCH` but does **not** enable it on replicated subnets yet.
`generate_from_args` and `generate_from_flexible_args` reject `PATCH`
outright with a new
`CanisterHttpRequestContextError::HttpMethodNotYetSupported` (*"The
PATCH HTTP method is not yet supported."*), independent of
`is_replicated`. This guarantees no `PATCH` `http_method` enters
replicated state before the variant is understood by all replicas
(avoiding cross-version deserialization / replay divergence during
rollout).

A follow-up PR removes the guard once the rollout is complete, at which
point `PATCH` behaves like `PUT`/`DELETE` — permitted only for
non-replicated / deterministic-response-count requests, since `PATCH` is
a non-idempotent mutation (RFC 5789 §2).

## Tests

- `canister_http.rs`: `patch_is_rejected_until_rollout` asserts `PATCH`
is rejected via both entry points; `PATCH` is dropped from the
`PUT`/`DELETE` cases in `put_delete_requires_non_replicated` and
`flexible_methods_require_deterministic_response_counts`; the
enum-stability assertion stays `[1, 2, 3, 4, 5, 6]`.
- `https_outcalls/adapter/tests/server_test.rs`:
`test_canister_http_server_patch` + a `/patch` route on the test server
(the adapter mapping is below the execution-layer guard, so it is
exercised directly).
- `rs/tests/networking/canister_http_correctness_test.rs`:
`test_patch_rejected` asserts a `PATCH` outcall is rejected.
- `httpbin-rs`: `/anything` gains a `PATCH` route.

## Notes for reviewers

- Staged rollout per @eichhorl: `PATCH` is plumbed but hard-rejected in
the execution layer; the enabling PR follows once the rollout is done.
- Built/validated by CI rather than locally.

Spec/docs companion: dfinity/portal#6245. Requested in
dfinity/portal#6244.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@marc0olo

marc0olo commented Jun 9, 2026

Copy link
Copy Markdown
Member

@ggreif @mraszyk we should make these changes in the https://github.com/dfinity/developer-docs repository

@ggreif

ggreif commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

The content of this PR has been migrated to dfinity/developer-docs as requested: dfinity/developer-docs#289 (opened as a draft from branch migrate-portal-6245).

One item for human confirmation: this PR adds a 0.62.0 changelog entry, but developer-docs already has a 0.62.0 with different content (dated 2025-05-26). The migration used 0.63.0 (TBD) as a placeholder — the correct version number should be confirmed with the IC team.

This PR (#6245) can be closed once the developer-docs PR is approved and merged.

@ggreif

ggreif commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favour of dfinity/developer-docs#289.

@ggreif ggreif closed this Jun 10, 2026
ggreif added a commit to ggreif/developer-docs that referenced this pull request Jun 19, 2026
Mirrors dfinity/portal#6199 (PUT/DELETE). PATCH is a mutation, so like PUT/DELETE it is
restricted to non-replicated mode (a replicated outcall is sent once per
replica; PATCH is not guaranteed idempotent per RFC 5789). Requested in dfinity/portal#6244.

Migrated from dfinity/portal#6245.

NOTE: The changelog entry uses 0.63.0 because developer-docs already has a
0.62.0 entry with different content. The correct version number needs
human confirmation before this PR is merged.

Co-Authored-By: Claude <noreply@anthropic.com>
mraszyk added a commit to dfinity/developer-docs that referenced this pull request Jun 29, 2026
Migrated from dfinity/portal#6245 (moved to this repo per reviewer
request — the spec is now hosted here).

### What

- `public/references/ic.did`: `method` variant → `variant { get; head;
post; put; delete; patch }`.
- `docs/references/ic-interface-spec/management-canister.md`: document
`PATCH` alongside `PUT`/`DELETE` as supported in non-replicated mode
only (two paragraphs).
- `docs/references/ic-interface-spec/changelog.md`: new `0.63.0 (TBD)`
entry.

> **Note:** the changelog uses `0.63.0` because `0.62.0` is already
present in this repo with different content (2025-05-26). Please confirm
the correct version number before merging.

### Why

`PATCH` is the last common REST verb missing after `PUT`/`DELETE` landed
(dfinity/portal#6199). It is pervasive in modern REST APIs for partial
updates (Google Calendar, GitHub, Stripe, …). The concrete driver is
generated Motoko clients for the Google Calendar API whose
partial-update operations are otherwise un-callable.

### Why non-replicated only

Same rationale as `PUT`/`DELETE`: in replicated mode an outcall is
issued once per replica; `PATCH` is additionally not guaranteed
idempotent (RFC 5789 §2). The existing `is_replicated` machinery already
covers it; no new mechanism is introduced.

### Notes

- Spec/docs change only. The corresponding runtime implementation is in
dfinity/ic#10378.
- The date in the changelog entry should be updated to the mainnet
rollout date before merging.
- Originally opened as dfinity/portal#6245; that PR will be closed once
this one merges.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

interface-spec Changes to the IC Interface Specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTPS outcalls: add PATCH to the http_request method variant

3 participants