2

I'm creating SEO friendly URLs with rewrites in .htaccess.

Now I need to redirect (301) a couple of these rewrites, and have no idea how to do that.

These lines:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ /engines/index.php?engine_id=$1&urlTxt=$2 [L]

Creates the following URL:

 /engines/1009/malilla-35-hp-1938

Now I need to redirect that URL to

(Note the extra BRB):

/engines/1009/malilla-brb-35-hp-1938

Catch-22?

Thanks,

1
  • 2
    Is your .htaccess file located at /engines/.htaccess? Is this a one-off redirect? Or are you wanting to insert -brb in all URLs that follow a specific pattern?
    – MrWhite
    Commented Jan 17, 2023 at 14:42

1 Answer 1

2

It would seem your .htaccess file is located in the /engines subdirectory (otherwise that rule won't match the stated URL).

There's no "Catch-22" here, in fact this looks like a simple redirect. The confusion may come about from a possible misunderstanding of the existing "rewrite rule"? That rule doesn't actually "create" the URL as such. The URL is already created when you make the initial request (eg. by clicking the link). That "rewrite rule" allows a URL of the form /engines/<id>/<txt> to "work" by internally rewriting the request to the underlying file /engines/index.php?engine_id=<id>&urlTxt=<txt> that actually handles the request.

You need to issue a redirect before the existing rewrite. So that it applies to the initial request and not the rewritten request.

To implement the stated redirect you should use mod_rewrite again (just as you are doing for the internal rewrite) and this rule needs to go before your existing rewrite (the order of the rules is important):

RewriteRule ^1009/malilla-35-hp-1938$ /engines/1009/malilla-brb-35-hp-1938 [R=301,L]

Alternatively, use backreferences to avoid repetition:

RewriteRule ^(1009/malilla)(-35-hp-1938)$ /engines/$1-brb$2 [R=301,L]

Where $1 and $2 contain the text from the corresponding capturing subgroups in the preceding RewriteRule pattern.

Summary

The resulting rules should then look like this:

Options +FollowSymLinks

RewriteEngine On

RewriteRule ^(1009/malilla)(-35-hp-1938)$ /engines/$1-brb$2 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ /engines/index.php?engine_id=$1&urlTxt=$2 [L]

Aside:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ /engines/index.php?engine_id=$1&urlTxt=$2 [L]

It looks like you could be more specific with the regex and avoid the need for the preceding conditions (RewriteCond directives) that perform the filesystem checks.

For example, assuming the engine_id is numeric only and the urlTxt cannot contain dots then the above can be reduced to a single directive, thus avoiding the filesystem checks (which is more efficient):

RewriteRule ^(\d+)/([^/.]+)/?$ /engines/index.php?engine_id=$1&urlTxt=$2 [L]

(I'm assuming there are no subdirectories that have numeric-only names.)

I would also be wary of allowing an optional trailing slash on the rewrite. This potentially permits duplicate content, since both URLs serve the same content. Your example URL does not include a trailing slash so it's possible this could simply be removed.

1
  • What great answer, much appreciated, thank you very much. Also a crystal clear explanation.
    – Aknot
    Commented Jan 18, 2023 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.