How to rewrite /wp-admin/admin.php?page=something to /wp-admin/something using .htaccess

Viewed 310

I'm trying to configure my .htaccess so that when someone navigates to the path /wp-admin/admin.php?page=something, the path /wp-admin/something is shown in the browser, and the content from /wp-admin/admin.php?page=something is served.

If I navigate to /wp-admin/admin.php?page=something the page is served correctly. However, /wp-admin/something doesn't serve the content, instead it shows the default 404 page I have in my site.

My .htaccess config:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?wp-admin/?$ /wp-admin/admin.php?page=$1 [L]

RewriteBase /
ReWriteCond %{ENV:ENVIRONMENT} !^development$
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R,L]
</IfModule>

RedirectMatch 301 ^/kundeoplysninger https://signup.kredslob.dk/kundeoplysninger
RedirectMatch 301 ^/mobilepay /

# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
1 Answers

when someone navigates to the path /wp-admin/admin.php?page=something, the path /wp-admin/something is shown in the browser

This requires an external redirect. This is OK for users who have independently typed (or followed an external link) to the "old" (page=something) URL, but any internal links must be updated to point to the desired canonical URL, ie. /wp-admin/something.

Add the following immediately after the RewriteEngine directive:

# Redirect direct requests for "/wp-admin/admin.php?page=something" to "/wp-admin/something"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^page=([^&]+)
RewriteRule ^(wp-admin)/admin\.php$ /$1/%1 [QSD,R=301,L]

The $1 backreference contains the captured "wp-admin" from the URL-path (simply saves repetition) and the %1 backreference contains the "something" from the query string, captured in the preceding RewriteCond directive.

The QSD flag (Apache 2.4+) is required to remove the query string from the redirect response.

The check against the REDIRECT_STATUS environment variable is necessary to prevent the rewritten request (see below) from being redirected. Only direct requests from the client are redirected.

and the content from /wp-admin/admin.php?page=something is served

Immediately after the above redirect, we need to internally rewrite the request from the requested /wp-admin/something back to the format the server understands, ie. /wp-admin/admin.php?page=something.

Add the following after the above redirect.

# Rewrite "/wp-admin/something" back to "/wp-admin/admin.php?page=something"
RewriteRule ^(wp-admin)/([^.]+)$ $1/admin.php?page=$2 [L]

The capturing regex ([^.]+) excludes the dot so that it naturally avoids matching requests of the form admin.php, thus preventing a rewrite loop. The alternative is to avoid rewriting requests that map to physical files, but filesystem checks are relatively expensive so are best avoided if possible.

Related