WordPress.org

Make WordPress Core

Opened 4 months ago

Last modified 4 months ago

#49069 new defect (bug)

Multisite: 404 template isn't used in network installs when a file extension is used in the URL

Reported by: henry.wright Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: General Keywords: 2nd-opinion dev-feedback
Focuses: multisite Cc:

Description

The WordPress 404 template isn't used when certain URLs are visited. For example:

Note this seems to happen in network installs only. I can't reproduce when using a single install.

Change History (6)

#1 @pbiron
4 months ago

  • Focuses multisite added

This only happens when the file extension is .php and is because of the .htaccess rewrite rules that are used with multisite.

multisite sub-directory rewrite rules

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ \$1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) \$2 [L]
# the following rule is the "culprit" and is necessary for URLs like:
# https://example.com/sub-site/wp-login.php
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ \$2 [L]
RewriteRule . index.php [L]

multisite sub-domain rewrite rules

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ \$1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) \$1 [L]
# the following rule is the "culprit" and is necessary for URLs like:
# https://sub-site.example.com/wp-login.php
RewriteRule ^(.*\.php)$ \$1 [L]
RewriteRule . index.php [L]
Last edited 4 months ago by pbiron (previous) (diff)

#2 @pbiron
4 months ago

Because of those 2 .htaccess rewrite rules the web server, and not WP, handles those requests, which is why the 404 template never gets called.

#3 @apedog
4 months ago

ErrorDocument directive is your friend.

https://httpd.apache.org/docs/2.4/custom-error.html

#4 follow-up: @henry.wright
4 months ago

@apedog

The pattern matching described by @pbiron could be improved rather than fixing this at the server level

#5 @pbiron
4 months ago

  • Keywords 2nd-opinion dev-feedback added

@henrywright Unfortunately, as far as I know, the RewriteCond syntax is not expressive enough to "improve the pattern matching".

However, I'm not sure if this is what @apedog was suggesting in his comment (and I'd never thought of this before), but since the ErrorDocument directive is allowed in .htaccess, changing the multiste mod_rewrite rules to the following seems to works:

new multisite sub-directory rewrite rules

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# the following is the new rule.
# it forces WP to handle the request when apache detects a 404 as a result of
# the "RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]" rule.
ErrorDocument 404 /index.php

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?fwp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

new multisite sub-domain rewrite rules

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# the following is the new rule.
# it forces WP to handle the request when apache detects a 404 as a result of
# the "RewriteRule ^(.*\.php)$ $1 [L]" rule.
ErrorDocument 404 /index.php

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]

I've tried the above on a few local multisites and it seems to work. I haven't tested it enough to know whether it will cause unintended consequences. Would love to get some more feedback from others.

As I've never used nginx, I have no idea whether there is an equivalent for it's rules (or IIS, for that matter).

#6 in reply to: ↑ 4 @apedog
4 months ago

@henrywright
I've no experience with multisite, so I've no idea why WordPress's default .htaccess rules are as they are.
I was treating this as a support question. Figuring this ticket would be flagged as invalid by someone else down the road, I thought I'd chime in with an easy solution.

Adding an ErrorDocument rule by default might be considered an opinionated solution, that could affect others in ways I don't know.
I've no idea if WordPress should redirect server 404's to a WordPress document. And even if so, if it perhaps should redirect to /404.php and not /index.php.

Adding a line of code to your .htaccess is an easy and reasonable fix.

Note: See TracTickets for help on using tickets.