1

I have the following in my .htaccess file:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On

    # Block hidden directories
    RewriteRule "(^|/)\." - [F]

    # Prevent /health_check.php from using https
    RewriteCond %{REQUEST_URI} !(health_check\.php)$

    # Prevent /sns from using https but this DOES need codeigniter rewriting (see below)
    RewriteCond %{REQUEST_URI} !^/(sns)/

    # Reroute http to https
    RewriteCond %{HTTP:X-Forwarded-Proto} =http
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

    # Prevent rewriting of domain for codeigniter
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

</IfModule>

It all seems to be working OK except for the /sns part. I can't get this to stop redirecting to https.

I would like http://sub.example.com/sns and http://sub.example.com/health_check.php to not redirect to https.

MrWhite
  • 11,643
  • 4
  • 25
  • 40
Tom
  • 133
  • 6
  • Please include a complete example of the (`/sns`) URL you are trying to prevent from being redirected. Is Codeigniter itself issuing this redirect later in the request? (_Aside:_ You should remove the `./` prefix on the `RewriteRule` _substitution_.) – MrWhite Feb 22 '18 at 11:51
  • Added the complete URLs I want to prevent... – Tom Feb 22 '18 at 11:59
  • The regex in your rule includes a trailing slash, but your stated URL does not?! (Or is this a typo?) – MrWhite Feb 22 '18 at 12:10
  • It could be either to be honest, but it will probably be without – Tom Feb 22 '18 at 12:23
  • Can you just clarify the URL you are being redirected to? Is it `https://sub.example.com/sns` or `https://sub.example.com/index.php/sns`? Also, you've stated a subdomain. Do you have another site on the main domain? Does this other site share the same filespace? – MrWhite Feb 22 '18 at 15:22

1 Answers1

0
# Prevent /sns from using https but this DOES need codeigniter rewriting (see below)
RewriteCond %{REQUEST_URI} !^/(sns)/

If the request URL does not end with a trailing slash (as stated), then the above rule (which includes the trailing slash on the CondPattern) will always be successful (it's a negated condition), so the redirect to HTTPS will always occur.

Ideally, you should be canonicalising the trailing slash earlier in the request. Either include the trailing slash or not (otherwise, it's essentially duplicate content and could potentially cause problems with other scripts that parse the URL).

However, to handle the two URLs /sns and /sns/ then you need to make the trailing slash optional and include the end-of-string anchor (^). For example:

RewriteCond %{REQUEST_URI} !^/sns/?$

Note that this only matches the two URLs stated. It will not match a URL of the form /sns/<something>.

I've removed the parentheses around the path segment (you should also remove other parentheses in your regex). This creates a captured group and is superfluous in the directives you have posted.

UPDATE: You'll also need an additional check to make sure the rewritten URL (ie. /index.php/sns) is not redirected. You can do this in a more general way by only applying the HTTPS redirect on the initial request, not the rewritten request, by including an additional condition:

# Only applies to direct requests (not rewritten requests)
RewriteCond {%ENV:REDIRECT_STATUS} ^$

The REDIRECT_STATUS environment variable is set to "200" after the first successful rewrite (ie. the CodeIgniter routing). It is not set on the initial request (ie. ^$ - empty string).

If this still results in a redirect then it's possible that CodeIgniter itself is triggering the redirect (after .htaccess has been processed).

RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

Aside: And as noted in my comment, you should remove the ./ prefix on the RewriteRule susbtitution. See the end of my answer on this StackOverflow question for an explanation.

Summary

Options +FollowSymlinks
RewriteEngine On

# Block hidden directories
RewriteRule ^\. - [F]

# Only applies to direct requests (not rewritten requests)
RewriteCond {%ENV:REDIRECT_STATUS} ^$

# Prevent /health_check.php from using https
RewriteCond %{REQUEST_URI} !health_check\.php$

# Prevent /sns from using https but this DOES need codeigniter rewriting (see below)
RewriteCond %{REQUEST_URI} !^/sns/?$

# Reroute http to https
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Prevent rewriting of domain for codeigniter
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

The HTTP to HTTPS redirect should ultimately be a 301 (permanent) redirect, but only once you have confirmed it's working OK. The R flag on its own defaults to a 302 (temporary) redirect.

(You don't need the <IfModule> wrapper either, unless you site is intended to work without mod_rewrite?)

MrWhite
  • 11,643
  • 4
  • 25
  • 40