Tricky .htaccess settings


#1

Hello, thanks for looking. I have a decent handle on regular expressions & this is not at all my first time working out sets of rules under htaccess but I’m having some baffling trouble. I’ve tried many variants of these settings under a few different domains and subdomains. Some work some don’t. I’m consistently having trouble with forcing https & forcing non-www. I’m concerned I may have a conflict with an httpd file or a control panel setting. Here is the code:

RewriteEngine On RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

FORCE HTTPS

RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]

REDIRECT INDEX TO ROOT

RewriteRule ^index.php$ / [R=301,L]
RewriteRule ^index.htm$ / [R=301,L]

STRIP UNWANTED QUERY STRINGS FROM ALL BUT EXEMPTED FILES

RewriteCond %{query_string} .
RewriteCond %{THE_REQUEST} !^./stuff.php?(.)
RewriteCond %{THE_REQUEST} !^./free_stuff.php?(.)
RewriteRule (.*) /$1? [R=301,L]

SET CUSTOM ERROR PAGES

ErrorDocument 400 /error/error_400.php
ErrorDocument 401 /error/error_401.php
ErrorDocument 403 /error/error_403.php
ErrorDocument 404 /error/error_404.php
ErrorDocument 500 /error/error_500.php

BETTER YET I’D LIKE TO USE THIS

WWW TO NON-WWW & FORCE HTTPS IN ONE SHOT

RewriteCond %{HTTP_HOST} !^(example.com)?$ [OR]
RewriteCond %{HTTPS} !on
RewriteRule (.*) httsiteurlgoeshere/$1 [R=301,L]

AND I’D LOVE TO INCLUDE THIS ALSO

PRETTY URLS FOR DYNAMIC PAGES V2

WORKS BUT HAS CONFLICT WITH STRIP UNWANTED STRINGS

RewriteRule ^([a-zA-Z0-9]+)$ stuff.php?thing=$1
RewriteRule ^([a-zA-Z0-9]+)/$ stuff.php?thing=$1


#2

I wanted to add that I got this much of it all working together:

Options -Indexes

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

FORCE HTTPS

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]

REDIRECT INDEX TO ROOT

RewriteRule ^index.php$ / [R=301,L]
RewriteRule ^index.htm$ / [R=301,L]

STRIP UNWANTED QUERY STRINGS FROM ALL BUT EXEMPTED FILES

RewriteCond %{query_string} .
RewriteCond %{THE_REQUEST} !^./font.php?(.)
RewriteCond %{THE_REQUEST} !^./free_font.php?(.)
RewriteRule (.*) /$1? [R=301,L]

SET CUSTOM ERROR PAGES

ErrorDocument 400 /error/error_400.php
ErrorDocument 401 /error/error_401.php
ErrorDocument 403 /error/error_403.php
ErrorDocument 404 /error/error_404.php
ErrorDocument 500 /error/error_500.php

One main conflict was that:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

Were interfering with the force https rule. I’d like to understand why?

There is a conflict between the the rules that prevent unwanted query strings and the rules I’m building to do the “pretty urls”. All of the files are on the same directory level so I might be able to work around it by placing some down one level. I’d like to have a better solution though.


#3

RewriteCond directives apply to the next RewriteRule found in the .htaccess file, so the not-file and not-dir conditions were applying to the HTTPS RewriteRule. The result would be that only non-file/dir requests get redirect to HTTPS.


#4

Yes, thank you. That’s the one conflict that I’ve been able to figure out so far. So silly I just kept looking past it.

Is it true that the conditions only apply to the very next single rule? I had been looking for a way to encapsulate the conditions so they didn’t “leak” out onto subsequent rules.

I’m now trying to work out the conflict between the “pretty URLs” rules and the “strip unwanted query strings” rules. Either one seems to play nice with the rest of the set but not with each other.


#5

Yes, sequences of RewriteCond and RewriteRule combine like an IF-THEN statement in other programming languages:

RewriteCond A   # IF A is true,
RewriteCond B   # And IF B is true,
RewriteRule C   # THEN, apply Rule C

Possibly your pretty-URL rewrite rules need the last flag (L) to prevent further rewriting. After a rewrite is applied, Apache re-runs all the rules again, which probably causes the unwanted-query-string rule to fire. The last flag prevents this re-processing of the rules.


#6

Thank you habilis. Well said. Saves me a wild-goose-chase.

That was a great suggestion. I was sure it was going to work but… I’ve actually tried adding several variations of the “last flag”. It doesn’t hurt anything but it doesn’t solve the problem either

STRIP UNWANTED QUERY STRINGS FROM ALL BUT EXEMPTED FILES

RewriteCond %{query_string} .
RewriteCond %{THE_REQUEST} !^./item.php?(.)
RewriteCond %{THE_REQUEST} !^./free_item.php?(.)
RewriteRule (.*) /$1? [R=301,L]

PRETTY URLS FOR DYNAMIC PAGES V2

RewriteRule ^([a-zA-Z0-9]+)$ item.php?font=$1
RewriteRule ^([a-zA-Z0-9]+)/$ item.php?font=$1

I’ve tried several other variants of each of these 2 sets of conditions & rules but the 2 methods above cause the least trouble. Some attempts would break the whole site or produce broken pages. The combination of these 2 just causes unwanted stripping of the query strings from the target file (item.php)… a relatively gentle failure.

I may have to try a totally different tact.

I’m thinking if I were to strip the file extensions from all pages with something like the “pretty url” rules for all pages it might sufficiently dissuade the adding of unwanted queries since the real file name would not be known. Then I could ditch the “strip unwanted…” bit all together.

I should be able to do something like:

^/items/([a-zA-Z0-9]+)/$ item.php?itemname=$1
^/free_items/([a-zA-Z0-9]+)/$ free_item.php?itemname=$1
^/contact$ cont.php
^/privacy$ priv.php

There are only a handful of top-level, static links I would need to rewrite. Any thoughts on how I could do this better?


#7

looks like a nice way to "strip file extensions if you’re ok with the url just being the same thing minus the file extension would look something like:

RewriteRule ^([a-zA-Z0-9]+)$ $1.php

Interestingly the “strip unwanted query strings…” bit interferes with this also. I can probably just ditch it if I go this route but why it interferes is still a mystery to me.


#8

Something like this works.

PRETTY URLS FOR DYNAMIC PAGES

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^item=([a-zA-Z0-9]+)$ item.php?itemname=$1 [L]
RewriteRule ^free_item=([a-zA-Z0-9]+)$ free_item.php?itemname=$1 [L]

PRETTY URL FOR STATIC FILES

RewriteRule ^([a-zA-Z0-9]+)$ $1.php [L]

I’ can now use URLs like https://example.com/item=itemname

If I do something like this then I can have “pretty URLs” for any number of static pages or dynamic pages with specific or non-specific parameters etc…

Since the actual file names can be obfuscated here & the file extensions are gone I can skip the rules that strip unwanted query strings.


#9

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.