Need help with RewriteRule (mod_rewrite) to redirect special files to HTTPS
Discuss Need help with RewriteRule (mod_rewrite) to redirect special files to HTTPS in the Apache Development forum on Dev Shed. Need help with RewriteRule (mod_rewrite) to redirect special files to HTTPS Apache Development forum discussing HTTP Server general topics, configuration, and modules. Apache is an open source web server that runs on multiple platforms.
Posts: 366
Time spent in forums: 1 Day 9 h 30 m 48 sec
Reputation Power: 13
Need help with RewriteRule (mod_rewrite) to redirect special files to HTTPS
Hi all,
I am pretty close on this and have this partially working all thanks to the great mod_rewrite sticky guide provided by jharnois!
My premise is pretty simple:
If the protocol is currently 80 and the filename the user is looking at is "signup.php", "signup_process.php" or "signup_conf.php" then force the user from HTTP to HTTPS
If the protocol is currently 443 (SSL) and the filename is not one of the three aforementioned files, then redirect the user from HTTPS to HTTP.
I was able to get both redirects functioning properly using only one of the files (signup.php). But when I try and get all fancy and add three files, I fail.
I assumed I needed to use RewriteCond (conditions) to specify my three files to match (maybe this isn't the correct way). I think my problem may be in the RewriteCond usage, or in the RewriteRule where I am specifying the "^(.*)$" since I actually am not even sure what that does - I just assumed that was a catch-all or wildcard match. Or it is in how I am trying to specify the REQUEST_URI matching files. Basically I want this to do the redirect to secure HTTPS if any of the files above are matched.
Can anyone point our where I am making my mistake and suggest a way to make this work? Much much thanks.
Posts: 12,703
Time spent in forums: 5 Months 1 Week 4 Days 5 h 39 m 40 sec
Reputation Power: 8969
It's not spelled out in the docs but I believe ANDing two RewriteConds has precedence over ORing. Or maybe it's the same precedence and they're left-to-right (or rather top-to-bottom). Thus you've written
Code:
(HTTP and signup.php) or (signup_process.php) or (signup_conf.php)
1. Use the HTTPS flag, not the port number.
2. The REQUEST_URI is the entire URL as requested.
3. Put the list of files in the RewriteRule.
Code:
RewriteCond %{HTTPS} off
RewriteRule ^(signup|signup_process|signup_conf).php$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
RewriteCond %{HTTPS} on
RewriteRule !^(signup|signup_process|signup_conf).php$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R]
Posts: 366
Time spent in forums: 1 Day 9 h 30 m 48 sec
Reputation Power: 13
requinix,
Awesome, that totally did the trick. I was wondering myself about how mod_rewrite would work with AND and OR together, but looking back at the documentation, you are correct... it does not really talk about precedence.
I had wondered about doing the (file|file2|file3) syntax, but so few examples I have seen talk about anything other than redirecting directories, or entire servers from HTTP to HTTPS.
But I am glad I now have everything working flawlessly on my production servers.
Posts: 366
Time spent in forums: 1 Day 9 h 30 m 48 sec
Reputation Power: 13
Postmortem to the prior solution... a gnarly wrinkle.
After testing my order process fully with the new mod_rewrite directives, I realized I still had a problem. This has nothing to do with the solution provided by requinix, which worked flawlessly, it was because I hadn't fully tested the process from end-to-end and forgot about a key component.
The problem was that all of the order data in the signup form was being lost somewhere between the passing of the data to our external merchant provider from the "signup_process.php" script and when the data was sent back from the vendor to our "create_order.php" script.
The culprit was upon the return from the call to our "create_order.php" script by our external vendor, that call - which is supposed to be a HTTPS secure call, was being rewritten to a HTTP based URI. This caused all the POST data in the form to be lost (I am not sure why that happens, but I suppose HTTP and HTTPS protocols don't share data sessions).
To solve the redirect issue, I went ahead and added the "create_order.php" script to my mod_rewrite directives in my httpd.conf files from above, but it didn't solve the problem. I surmised this was because the "create_order.php" script is actually in another directory, one level deeper from the main directory "/orders/" named "/orders/data_store/"
My full processing flow (for those following this posting) is:
* means this script is one directory deeper than the main directory
For some reason, even though the external site called the script using a fully qualified https://... URI, the prior mod_rewrite was still forcing it to be HTTP:, even though I added the name of the script to my mod_rewrite. This caused the "create_order.php" script to lose all the passed POST variables, thus killing the order process with an error.
I am not sure why this was forcing the mod_rewrite to HTTP for the "create_order.php" script even though I had it in my http.conf file... maybe mod_rewrite in a <directory> section cannot follow hierarchical directories. That would answer the problem, but I don't know. Maybe someone can shed some light on this.
In the end, I was able to solve my problem by adding a new directory section to my http.conf files named: <Directory "/Library/WebServer/Documents/orders/data_store">, for the subdirectory that has just the one new filename "create_order.php". This fixed the issue of the data being lost in the rewrite since it wasn't switching protocols for the create_order.php script anymore :-)
Maybe adding a whole other <directory> section wasn't the best way to solve this problem and there is a way to reference the subdirectory where the "create_order.php" file lives using the original mod_rewrite directives. So if anyone has any comments or advice on this particular issue of the solution, I am happy to tweak my code to make it cleaner and more efficient.
Posts: 12,703
Time spent in forums: 5 Months 1 Week 4 Days 5 h 39 m 40 sec
Reputation Power: 8969
Quote:
Originally Posted by jkoerber
The culprit was upon the return from the call to our "create_order.php" script by our external vendor, that call - which is supposed to be a HTTPS secure call, was being rewritten to a HTTP based URI. This caused all the POST data in the form to be lost (I am not sure why that happens, but I suppose HTTP and HTTPS protocols don't share data sessions).
The problem is the redirect. Technically speaking browsers should repeat the same POST request to the new URL, but in practice they do not (anymore). It actually turns from a POST with data into a GET at the new location.
So regardless of URL rewriting, POSTed forms must always point to the right location - any redirects will kill the process.