Skip to content

fix: normalize the trailing slash on the site API root - #725

Open
dcalhoun wants to merge 1 commit into
refactor/url-trailing-slash-helpersfrom
fix/site-api-root-trailing-slash
Open

dcalhoun wants to merge 1 commit into
refactor/url-trailing-slash-helpersfrom
fix/site-api-root-trailing-slash

Conversation

@dcalhoun

@dcalhoun dcalhoun commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

What?

Ensure trailing slash on site API root configuration.

Why?

Mitigate unexpected failures from improper concatenation.

How?

Apply ensureTrailingSlash before configuring api-fetch's root URL.

Testing Instructions

N/A, not addressing known bug, merely increasing robustness.

Accessibility Testing Instructions

N/A, no user-facing changes.

Screenshots or screencast

N/A, no user-facing changes.


AI-generated details

On a site whose API root is configured without a trailing slash, every REST request the editor issues from JavaScript is malformed and 404s, so the editor cannot load its settings or the post. Native-issued requests keep working, because WordPressRESTURL (iOS) and RestUrlBuilder (Android) both normalize the root, each with a test pinning the unslashed case. The result is a site where the host app works and the web editor does not.

The cause is that createRootURLMiddleware strips the path's leading slash and concatenates, so the root has to supply the separator:

https://example.com/wp-json + wp/v2/posts -> https://example.com/wp-jsonwp/v2/posts

This is the same class of defect as #595, one level up: there the namespace ran into the following segment, here the root runs into the path.

No in-repo host emits an unslashed root today — the WP.com constant and both self-hosted fallback literals carry the slash. It is reachable because REST discovery's last-resort fallback builds the root by appending a wp-json path segment, which produces no trailing slash, and the host apps store the discovered value verbatim (blog.restApiRootURL on iOS, site.wpApiRestUrl on Android). That fallback runs when the Link header, the <link> tag, and RSD all fail but /wp-json responds — for example on sites whose security plugin strips the header.

configureApiFetch now applies ensureTrailingSlash once, where the root enters. An unset root stays empty rather than becoming /, which would otherwise resolve every request against the page itself.

Android's live editor-assets endpoint already normalizes the root (stores/EditorAssetsLibrary.kt), and iOS builds it with appending(path:), so no native change is needed.

Testing

  1. Run the unit suite:
    make test-web-unit
  2. Confirm the new cases fail without the fix. In src/utils/api-fetch.js, replace the ensureTrailingSlash( siteApiRoot ) argument in configureApiFetch with siteApiRoot, then:
    npx vitest run src/utils/api-fetch-root-url.test.js
    Three of the four cases fail: the two unnormalized roots, plus the unset root, which now relies on the helper rather than a destructuring default.
  3. Restore the change:
    git checkout src/utils/api-fetch.js

@dcalhoun
dcalhoun added this pull request to stack #726 September 23, 2026 19:10
@github-actions github-actions Bot added the [Type] Bug An existing feature does not function as intended label Sep 23, 2026
@wpmobilebot

wpmobilebot commented Sep 23, 2026 •

Copy link
Copy Markdown

XCFramework Build

This PR's XCFramework is available for testing. Add the following to your Package.swift:

.package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/725")

Built from 8f89e48

@dcalhoun
dcalhoun force-pushed the fix/site-api-root-trailing-slash branch from 4ecabd0 to 7904423 Compare September 23, 2026 19:38
@dcalhoun
dcalhoun force-pushed the fix/site-api-root-trailing-slash branch from 7904423 to a5c3c94 Compare September 23, 2026 20:18
@dcalhoun
dcalhoun marked this pull request as ready for review September 24, 2026 10:59
The root is concatenated with the request path, so a root configured
without a trailing slash runs into the path and every request 404s:
`https://example.com/wp-jsonwp/v2/posts`. Both forms are supported
input, and the native URL builders already normalize either one.

Reachable when the root comes from REST discovery's last-resort
`/wp-json` fallback, which is built without a trailing slash and stored
verbatim by the host apps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014V7YC1kW6f5ZFHtMNGcLKs
@dcalhoun
dcalhoun force-pushed the fix/site-api-root-trailing-slash branch from a5c3c94 to 8f89e48 Compare September 24, 2026 10:59
@dcalhoun
dcalhoun requested a review from adalpari September 24, 2026 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants