I want a 301 redirect that doesn't include certain pages.
February 15, 2010 2:57 PM   Subscribe

How do I set up a 301 redirect for all pages except one?

The situation is as follows:

My friend had the original site, which we'll call example.com. It is a mess of html files coded with a WYSIWYG editor. There are various root-level pages, and also subdirectories.

I set up a new Wordpress installation for him at example.com/blog, thinking that he would become fond of it and eventually want to get rid of the old site. I was right, and that has come to pass.

I set up a 301 redirect with an .htaccess file using info that I found googling for basic 301 info. (I don't have the actual code I was using anymore, sorry.) It worked, and any request for any file of directory under example.com that was not part /blog redirected to example.com/blog. That is what we thought we wanted.

Here's the twist. My friend contacted me about a special page on the old site, example.com/samples.htm. This particular page was actually had a lot of inbound links, and users who come looking for it are disappointed when they end up at example.com/blog.

That being said, we want to keep the bulk of the redirect in place. The old site needs to be hidden by the redirect, except for this specific case. And, of course, it's possible that he will come up some some other specific cases as time passes.

Thoughts?

p.s. I did see this thread, and suspect that the answer is in there somewhere, but I don't understand how to apply it to my situation.
posted by bingo to Computers & Internet (19 answers total)
 
You'll want something like this, I think:

RewriteEngine On
RewriteCond %{REQUEST_URI} ! ^/blog(.*)$
RewriteCond %{REQUEST_URI} ! ^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

Basically, if the user isn't requesting those specific pages, send their request to the /blog directory. I haven't tested that, so you may need to tweak it to get it to work.
posted by lholladay at 3:09 PM on February 15, 2010


Well, I set that up, and it resulted in a 500 error for any request. I'm not sure how to tweak around that.
posted by bingo at 3:22 PM on February 15, 2010


500 error - your first stop is your apache error logs to see what the details are.

500 error after messing with .htaccess is usually due to a syntax error in the .htaccess file.

Otherwise, looking at the example lholliday's example (guessing here)

You might need an [OR] on the end of hte first RewriteCond -otherwise they are ANDed together.

That said - 500 error is usually due to a sytax error... perhaps the space between the ! and the ^ is incorrect?
posted by TravellingDen at 5:10 PM on February 15, 2010


For what it's worth, those two rules should be ANDed together. If the URI doesn't match /blogsomething, AND it doesn't match /samples.htp, THEN you want it to redirect.
posted by flabdablet at 5:34 PM on February 15, 2010


The htaccess file that caused the error contains nothing but the text suggested by iholladay above.
posted by bingo at 6:27 PM on February 15, 2010


I took out the spaces as suggested by TravellingDen, and it seems to be working correctly now. Thanks, everyone!
posted by bingo at 6:53 PM on February 15, 2010


Okay, not sure if anyone is still reading this, but I have a related problem.

I actually need to add another directory as an exception. This is the /production/music/ directory. Any request that falls under that category should not be redirected. I am having trouble figuring out how to add it properly.
posted by bingo at 3:29 PM on February 24, 2010


I'm not a web guy, but I'm going to assume that what you have at present is

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog(.*)$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

and that it works. Let's look at what it's doing.

The first RewriteCond says that the rewrite rule should apply only to requests whose URI does not (!) match, starting from its beginning (^), the exact pattern /blog followed by a group (()) consisting of any number (*) of any character (.), followed by the end of the URI ($).

Using that pattern, you should be able to avoid rewriting requests for /production/music/anything by inserting a second RewriteCond as follows:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog(.*)$
RewriteCond %{REQUEST_URI} !^/production/music/(.*)$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

Because I'm not a web guy, there are probably conventions and best practices for writing these things that I don't know about but I can't see a good reason for the grouping parentheses in either of the above conditions. I'd expect that

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog.*$
RewriteCond %{REQUEST_URI} !^/production/music/.*$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

would do exactly the same thing. Furthermore, since what's being matched at the end of each URI is "any number of anything", I'd expect that simply leaving out that part of the matching expression should work equally well:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog
RewriteCond %{REQUEST_URI} !^/production/music/
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

posted by flabdablet at 4:12 PM on February 24, 2010


Those conditions, by the way, will prevent rewrites for any link to a file or subdirectory inside /production/music/ but not for /production/music itself, because the /production/music/ condition includes a trailing slash.

The /blog condition doesn't, so requests for /blog and /blog/ and /blog/anything will all bypass rewriting. This is a little cheap and nasty, in my non-web-guy opinion, because requests for e.g. /bloggage will also sneak past the rewrite rule.

This is probably better:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog($|/)
RewriteCond %{REQUEST_URI} !^/production/music($|/)
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

The | operator specifies alternation: foo|bar|baz matches foo, or bar, or baz. The parentheses limit the extent of the alternative patterns: /blog(foo|bar|baz) matches /blogfoo or /blogbar or /blogbaz. The dollar sign means match-at-end, so /blog($|/) matches /blog or /blog/anything but doesn't match /bloggeration.
posted by flabdablet at 4:48 PM on February 24, 2010


Then I try any of these, requests for subdirectories of /blog redirect to just /blog. So for example, a request for /blog/performance redirects back to just /blog .
posted by bingo at 5:02 PM on February 24, 2010


You should probably wait for somebody who is a web guy to weigh in and untangle the mess I've made here, then. Sorry.
posted by flabdablet at 6:04 PM on February 24, 2010


In the meantime, you might care to try these:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog(/.*)?$
RewriteCond %{REQUEST_URI} !^/production/music(/.*)?$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

posted by flabdablet at 6:08 PM on February 24, 2010


Try this:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog(.*)$
RewriteCond %{REQUEST_URI} !^/production/music(.*)$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

Flabdablet, you may be right about some of your regex comments. I'm not great with regex. I just manage bunches of Apache servers and I know what I've found to work.
posted by lholladay at 6:51 PM on February 24, 2010


Actually, flabdablet's 7:48 answer is working. I was modifying the wrong .htaccess file. i was modifying the wordpress-generated one in the /blog directory, instead of the one in root.

*facepalm*

Thanks for spending the time on this, guys...
posted by bingo at 7:22 PM on February 24, 2010


Actually, I don't know if anyone is at all interested in this at this point, but for those who care to indulge me, the plot thickens.

We now need to redirect

/samples.htm
to
/blog/christian-howes-string-productions/samples/

So I tried to give it its own redirect rule at the end, but it doesn't seem to be effective. Open to your thoughts if you care to comment.

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog($|/)
RewriteCond %{REQUEST_URI} !^/production/music($|/)
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

RewriteRule ^/samples.htm http://www.example.com/blog/example-person-productions/samples/ [R=301]

The logic is:

1. Any request that starts with /blog should stay as is.
2. Any request that doesn't start with /blog should be rediredted to /blog
2a. except requests to the /production/music/directory which should stay as they are.
2b. except requests for /samples, which should be redirected to /blog/example-person-productions/samples/

Sorry that this keeps dragging on. I think that after this is solved, we will really have everything we need. Much gratitude to anyone willing to comment further.
posted by bingo at 12:25 AM on February 25, 2010


Curious. I have tested the ruleset below on one of my servers, and it works correctly:

RewriteCond %{REQUEST_URI} !^/blog(.*)$
RewriteCond %{REQUEST_URI} !^/production/music(.*)$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

RewriteRule ^/samples.htm http://www.example.com/blog/example-person-productions/samples/ [R=301]

Sometimes the order of the rules can mess you up, so you might try putting that final RewriteRule on the top, like this:

RewriteRule ^/samples.htm http://www.example.com/blog/example-person-productions/samples/ [R=301]

RewriteCond %{REQUEST_URI} !^/blog(.*)$
RewriteCond %{REQUEST_URI} !^/production/music(.*)$
RewriteCond %{REQUEST_URI} !^/samples.htm$
RewriteRule (.*) http://www.example.com/blog [R=301]

I tested both ways and they both worked. Let me know what behavior is happening if neither of these works for you.
posted by lholladay at 9:59 AM on February 25, 2010


Thanks, lholladay. I had to take the redirect down temporarily in order to allow some editors to access the old site, so I haven't had a chance to implement your suggestion yet. I will comment here as soon as I do.
posted by bingo at 8:37 PM on February 26, 2010


I'm finding that this:

RewriteEngine On
RewriteRule ^/samples.htm http://www.example.com/blog/example-person-productions/samples/ [R=301]

Does not work, even if there is nothing else in the file.

Maybe I'm doing something wrong, but I've been going over it pretty carefully.
posted by bingo at 7:11 PM on March 9, 2010


Okay. With the help of a friend, I got it to work.

The solution was to take lholladay's last suggestion, but to use ^samples.htm instead of ^/samples.

My friend commented: "I think the / is implicit so the rewrite rule doesn't include that as part of the match."

Thanks very much to everyone who helped. This has been quite the redirect adventure.
posted by bingo at 8:23 PM on March 9, 2010


« Older How to evaluate a financial firm?   |   What is the best way to view m2ts videos on my... Newer »
This thread is closed to new comments.