Repository navigation
fix: send cross-origin writes with their real method - #841
Merged
Merged
Conversation
XCFramework BuildThis PR's XCFramework is available for testing. Add the following to your .package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/841")Built from f8daefd |
api-fetch sends PUT, PATCH and DELETE as POST with an X-HTTP-Method-Override header. WordPress's CORS preflight doesn't allow that header, so cross-origin writes fail, e.g. from Android to sites whose REST API lives on another host. WordPress reads `_method` as the same override and it needs no preflight approval. Refs CMM-2553 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dcalhoun
force-pushed
the
fix/cross-origin-method-override
branch
from
October 30, 2026 12:39
4555521 to
1132375
Compare
WordPress applies `_method` to the CORS preflight too, which carries no credentials, so the preflight fails authentication with a 401. The real PUT, PATCH and DELETE methods are allowed by the preflight. Refs CMM-2553 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`fetch` normalizes `put` and `delete` but not `patch`, and the CORS preflight compares methods case-sensitively, so a lowercase `patch` was still blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`isPreflighted` returned true for the iOS dev server, whose requests go through the relay without a preflight; the new name says what the check actually tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The relay's comments said a cross-origin editor cannot send DELETE, which is no longer true now that cross-origin writes use their real method. Removing the relay is left for a follow-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Whether to remove the relay is still undecided, so the comments point to the issue tracking it rather than presuming the outcome. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dcalhoun
marked this pull request as ready for review
October 30, 2026 13:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Close CMM-2553. Send the real
fetchmethod rather than a method-override header for cross-origin requests.Core places
PUTandDELETEmethods as headers to mitigate disruption from servers that block these methods. However, the header is not allowed cross-origin, which causes these requests to fail.This prepares for editor-driven saving, where the editor will send these requests to save posts. It also fixes plugins that send these requests, which fail cross-origin today.
Add logic to the GutenbergKit
api-fetchhandler to restore the real method for cross-origin requests. Same-origin requests keep the header.Testing instructions
Tip
The Chrome inspector seems to often timeout when using GutenbergKit's local dev server with an emulator. Consider using a physical device and/or a local production build instead (
make build).The editor doesn't send writes yet, so these steps send them from the WebView console.
make build, then build and install the Android demo app. Use the production build, not the Vite dev server: the dev server makes every request cross-origin.make login-android-app SITE=<site>.chrome://inspect.PUTand aDELETEtopublic-api.wordpress.com, with noX-HTTP-Method-Overrideheader./wp-json/with theX-HTTP-Method-Overrideheader.On
trunk, the PUT fails on the Simple site, becausepublic-api.wordpress.com's CORS preflight doesn't allow theX-HTTP-Method-Overrideheader.Additional AI-generated details
api-fetch's built-in
httpV1Middlewaresends PUT, PATCH and DELETE as POST with anX-HTTP-Method-Overrideheader. Core WordPress's andpublic-api.wordpress.com's CORS preflight responses allow those methods but not that header, so a cross-origin write fails before it's sent. On Android, that covers Simple sites, which the editor reaches throughpublic-api.wordpress.com. Atomic and Jetpack sites use their own/wp-json/, so they're same-origin. Editor writes don't exist yet, but editor-driven saving needs them.A new fetch-handler wrapper,
withCrossOriginRealMethod, restores the real method and drops the header when the page is HTTP(S) and the request is cross-origin.httpV1Middlewareruns after every GBK middleware, so the change has to happen in the fetch handler.file:page is never preflighted._methoddoesn't work. The first commit used the_methodquery parameter. WordPress applies it to the preflight too, which carries no credentials, so the preflight returns 401. That happens on bothpublic-api.wordpress.comand core.HeaderDisallowedByPreflightResponse; the branch'sPUTandDELETEreturn 200.PUT,PATCHandDELETE.🤖 Generated with Claude Code