How can I stop a single URL POST being changed to a GET redirect in .htaccess - apache

I have about 40 c# desktop applications that are doing a POST off to http://www.example.com/submit-bug for user generated bug reports.
However I've recently switched my website (where the POST data is handled) over to HTTPS so everything is now 301'ed to HTTPS via htaccess.
This also means that my POST to http://www.example.com/submit-bug is being 301'ed to https://www.example.com/submit-bug which causes all the POST data to be lost as it goes from POST to a GET redirect.
How can I tell htaccess to ignore the redirect with a post to http://www.example.com/submit-bug and just continue to do the normal index.php routing that Laravel uses.
I've tried all sorts of combinations of the L and P flags but they are either ignored or cause a 500/404 error.
This is my current htaccess
RewriteEngine On
#RewriteCond %{REQUEST_URI} (.*)submit-bug(.*)
#RewriteRule ^ index.php [L]
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

You can remove any redirections or rewrite regarding a POST, by adding at the beginning, before RewriteCond %{HTTPS} off:
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^ - [L]

Related

URL rewrite with HTTPS / www not working for subpages

I have to following configuration in my .htaccess. The first rule puts https before the URL and the second puts www before the URL, if not set already.
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
These redirects work perfect for the homepage. However, if you call a subpage, these rules wont work.
domain.xy -> https://www.domain.xy (works, Homepage)
domain.xy/contact -> http://domain.xy/contact (doesnt work)
The weird thing is, the favicon get redirected correctly. Example with the contact page, as seen on
this picture.
How can it be, that my configuration only works for the toplevel, not for any subpage?
I'd say your RewriteRule is wrong. It should be .* instead of ^:
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The problem was another rule in the .htaccess-File. Our hosting provider automatically generates a .htaccess suiting the Typo3 installation. I had to place my rewrite rule before the following lines:
# If the file/symlink/directory does not exist => Redirect to index.php.
# For httpd.conf, you need to prefix each '%{REQUEST_FILENAME}' with '%{DOCUMENT_ROOT}'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]
This rules, as far as i understand, redirects any request, which is not a file, directory or symlink back to the index.php. So in my case if i call domain.xy/contact, it redirects back to the index.php.
Because this rule has the [L] flag at the end, the .htaccess stops processing here. So i moved both my rules above this block and they get called before this block comes to action.

How can I direct all pages except one to HTTPS in an htaccess?

Currently I am redirecting all pages to https using the following htaccess directive:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
But I have one page, http://foo.bar/baz which needs to be accessed http-only. Using an htaccess directive, how can I redirect to https on all pages except this one, where users are forced to http?
Edit: I should have mentioned that this is a Laravel 4 application, and I currently also have the following rules to handle the front-controller
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
You can use a negative regex pattern in RewriteRule:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !/baz[/?\s] [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} /baz[/?\s] [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
RewriteRule ^index\.php - [L,NC]
# Redirect Trailing Slashes...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301,NE]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
A negative lookahead works especifically for these cases when you want one or more exceptions:
RewriteRule ^(?!baz)(.*) https://%{HTTP_HOST}/$1 [R,L]
This basically says, redirect everything except baz.
SideNote: Remember ".htaccess" is not some sort of rewrites depot for Apache, if you have access to the config in the virtualhost, make sure to add these rewrites in there. htaccess adds overhead and complexity.

Cannot make htaccess redirect www to non-www

The 3 comments in the code explain fairly accurate what I want to achieve.
<IfModule mod_rewrite.c>
RewriteEngine On
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [L,R=301]
# Add trailing slash / if there's none
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
</IfModule>
However, I am finding some problems and I think they come from putting the conditions together. When I enter www.secretdiary.org/about , it gets (showing it in the browser) to secretdiary.org/index.php?url=about, deleting the www but ignoring the first rule. Switching the order did not help at all nor messing with RewriteBase. However, if I enter normally without the www, the uri is shown normally, secretdiary.org/about, without any rewriting. Why is this and how can I fix it?
Besides, I've followed this answer and this other attempting to add automatically a trailing slash to the uri if missing. I could achieved it with PHP ( if (substr($_GET['url'], -1) != "/") header("Location: " . htmlspecialchars($_GET['url']) . '/');, but now it bothers me that I cannot achieve it with .htaccess, so if you could also spot where's the problem here it'd be very helpful.
Try this .htaccess code :
RewriteEngine On
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{HTTP_HOST} ^secretdiary.org$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [L]
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [R=301]
# Add trailing slash / if there's none
RewriteRule ^([^/]*)[^/]$ $1/ [R=301,L]
I'm not sure for the last rule.
The main problem I faced was with Firefox storing the 301 redirect, which made the changes in .htaccess "not work". I deleted the cache and now it's working perfectly, although I made the trailing slash to be added with PHP to avoid headaches.
.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# For some shady reason, this redirect should be first.
# Redirect http://www.secretdiary.org/ to http://secretdiary.org/
RewriteCond %{HTTP_HOST} !^secretdiary.org$ [NC]
RewriteRule ^(.*)$ http://secretdiary.org/$1 [L,R=301]
# Change secretdiary.org/index.php?url=URL to secretdiary.org/URL on the browser's url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>
index.php:
<?php
// Redirect if there's no trailing slash
if (!empty($_GET['url']) && substr($_GET['url'], -1) != "/")
{
header ('HTTP/1.1 301 Moved Permanently');
header ("Location: http://secretdiary.org/" . htmlspecialchars($_GET['url']) . "/");
}
// The rest of the php

Redirect Loop When Enabling SSL on Matching URI Slug

I'm trying to accomplish 2 tasks with mod_rewrite:
If the URL, regardless of protocol, does not have the "www" subdomain, then add "www" to the URL.
If the URI begins with /secure.php AND the protocol is NOT https, then switch the protocol to https.
So I tried:
# Redirect to www subdomain
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# Force SSL for secure.php URIs
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure.php
RewriteRule ^(.*)$ https://www.mysite.com%{REQUEST_URI} [R=301,L]
But I get a redirect loop when accessing /secure.php URIs. I can't figure out what the problem is, this is how I see the sequence of events:
http://mysite.com/secure.php is requested
The host name does not contain "www", so it passes the first condition
The URL is updated to http://www.mysite.com/secure.php, and the process loops back to the top.
The host name does contain "www", so it fails the first condition and skips the rewrite.
HTTPS is off, so it matches the next condition, AND
The URI begins with "/secure.php", so it matches both required conditions
The URL is updated to https://www.mysite.com/secure.php, and the process loops back to the top.
The host name does contain "www", so it fails the first condition, and skips the rewrite.
HTTPS is not off, so it fails the next condition and skips the rewrite.
Have I got that right? What am I doing wrong here?
I also have one other rule in .htaccess for removing index.php from ExpressionEngine URLs:
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
So here's the entire .htaccess file:
RewriteEngine On
RewriteBase /
# Remove index.php from ExpressionEngine URIs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
# Redirect to www subdomain
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# Force SSL for /secure.php URIs
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure.php
RewriteRule ^(.*)$ https://www.mysite.com%{REQUEST_URI} [R=301,L]
The server variables like HTTP_HOST or REQUEST_URI are available in a RewriteCond, but not in a RewriteRule. If you need these variables you must capture them in a RewriteCond
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} (.+)
RewriteRule .* http://www.%1/$0 [R,L]
You don't need to check for secure.php in a RewriteCond, you can just specify it in the RewriteRule
RewriteCond %{HTTPS} off
RewriteRule ^/?(secure.php.*) https://www.mysite.com/$1 [R,L]
OT: Never test with 301 enabled, see this answer Tips for debugging .htaccess rewrite rules for details.

How do i force www subdomain on both https and http

For whatever reason I can't seem to get this right, I've looked at many examples on here and apache's website. I'm trying to force www.domain.com instead of domain.com on EITHER http or https but I am not trying to force https over http.
the following code seems to work for all https connections but http will not redirect to www.
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^ https://www.domain.com%{REQUEST_URI} [R=301]
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^ http://www.domain.com%{REQUEST_URI} [R=301]
You don't need the second RewriteEngine directive. That may or may not be causing a parse issue making the second set of rules not work. To test whether this is the case, try switching the order of the two blocks you have.
It's good practice to use L to modify requests that are definitely the last. So, change [R=301] to [R=301,L] both times it appears.
Largely as a matter of style, I would consider changing the RewriteRule directives to something like (using http or https as appropriate):
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L,QSA]
Your rules seem to be fine. You can combine them as follows:
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTPS}s on(s)|
RewriteRule ^ http%1://www.example.com%{REQUEST_URI} [L,R=301]
Also note the additional L flag to stop the rewriting process after this rule has been applied.
In case anyone still need an answer to this. Use another .htaccess. Get guide from here, I found it and it looks good: http://www.farinspace.com/codeigniter-htaccess-file/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
### Canonicalize codeigniter URLs
# If your default controller is something other than
# "welcome" you should probably change this
RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
RewriteRule ^(.*)/index/?$ $1 [L,R=301]
# Removes trailing slashes (prevents SEO duplicate content issues)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,R=301]
# Enforce www
# If you have subdomains, you can add them to
# the list using the "|" (OR) regex operator
RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
RewriteRule ^(.*)$ http://www.domain.tld/$1 [L,R=301]
# Enforce NO www
#RewriteCond %{HTTP_HOST} ^www [NC]
#RewriteRule ^(.*)$ http://domain.tld/$1 [L,R=301]
###
# Removes access to the system folder by users.
# Additionally this will allow you to create a System.php controller,
# previously this would not have been possible.
# 'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php/$1 [L]
# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# Without mod_rewrite, route 404's to the front controller
ErrorDocument 404 /index.php
</IfModule>
Remember, once you have your CodeIgniter htaccess file setup, you will want to go into your “/system/application/config/config.php”, find the following:
$config['index_page'] = "index.php";
and change it to:
$config['index_page'] = "";