0

I want to redirect to https and add a trailing slash in one redirect.

This is my current .htaccess:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule .* https://www.test.ru%{REQUEST_URI} [L,R=301]


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*[^/])$ https://www.test.ru/$1/ [L,R=301]

When I open a fake url I get two redirects

http://www.test.ru/documents/test
301 Moved Permanently
https://www.test.ru/documents/test
301 Moved Permanently
https://www.test.ru/documents/test/

Is there any way to combine this into one redirect?

http://www.test.ru/documents/test
301 Moved Permanently    
https://www.test.ru/documents/test/

This may also be related

RedirectMatch 301  ^/fitness/$  /services/fitness/
RewriteRule ^fitness/$ services/fitness/ [R=301,L]

What is wrong on this server? I have the feeling that the rules are executed one by one in turn.

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
Sliva
  • 63
  • 6

1 Answers1

1

When you use the [L] flag with a redirect flag [R=301], Apache will immediately redirect ignoring the other rules. The two back-to-back redirects are expected with your current rule.

You can combine the two rules with the [OR] flag. I have left out the X-Forwarded-Proto condition, since if you run a load balancer you should just configure it correctly.

RewriteCond %{HTTPS} off [OR]
RewriteCond %{REQUEST_URI} !.*/$
RewriteRule ^(.*)/?$ https://www.test.ru/$1/ [R=301,L]

With these rules we first test if the url matches ^(.*)/?$. This is always true. The last slash is optional because of the ? after it, and the capture group just captures everything before it.

Then we check if https is off. If it is, we execute the rule and redirect. If we are already on https, we check the second condition and check if the url does not end with a slash. If this condition is true we also execute the rule.

The rule itself makes sure to match everything of the url before the slash. This way we can always add the slash at the end without ending up with multiple slashes. The protocol and host are not variable, so we have just hardcoded it here.

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
  • Thank you very much, this is exactly what I couldn't remember about the order of redirects. it remains to figure out how to configure it correctly. the site is old, there are thousands of 2 redirects and shoveling everything - the client is not ready. But this does not answer probably the main question, why when a redirect is written Redirect 301 /old-page/ /new-cat/old-page/ then first redirect to http that's unclear most of all this. the page opens over https, but the redirect goes to http and then back, and then everything is normal. – Sliva Nov 19 '21 at 10:39
  • `Redirect` and `RedirectMatch` are handled by a different Apache module than `RewriteRule`. They don't combine when just doing redirects, or even interact with each other. Why it would redirect to http though I am not sure. – Sumurai8 Nov 19 '21 at 10:44
  • I tried RewriteRule and the result is the same: first redirect to http then back to https. It works correctly only if you directly specify the protocol. The feeling is that by default, without directly specifying the protocol, RewriteRule creates a redirect to http – Sliva Nov 19 '21 at 11:18