Search code examples
.htaccessmod-rewritemod-alias

301 redirect with wildcard in htaccess file not working


I am trying to redirect these pages

  • /reviews/page/2/
  • /reviews/page/3/

to this

  • /reviews/

using this line:

Redirect 301    /reviews/page/./    /reviews/

But it's not working. I've tried other combinations like .* and ^.*$ but nothing works. Only a specific URL will get redirected to the new one.

Is there anything else that could interfere with the line I'm trying to work? Maybe space, uppercase, lower case, indent, etc?

The whole file is pasted below.

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
#  --------------------------------
# | ADDITIONAL RULES               |
#  --------------------------------
<FilesMatch "^robots\.txt">
Order Allow,Deny
Allow from all
</FilesMatch>
<FilesMatch "^\.htaccess|.*\.cgi">
Order Deny,Allow
Deny from all
</FilesMatch>

Redirect 301    /reviews/page/./    /reviews/

Solution

  • The mod_alias Redirect directive is prefix-matching, it does not accept wildcards or regex. So, you could theoretically do something like:

    Redirect 301 /reviews/page/ /reviews/
    

    However, as mentioned, the Redirect directive is prefix-matching and everything after the match is copied onto the end of the target URL. So, a request for /reviews/page/2/ would be redirected to /reviews/2/ - which is not desirable.

    You could use RedirectMatch instead, which uses regex rather than simple prefix matching. However, since you are already using mod_rewrite (RewriteRule) directives, it is preferable to use mod_rewrite for this in order to avoid potential conflicts. Different Apache modules execute at different times during the request, regardless of the apparent order of these directives in the config file.

    Instead, try the following mod_rewrite directive at the top of your .htaccess file, immediately after the RewriteEngine directive:

    RewriteRule ^reviews/page/[23]/$ /reviews/ [R=302,L]
    

    This matches any request for /reviews/page/2/ or /reviews/page/3/ and redirects to /reviews/. The 2 or 3 are matched using a character class. Note that in per-directory .htaccess files the URL-path that the RewriteRule pattern matches against does not start with a slash.

    This is also a 302 (temporary) redirect. Change this to 301 (permanent) redirect - if that is the intention - but only after you have tested that it's working OK. 301s are cached hard by the browser, so can make testing problematic.

    You'll need to clear your browser cache before testing.


    UPDATE: To match any digit you can change [23] to \d (the shorthand character class for digits. To match 1 or 2 digits, you can use \d{1,2}. For example:

    RewriteRule ^reviews/page/\d{1,2}/$ /reviews/ [R=302,L]
    

    You could use . (dot) to match any character. However, this might be too broad for what looks like a page number. Regular expressions (regex) should be as restrictive as possible.