Skip to content

Document trailing slash canonical redirects#472

Open
samdark wants to merge 1 commit into
masterfrom
docs-trailing-slash-canonical
Open

Document trailing slash canonical redirects#472
samdark wants to merge 1 commit into
masterfrom
docs-trailing-slash-canonical

Conversation

@samdark
Copy link
Copy Markdown
Member

@samdark samdark commented May 30, 2026

Summary

  • add routing guide guidance for canonical trailing slash behavior
  • document a PSR-15 middleware that redirects trailing slash URLs before routing
  • use a 308 redirect to preserve the HTTP method and keep query strings intact

Verification

  • Used a fresh yiisoft/app template created with composer create-project yiisoft/app /tmp/yii-docs-upload-app --no-interaction
  • Checked installed Yii Router/Yii HTTP packages for built-in trailing slash support; no router switch or middleware was present
  • Added RemoveTrailingSlashMiddleware and verify-trailing-slash-canonical.php to the template app
  • Ran php -l src/Web/Middleware/RemoveTrailingSlashMiddleware.php && php -l verify-trailing-slash-canonical.php
  • Ran php verify-trailing-slash-canonical.php; verified /docs/?page=2#heading redirects with 308 to /docs?page=2 and root / passes through
  • Ran vendor/bin/phpstan analyse src/Web/Middleware/RemoveTrailingSlashMiddleware.php verify-trailing-slash-canonical.php --level=max --no-progress
  • Ran vendor/bin/psalm --no-cache --output-format=console src/Web/Middleware/RemoveTrailingSlashMiddleware.php verify-trailing-slash-canonical.php
  • Ran npx markdown-link-check src/guide/runtime/routing.md
  • Ran npm run build

Copilot AI review requested due to automatic review settings May 30, 2026 10:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds guidance to the routing guide on handling canonical URLs for trailing slashes, including an example PSR-15 middleware to normalize paths before routing.

Changes:

  • Document why /docs vs /docs/ should be normalized for SEO/caching consistency.
  • Add a RemoveTrailingSlashMiddleware example that redirects to a canonical, non-trailing-slash URL using HTTP 308.
  • Explain where to register the middleware in the application middleware stack.

Comment on lines +309 to +310
The following middleware removes trailing slashes, preserves the query string, drops the fragment, and uses `308
Permanent Redirect` so the HTTP method is preserved:
Comment on lines +324 to +346
use Yiisoft\Http\Header;
use Yiisoft\Http\Status;

final readonly class RemoveTrailingSlashMiddleware implements MiddlewareInterface
{
public function __construct(
private ResponseFactoryInterface $responseFactory,
) {
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$uri = $request->getUri();
$path = $uri->getPath();

if ($path !== '/' && str_ends_with($path, '/')) {
$canonicalUri = $uri
->withPath(rtrim($path, '/'))
->withFragment('');

return $this->responseFactory
->createResponse(Status::PERMANENT_REDIRECT)
->withHeader(Header::LOCATION, (string) $canonicalUri);
];
```

### Trailing slash canonical URLs
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

  1. It's better to be done via webserver config.
  2. Don't we have a middlware for it? Seems not.

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.

2 participants