Search code examples
regexwordpressapache.htaccesshttp-redirect

Query string not redirected on deeper level directories


I want to redirect each link with a query string to a specific address by appending the string. I have the following in my WordPress .htaccess:

RewriteEngine On
RewriteCond %{QUERY_STRING} catid=([0-9]+) [NC]
RewriteRule (.*) catid%1? [R=301,L]

When a user hits example.com/?catid=10, they are successfully redirected to example.com/catid10, which is what I want.

However, when they go a directory deeper (example.com/category/?catid=10), they are not redirected to example.com/category/catid10.

I have been reading manuals but can't find the answer.

Edit

If this is helpful, this is what WordPress has defined in my htaccess:

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]

Solution

  • Providing RewriteBase / is already defined (which it normally is with WordPress and must be if your existing redirect is working) then you can do it like the following with a single rule:

    RewriteCond %{QUERY_STRING} (?:^|&)catid=(\d+) [NC]
    RewriteRule (.*?)/?$ $1/catid%1 [QSD,R=301,L]
    

    The capturing group (.*?) is non-greedy so does not consume the optional trailing slash that follows.

    Requests for the document root do not require RewriteBase, but all "deeper" URLs do, since the resulting substitution string will otherwise be a relative URL.

    The non-capturing (?:^|&) prefix on the CondPattern ensures that it only matches the URL parameter name catid and not foocatid etc.