Redirecting all Requests on a Domain to a Specific URL - apache

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>

Related

.htaccess 301 redirect with exclusion does not work

I try to use a simple 301 redirect
from domain1.com/folder/ to domain2.com/
but excluding domain1.com/folder/subfolder
I use the following code in .htaccess:
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1
but it simply redirects all the requests, including the requests to subfolder.
Please, help to fix the line to make it work as described. Thank you!
here is the complete code of .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1
Try it like this using mod_rewrite instead:
(NB: This assumes the .htaccess file is located in the document root.)
# /.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule ^folder/(.*) https://domain2.com/$1 [R=301,L]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
It is important that the redirect goes before the rewrite to your front-controller.
You will need to ensure your browser cache is cleared before testing and test with a 302 (temporary) redirect to avoid potential caching issues.
UPDATE:
Yes, /folder has it's own .htaccess (this is the file I am working at all this time). Yes, /folder is where Wordpress is installed.
In that case you would need to change the above redirect to read as follows (it won't do anything otherwise):
# /folder/.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule (.*) https://domain2.com/$1 [R=301,L]
Basically, you need to remove folder/ from the start of the regex that matches the URL-path. The URL-path that the RewriteRule pattern matches against is relative to the directory that contains the .htaccess file.
The addition of the check against the REDIRECT_STATUS env var is to ensure that rewritten requests to the WP front-controller (when subfolder is requested) are not redirected.
You can also "simplify" the WordPress directives that follow (although if these are enclosed in # BEGIN WordPress / # END WordPress comment markers then you should leave the directives as they are since they are maintained by WordPress). For example:
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
The RewriteBase directive is not required. And neither is the <IfModule> wrapper. (But as I said above, only change this if you are hand-coding the .htaccess and not letting WordPress maintain it.)

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)

Redirect subfolder to the main domain (root) using mod_rewrite (htaccess)

So I bought a script from the other guy (nothing fancy, let's say just a customized CMS) which is kinda complicated and uses frameworks that I don't know nothing about except names like "bootstrap", "laravel" and so. I am the guy who knows the basis and know some things from intermediate level but again, only some so when I see some fancy solutions I am getting confused.
Like here - I have never seen page built on files with strange extensions and two .htaccess files - one in root, and second in /public/ folder. Still, even though there are so many files, everything works really fine and fast.
Here is the issue's description:
So it seems that when browser loads the page (domain.com), it requests (I guess) content from /public/ folder and everything works fine and domain remains as domain.com. The thing is, that domain.com/public also works and I want to create redirection on this specific address just to prevent indexing this crappy-looking address of domain.com/public but bearing in mind, that domain.com should still work fine.
I have tried maaany solutions found here on SO and on other pages but they resulted in either crashing page (internal server error) or not doing anything at all. I think some of them might work but only when files are not embedded in another sub-folder. Eh I don't know, I am out of ideas. Can you please help me?
Here is the root's .httaccess
RewriteEngine On
RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]
RewriteRule ^((?!public/).*)$ public/$1 [L,NC]
And here is the public/.htaccess
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# 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]
</IfModule>
It looks to me like what you have should work, specifically the first condition + rule in the root .htaccess is meant to do what you're asking. I would polish it up a little:
In /.htaccess:
RewriteEngine On
RewriteBase /
# Fix URLs that begin with "public" subdirectory
RewriteCond %{THE_REQUEST} \s/public(?:/(\S*))?\s
RewriteRule ^ %1 [NS,NE,R=301,END]
# Internally rewrite everything else
RewriteRule ^(?!public/).* public/$0 [DPI,L]
In /public/.htaccess:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Pretend this is the root
RewriteBase /
# Redirect trailing slashes if not a folder
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [DPI,R=301,END]
# Handle front controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?!index\.php$). index.php [DPI,END]
</IfModule>
You can use L instead of END if your version of Apache is old, you'll know because of a 500 error.

.htaccess RewriteCond not working / being ignored

I'm trying to set the .htaccess file in my cpanel shared hosting so that all URLs which don't exist get redirected as 301 redirects to the homepage (doing this for a specific reason).
This code works for the redirect, but the RewriteCond statements are ignored so every single URL is redirected to the homepage, even existing ones (not good).
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule . / [L,R=301]
</IfModule>
#END wordpress
I've tried it without the %{DOCUMENT_ROOT} too with no luck and a few other things.
Does anyone know why the RewriteCond isn't working?

override apache rewrite rules with htaccess

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]