override apache rewrite rules with htaccess - apache

working on a server that hosts multiple domains.
Somewhere in apache config is a rewrite rule that is set for ALL domains.
What happens is if a user goes to example.com/foo they are supposed to get redirected to example.com/foo_bar
However, in one domain, I want to override this behavior so that the url stays at example.com/foo and does not redirect. I've been searching and trying various rules and conditions to no avail. I don't have access to the apache config, but I am using .htaccess for some rewrite rules on this domain.
here's my rewrite rules in .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
# this isn't working
# RewriteRule ^(foo)($|/) - [L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1
# this didn't work either
# RewriteRule ^/foo index.php?/$1 [L]
</IfModule>

Try redirecting /foo_bar back to /foo.
When Apache processes the rewrite rules it runs through them multiple times, which you can see when you turn on debugging. I think what's happening in your case is that you're trying to match the URI in the first pass, but Apache has already modified it to /foo_bar.
Also, as a matter of debugging, you should try to recreate the problem in an environment you control. Ask your sysadmin for a copy of the global configuration and mirror the set up you're constrained to.

You can create exception for one domain:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} !^(?:www\.)?domain\.com$ [NC]
RewriteRule ^foo(/.*)?$ /foo_bar$1 [L,R=302]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

Related

Combine mod_rewrite rules

In my .htaccess I've got the usual rewrite rules but I need to add a HTTP to HTTPS rule. If I put the new rule after the existing rules it does not work but putting it before works but then I suspect the vanilla WordPress code does not work.
I've put the rules together by adding the last two lines of the second rule to the end of the first one but that does not work either. I'm not sure what I'm doing!
What is the best way to combine these two?
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://127.0.0.1/$1 [R,L]
</IfModule>
The ruleset that's responsible for ensuring https is doing an external redirect, while the other one (wordpress) is doing internal rewrites.
It's often a good practice to first put the external redirects (if they don't depend on any previous internal rewrite).
Note the L flag:
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.
If you put wordpress rewrite rules before the https ruleset, the rewrite engine will never get to the second ruleset. That's because of the L flag that instructs the rewrite engine to stop processing of any other rules. This reason aside, you don't want to rewrite the request to wordpress' index.php and then ensure that it's https using an external redirect (R flag), right?
So, you might want to try this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# HTTPS:
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://127.0.0.1/$1 [R,L]
# WordPress:
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Few final notes:
You only need one RewriteEngine on and one IfModule.
It's better to use a 301 redirect for https and www redirects. (R=301)

mod_rewrite - redirect a page to index

I'm looking prevent people from accessing login URLs on certain servers.
Ideally I want a solution without having to reference the domain (there are many domains, and many server environments), and I'd like to put the rule within the global httpd.conf, rather than individual vhosts.
I've tried all kinds of mod_rewrite, to no avail, or terrible performance, eg;
RewriteRule ^/login$ /index.php [R,L]
RewriteRule ^login/?$ $1/$2 [R=301,L]
One caveat is that it needs to work with my URL rewrites;
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>
..and in short, I want these;
http://mysite.co.uk/login
http://mysite.co.uk/index.php/login
to go here;
http://mysite.co.uk/
The below should redirect the examples you provided to your site root:
RewriteEngine On
RewriteRule ^/(index.php/)?login/?$ / [R,L]
As long as you place them before your existing rules, they should do what you want.

Redirecting all Requests on a Domain to a Specific URL

It's been a long time since I've used Apache (a very long time) and even then I didn't really do much URL rewriting or anything like that, just simple hosting. But now I'm trying to piece together a simple redirect for a small business that's re-branded to a new domain.
The way it's set up is that the host for the old domain has a web control panel based redirect to a specific URL, which is a "looking for the old us?" page on the new domain. All requests are redirected, but they carry with them the entire request path which results in a 404 on the new site.
I've been looking through some Apache documentation and some examples I can find online, but I'm not quite there yet. Where I've left off so far is with something like this:
RewriteCond %{REQUEST_URI} .*looking-for-blah.* [NC]
RewriteRule ^ http://newsite.com/looking-for-blah [L,R=301]
The idea is that any request coming in for any path which contains looking-for-blah, regardless of what's before or after it, should go to the explicit http://newsite.com/looking-for-blah. So when the old host redirects somebody to:
http://newsite.com/looking-for-blah/foo/baz
They get redirected by the new site to:
http://newsite.com/looking-for-blah
However, it doesn't seem to be catching the incoming requests and redirecting them. Am I missing some fundamental concept in the RewriteCond? Maybe there's a better way to do this that I haven't even considered?
Edit: Here's the current state of the .htaccess as a whole:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
# BEGIN custom redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule looking-for-icamp http://empow.me/looking-for-icamp [L,R=301]
</IfModule>
# END icamp redirect
But doing a simple wget on http://empow.me/looking-for-icamp/foo results in a 404 instead of the desired 301.
The Wordpress default catch-all routing is matching your rule before it can be reached, so your rule will need to be placed above any Wordpress rewrites. I also added a RewriteCond to be more explicit about the circular rewrite avoidance than your .+ trick, which seems a little hacky to me and would be hard to understand on later readings.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# BEGIN custom redirect
# This must take place before the Wordpress redirect to index.php
# Added condition to avoid circular rewrite
RewriteCond %{REQUEST_URI} !^/looking-for-icamp$
RewriteRule looking-for-icamp http://empow.me/looking-for-icamp [L,R=301]
# END icamp redirect
# Note - you had two identical WP blocks. I've removed one.
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# This rule was the one blocking your custom rule earlier....
RewriteRule . /index.php [L]
# END WordPress
</IfModule>

.htaccess rewrite to simultaneously change domain and remove path

My URL structure is currently as follows:
http://domain.com/folder/filename (CURRENT)
I want to change this so that I can use the following URL instead:
http://sub.domain.com/filename (NEW)
So accessing the CURRENT or the NEW url, should load the file located at the CURRENT url, but show the NEW url in the address bar. It should only apply to the "/folder/" path.
sub.domain.com is a mirror of domain.com, ie. they share the same file system and root directory.
This is what I have so far:
Options +FollowSymLinks
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www.)?domain.com$ [NC]
RewriteCond %{REQUEST_URI} ^/folder/?(.*)$ [NC]
RewriteRule ^(.*)$ http://sub.domain.com/$1 [R=301,L]
This is working, but is missing the rule to remove the "/folder/" from the path. I've tried combining multiple RewriteRule's with no luck. Any ideas? Thanks.
UPDATE: Thanks again #Gerben - I understand what your rules are doing now, but the second one isn't working for me. I suspect because it's conflicting with some other rewrite rules, in particular those of WordPress, which are lower down in my .htaccess file:
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Because of this the page ends up in a redirect loop, ie (from Chrome):
"The webpage at http://sub.domain.com/folder/index.php has resulted in too many redirects." - while the url I was originally trying to access was, for example, http://sub.domain.com/page
Any ideas?
Try:
RewriteCond %{HTTP_HOST} ^(www.)?domain.com$ [NC]
RewriteRule ^(folder/)?(.*)$ http://sub.domain.com/$2 [R=301,L]
This will redirect everything to sub.domain.com, and remove the /folder part of the URI if it is there. If not, it redirects and leaves the URI untouched.
RewriteCond %{THE_REQUEST} /folder/
RewriteRule ^folder/(.*)$ http://sub.domain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^sub\.domain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule ^(.*)$ folder/$1 [L]
# WordPress rules here
edit the second R=301 should not have been there
But this won't work, as wordpress has no way of knowing you want folder. You could add the Proxy flag to the rewrite, but then you need to change the rule above to not redirect on this internal proxy request.

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'] = "";