Skip to content

Canonical: Redirect the post format, page name and author name query vars to their pretty permalinks. - #13824

Open
Pathan-Amaankhan wants to merge 3 commits into
WordPress:trunkfrom
Pathan-Amaankhan:fix/20902-canonical-query-vars
Open

Pathan-Amaankhan wants to merge 3 commits into
WordPress:trunkfrom
Pathan-Amaankhan:fix/20902-canonical-query-vars

Conversation

@Pathan-Amaankhan

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/20902

Description

With pretty permalinks enabled, /?category_name=…, /?p=…, /?page_id=… and /?author=… are redirected to their canonical URLs. The three cases from the ticket were not:

Request Before After
/?post_format=image no redirect → /type/image/
/?pagename=blog no redirect → /blog/
/?author_name=admin no redirect → /author/admin/

Changes in redirect_canonical():

  • Pages: ?pagename= is handled like ?page_id=, including the static front page (→ /), the posts page (the ticket's /?pagename=blog example, when "blog" is the posts page) and multi-page pages (&page=2 → /slug/2/).
  • Authors: ?author_name= follows the rule already used for ?author=: only authors with at least one published post are redirected.
  • Post formats: _post_format_request() adds a post_type query var to every post format request. redirect_canonical() took that for a var coming from a rewrite rule and skipped the redirect. That var is now ignored for the post_format taxonomy. _post_format_request() itself is unchanged (its is_admin() guard exists because of Trac #18475), which is where this differs from WordPress/wordpress-develop#9029.

Paging and feeds are added to the resulting URL, as they already are for categories:

Request Result
/?post_format=audio&paged=2 /type/audio/page/2/
/?author_name=admin&paged=2 /author/admin/page/2/
/?author_name=admin&feed=rss2 /author/admin/feed/
/?pagename=blog&paged=2 (posts page) /blog/page/2/
/?pagename=about&feed=rss2 /about/feed/

The paging code rebuilds the URL from the requested path, which used to discard the URL found for ?author=. That is why /?author=2&paged=2 went to /page/2/ and /?author=2&feed=rss2 to /feed/. Both now keep the author. ?pagename= on a regular page is left alone when paged is present, because paging does not apply to a page.

Extra query args are kept (/?pagename=x&foo=bar → /x/?foo=bar). Nothing is redirected for content that does not exist (unknown page, author or post format) or is not public (a draft page, an author without published posts).

About paged on the Docker development environment

On a site whose URL has a port, such as the Docker environment on localhost:8889, no request that carries paged or feed is redirected: not even /?paged=1 or /?category_name=uncategorized&paged=1 on trunk. The paging code builds $redirect_url without the port, so the "protect against chained redirects" check compares it with the requested URL and skips the redirect. That is Trac #57724 and is not changed here. Without a port in the site URL, /?post_format=image&paged=1 redirects to /type/image/.

Testing instructions

  1. Enable pretty permalinks. Publish a post with the Image format, and make sure a page and an author with a published post exist.
  2. Request /?post_format=image, /?pagename=<page-slug> and /?author_name=<author-slug> (for example with curl -I): each should return a 301 to the pretty URL.
  3. Repeat with an extra argument (&foo=bar, kept in the redirect), with values that do not exist and with a draft page (no redirect, still a 404).
  4. Optionally set a static front page or a posts page: /?pagename=<that-page> redirects to / or to the posts page URL.
  5. Run the tests: npm run test:php -- --group canonical.

Tests added: the three scenarios above with extra args, paging, feeds and negative cases in Tests_Canonical, the front page and posts page in Tests_Canonical_PageOnFront, and tests that an author without published posts is not redirected for ?author_name= (same as ?author=) and that post format requests keep their paging and feed. The audio fixture post now has the Audio format.


AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5.5
Used for: Analysing the ticket, the earlier patches, reproducing the issue on a local site, drafting the redirect_canonical() changes and the PHPUnit tests, and running the test suites and PHPCS. I reviewed the code and tests and re-checked the redirects on a local site.

Pathan-Amaankhan and others added 2 commits September 29, 2026 22:53
…vars to their pretty permalinks.

With pretty permalinks enabled, `?category_name=`, `?p=`, `?page_id=` and `?author=` requests are redirected to the canonical URL, but `?post_format=`, `?pagename=` and `?author_name=` requests were not.

* Pages: `?pagename=` is handled like `?page_id=`, including the static front page and the posts page.
* Authors: `?author_name=` follows the rule already used for `?author=`, so only authors with at least one published post are redirected.
* Post formats: `_post_format_request()` adds a `post_type` query var to every post format request, which made `redirect_canonical()` treat the request as coming from a rewrite rule. That var is now ignored for post format requests, so `_post_format_request()` itself is unchanged.

Extra query args are kept, and requests for content that does not exist are not redirected.

See #20902.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…uthor name query vars.

The paging and feed handling rebuilds the redirect URL from the requested path, which discarded the URL resolved for `?author_name=`, `?author=` and `?pagename=`. For example, `/?author_name=admin&paged=2` went to `/page/2/` and `/?author=2&feed=rss2` to `/feed/`.

Set the path of the resolved URL as well, so that paging and feeds are appended to it, as they are for terms.

Requests that cannot be paged that way keep their current behavior: `?pagename=` on a regular page when `paged` is present, and on the posts page when a feed is requested.

Adds tests for paging and feeds with post formats, authors, pages and the posts page.

See #20902.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props akrocks.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@Pathan-Amaankhan Pathan-Amaankhan changed the title Fix/20902 canonical query vars Canonical: Redirect the post format, page name and author name query vars to their pretty permalinks. Sep 29, 2026
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.

1 participant