Apache .htaccess redirect removes form data - apache

To maintain consistency across my app, I need all requests to include www so I use .htaccess file like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www\.) [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,QSA,NC,L]
</IfModule>
It works just fine. HOWEVER, when POST requests are sent without the www the form data gets stripped out. Is this expected? Is there a way to correct this?

A Redirect response with status such as 301,302, or 303 is always handled as a GET in every browser I've encountered. Hence, a POST request redirected will be seen by the client browser and it will issue a GET request to the URL provided in the redirect response. See my answer to the following question and the comments others added for details how you might work around this gracefully:
Apache 301 Redirect and preserving post data

Related

How to setup request proxy using URL rewriting

I have an e-commerce site that resides in:
http://dev.gworks.mobi/
When a customer clicks on the signin link, the browser gets redirected to another domain, in order for authentication:
http://frock.gworks.mobi:8080/openam/XUI/#login/&goto=http%3A%2F%2Fdev.gworks.mobi%3A80%2Fcustomer%2Faccount%2Flogin%2Freferer%2FaHR0cDovL2Rldi5nd29ya3MubW9iaS8%2C%2F
I'm trying to rewrite http://dev.gworks.mobi/* to http://frock.gworks.mobi:8080/openam/*, without redirection.
I've tried this in the .htaccess of the dev.gworks.mobi site:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/openam(.*)$ [NC]
RewriteRule ^(.*)$ http://frock.gworks.mobi:8080/$1 [P,L]
</IfModule>
But when I access http://dev.gworks.mobi/openam, it shows a 404 page not found page.
Can anyone help me to achieve my use case?
Try this:
RewriteEngine on
RewriteBase /
# Make sure it's not an actual file being accessed
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Match the host
RewriteCond %{HTTP_HOST} ^dev\.gworks\.mobi
# Rewrite the request if it starts with "openam"
RewriteRule ^openam(.*)$ http://frock.gworks.mobi:8080/$1 [L,QSA]
This will rewrite all the requests to dev.gworks.mobi/openam to frock.gworks.mobi:8080.
If you want to mask the URI in a way that it's not visible to the visitor that she's visiting the authentication app, you need to add a P flag. Please note that it needs Apache's mod_proxy module in place:
RewriteRule ^openam(.*)$ http://frock.gworks.mobi:8080/$1 [P,L,QSA]
Feel free to drop the L flag, if it's not the last rewrite rule. See RewriteRule Flags for more information.
The 404
If it's all in place and you're still getting a 404 error, make sure that the target URL is not throwing 404 errors in the first place.
Second, check if you're still getting the error with the correct referrer URI set. It might be designed in a way to throw a 404, if the referrer is not correctly set. If that's the case, which I suspect, you need to use the R flag and redirect instead of proxying the request.
Last thing that comes to my mind, some webapps are not built in a way to figure out the URI address. The host, as well as the port number, might be hard-coded somewhere in the config files. Make sure that the authentication app is able to be run from another URL without the need to edit the configs.
Test
You can test the rewriterule online:

Redirecting HTTP to HTTPS without Redirect 301

I need to have https by default on my site, so I used this .htaccess code to redirect all http traffic to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Everything works great, except that website receives many POST requests coming to old http:// address, and POST data is lost when 301 is used. I can NOT stop POST requests from coming to old http:// address because they come from PHP-based scripts (installed on clients' servers), so my only possible options seem to be 307 or 308 redirects (because they keep POST data).
However, redirect 307 is considered as temporary, while I plan to use https permanently, so it doesn't seem to be the best choice? Of course, I can use 308, but this one seems to be "new" and isn't properly supported by all browsers (according to many comments I found on stackoverflow). Maybe someone knows a better rewrite rule to be used in .htaccess?
P.S. I know the best idea is to use 301 redirect and modify scripts to post data to https by default (and I did so already), but it may take a very long time while all clients will update scripts on their servers, that's why another workaround is needed too.
Keep the 301, change your conditions to these:
RewriteCond %{HTTPS} =off
RewriteCond %{REQUEST_METHOD} !=POST
If your clients' legacy scripts use any other method, you will have to change the second condition to include it, e.g.:
RewriteCond %{REQUEST_METHOD} !^(?:POST|PUT)$
Normal requests/crawling will always start with GET or HEAD thus be forced to use https, so subsequent requests will also use it. Make sure all the URLs in your site's content are relative or root-relative.

If specific URL not found - 301 to root

Basically I'm trying to edit my .htaccess file to do the following:
I want to 301 a URL to another URL but ONLY if that URL is not found (404).
Thus the following will not suffice, seeing as it will redirect the URL regardless of whether or not the URL was found.
Redirect 301 /oldpage.html http://www.example.com/newpage.html
Is this possible to do through .htaccess?
And yes, I know this might be an odd request but I have my reasons for needing this.
Try this mod_rewrite rule in your root .htaccess:
RewriteEngine On
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^oldpage\.html http://www.example.com/newpage.html [L,NC,R=302]
You really don't want to 301 a URL to another URL. Permanent redirects cause all sorts of problems which cannot be reverted.
I want to 301...if that URL is not found (404).
Again, that's a really bad idea. Even if your deployment and testing processes are perfect you need to be able to see and respond to the requests coming in.
Use an error document to display a message with a meta redrect after a delay to bounce the user back to the home page.

Change URL in browser without redirection with htaccess

I've looked everywhere to find the proper solution/method but I can't seem to find anything that works for me.
I even asked friends and they helped but none prevailed.
What i'm trying to do is, changing the URL displayed in the browser but only that. (No rediraction, page re-loading).
I want to do this to make my UCP just cleaner looking when going through certain pages/files.
What am I trying to achieve?
Heres an example on a profile, the URL would be:
mysite.com/ucp/profile.php?player=Heartfire
However, I want it to look like
mysite.com/ucp/profile/heartfire
Or something else! I just want to get rid of the parameters AFTER the .PHP
I've tried various examples found with google and this website but none seems to work, could somebody please guide me along the way to achieve the result.
what have I tried so far?
Here are a few examples of what I tried before:
RewriteRule ^profile/([0-9]+)/?$ /ucp/profile.php?player=$1
RewriteRule profile.php?player=$1 profile.php [NC,L]
RewriteRule ^profile$ profile.php?player=$1
So what am I doing wrong that it isn't working?
Put the following in .htaccess file inside website's root directory:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET\ /ucp/profile\.php?([^=]+)=(\S+) [NC]
RewriteRule ^ucp/profile\.php$ /ucp/%1/%2? [R=301,L,NC]
# Now, deal with internal rewrites (which will not cause redirection):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ucp/([^/]+)/([^/]+)/?$ /ucp/profile.php?$1=$2 [NC,L]
You can use internal redirects what will not change your url but map your request as your wanted.
What you want is impossible because:
Htaccess and rewrite is at server side. The request arrived to the server, need to rewrite at serverside and you need to change it in the clients url bar.
To achieve this the server should send a redirect with the url what you expected. This ia why redirect is mandatory. Server can't rewrite clients urls, just can send a redirect response.
Internal redirect can simulate you something like the request was what you expected but it is transparent at for the clients.
Btw, permanent redirect is the right solution here to notify the user and give the chance to let them know the resource has been changed and update the bookmark / api / whatever.

Force the mod_rewrite to pass request parameters when rewriting

I am trying to make the web server to redirect all users from http to https. This is the code I am using:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HTTPS} !=on
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=301,L]
However, I've realized that when users send a request with information to http initially, after that this rewrite rule has executed, the POST data seems to be lost.
Is there any way to, when rewriting to HTTPS, make sure that all POST data is sent as well.
There are two HTTP status codes 307 (temporary) and 308 (permanent), which you might use for such a case. These status codes do the same as 302 and 301 redirect codes, but keep the method (GET/POST) intact
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=308,L]
Although, you should test with 307 until everything works as expected. See this answer Tips for debugging .htaccess rewrite rules for details.