I'm trying to make a redirect with htaccess. Let's say that I have two websites:

  • www.oldsite.example
  • www.newsite.example

What I want to do is redirect old to new with random_file.html renamed to /random_file/ Example how I would like it to work: http://www.oldsite.example/shop.html?some_string_to_pass would redirect to http://www.newsite.example/shop/?some_string_to_pass

So far I came up with something like this:

RewriteEngine on 
RewriteRule ^([^/]+).html?(.*)$ /$1/$2 [R=301,L]
RewriteRule ^(.*)$ http://www.newsite.example/$1 [R=301,L]

But it doesn't seam to work as I planned. The first rule takes care of the file.html and redirects it to /file/ but only in main directory of the site.

When I try to enter: http://www.oldsite.example/shop/product.html, I get: http://www.oldsite.example/shop/product.html instead of the http://www.oldsite.example/shop/product/ that I wanted.

Is there any option for it to work on all of the directories? What am I missing?

And is it possible to combine those rules together? Because the second rule does not work when I place it after the first one and it does not delete the .html when on first position.


1 Answer 1

RewriteRule ^([^/]+).html?(.*)$ /$1/$2 [R=301,L]

This only "works" on the document root, because your regex ([^/]+) specifically excludes slashes, so it will not match any URLs that contain a path segment.

You also can't capture the query string with the RewriteRule directive - this matches against the URL-path only. (?(.*) isn't doing what you think it's doing - it's simply making the preceding l optional.) But your substitution /$1/$2 doesn't follow your example? Your example shows that the query string is passed through unaltered, whereas this directive implies the query string should be added as an additional path segment?

If you want the query string to be passed through unaltered (as in your example) then you don't actually have to do anything, since this is the default behaviour!

And is it possible to combine those rules together?

There is no need for a second rule here. Like you say, it's not doing anything anyway.

Try the following instead:

RewriteEngine on 
RewriteRule ^(.+)\.html$ http://www.newsite.example/$1 [R=301,L]

The pattern (.+) simply captures everything before the .html. The literal dot should be backslash escaped. Any query string on the request is passed through to the target URL unaltered.

You will need to make sure your browser cache is clear before testing. (Can be easier to test with 302s for this reason.)

  • 1
    Biggest thanks! that did the trick! You are the first one to explain to my how it works :)
    – user77389
    Commented Apr 3, 2018 at 15:32

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.