Showing posts with label redirect. Show all posts
Showing posts with label redirect. Show all posts

Friday, February 27, 2009

Subdomain Redirection Using htaccess And mod_rewrite On Apache For Linux Or Unix

Hey there,

Following up on yesterdays post on 301 redirects, which we realize is a tired subject, today we're going to take look at simple ways you can do regular/subdomain redirection using htaccess and "mod_rewrite" for Apache on Linux or Unix. And, while yesterday's subject matter (and perhaps even today's) may be somewhat generic, we're trying to even the balance here. Now that we're in the 500's on post count, we feel it would be a shame if somebody came here to learn something really cool and then couldn't find some other really basic information. As written previously, if this blog's subject matter were more limited this would be much easier to do. On the bright side, we'll probably never run out of things to write about :)

You can reference the basics of mod_rewrite syntax and rules on the link provided that points back to apache.org. While this page (or pages it links to within the same site), obviously, covers all the aspects of using Apache's "mod_rewrite," the style may not be suited to everyone. It's great information, but assumes some level of comfort that you may or may not already have regarding the subject matter.

In our few examples today (which won't cover much but should be explained with a good amount of detail), we're going to use a file named ".htaccess" (the dot at the beginning of the name is important!) placed in our web server's root folder (or base folder, etc) which contains the "mod_rewrite" rules. Our first example will implement the equivalent of a 3xx redirect using "mod_rewrite" instead of the more conventional methods. In order to implement this, just place the following content in your .htaccess file (assuming, again, that we want visitors to www.myxyz.com to be redirected to www.myotherxyz.com):

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
Redirect 301 / http://www.myotherxyz.com


Looks familiar, yeah? We actually covered that yesterday, as it's one of the most basic rewrites you can do. We just added the "standard recommended" starting lines for your .htaccess file. Those top three lines aren't "always" necessary, which is why we didn't include them in yesterday's example.

Here's another example that shows you how to use "mod_rewrite"'s regular expression functionality to redirect from an htm(l) page on one web server to a page on another web server:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^(.+)\.htm$ http://www.myotherxyz.com/$1.html [R,NC]


This example doesn't do all that much more than the previous, but it "is" a lot more flexible. We'll walk through the RewriteRule, to see what it's doing (and, remember, all of the nitty-gritty can be found on Apache's mod_rewrite page). The line itself, if you're familiar with basic regular-expression syntax, isn't too hard to decipher. The characters that are special in the line are the following:

^ <-- The caret indicates that the match is anchoring to the start of the request.
. <-- The dot character is representative of "any" alphanumeric character (including spaces, tabs, goofy characters, etc). It matches "anything"
\ <-- The backslash character "escapes" special match characters. In this case, we're using it to represent a "real" dot, rather than the regular-expression dot described above.
+ <-- The plus symbol indicates that the character preceding it must exist one or more times if the match is to be considered a success
$ <-- The dollar sign is the opposite of the caret. It indicates that the match is anchored at the end of the request
() <-- Anything within parentheses (on the left-hand-side, or LHS, of the expression) is considered to be a "captured" part of the match. It can be referenced on the right hand side (or RHS) of the rewrite rule using the dollar sign. This sign, as shown above, means something completely different on the RHS of the equation.
$1, $2, $3, etc <-- the dollar-sign-plus-number on the RHS of the expression represents the content of an LHS match (within the parentheses, as written above). The first parentheses match on the LHS is represented by $1, the second by $2, etc.
[] <-- Within the match rule itself, the brackets indicate a range, or "class" (a term that doesn't seem correct, but is used in the mod_rewrite terminology) of characters. For instance [abcd] would match the letter a, b, c or d. At the end of the mod_rewrite rule (as its final component) the characters within it hold special significance and "do not" represent a range. You can use more than one and just separate them with commas. In the example above they say that:
R <-- We're doing a "R"edirect. You can add an equals sign and the proper number if you want to be specific. So, a 301 redirect would look like [R=301] and make our expression's end look like [R=301,NC]
NC <-- Even though N and C both have special meanings of their own (in the final part of the rewrite rule), when used together as a single entity they mean that the matching-rule should be "case insensitive" NC equal "No Case" if that helps ;)

And that's that one line. Explained with only 10 or 12 more ;) Basically, it matches any web server request (for an html page - a bit more than our other rule was looking for) and redirects it, like so:

ORIGINAL REQUEST: http://www.myxyz.com/iNdex.html (Sent to the web server as "/iNdex.html)
MATCHING RULES APPLIED: ^(/iNdex).html ==> http://myotherxyz.com//index.html

The double slashes are squashed into one by default, but you could remove them from the LHS of the match rule and make that "" "^(.+)\.htm$" into "^/(.+)\.htm$" - effectively removing the leading forward slash from the () parentheses match and its extrapolated value ($1) on the RHS.

The standard final argument indicators are listed on Apache's mod_rewrite page and below:

[R] Redirect. You can add an =301 or =302, etc, to change the type.
[F] Forces the url to be forbidden. 403 header
[G] Forces the url to be gone. 401 header
[L] Last rule. (You should use this on all your rules that don't link together)
[N] Next round. Rerun the rules again from the start
[C] Chains a rewrite rule together with the next rule.
[T] use T=MIME-type to force the file to be a mime type
[NS] Use if no sub request is requested
[NC] Makes the rule case insensitive
[QSA] Query String Append. Use to add to an existing query string
[NE] Turns off the normal escapes that are the default in the rewrite rule
[PT] Pass through to the handler (together with mod alias)
[S] Skip the next rule. S=2 skips the next 2 rules, etc
[E] E=var sets an enviroment variable that can be called by other rules


In our final example, if you want to redirect all sub-domains of a domain to another site (e.g. redirect home.myxyz.com to www.myxyz.com), you could do it like this:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule %{HTTP_HOST} ^([^.]+)\.myxyz\.com$ http://www.myotherxyz.com [NC,L]


The %{HTTP_HOST} variable is translated from the variable provided by the standard HTTP headers. The L in the final argument means that, if this match is made, it will be considered the last match and no more rules in your .htaccess file will be processed. In our small example this doesn't really make a difference, but it can help with flow control if you have multiple rules and want to quit matching if you match this condition.

Hopefully today's quick run-down has been helpful. Let us know - too much information, not enough, not-enough-of-some-but-too-much-of-another? We're always interested in hearing your thoughts :)

Cheers,

, Mike




Discover the Free Ebook that shows you how to make 100% commissions on ClickBank!



Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.

Thursday, February 26, 2009

Simple Site Redirection On Apache For Linux Or Unix

Hey there,

Today we're going to look at simple ways you can do site redirection using a few basic methods for Apache on Linux or Unix. I'd presume that the functionality works exactly the same for Apache on Windows, but that would (to misquote a cliche) make a "pres" out of "u" and "me" - yeah, the "assume" version of that plays much nicer ;) Tomorrow, we're going to follow up with more advanced ways to do site and subdomain redirects using "mod rewrite".

Site redirection, in and of itself, is fairly easy to do with just straight-up HTML or PHP, but it has its limitations. For instance, if you wanted everyone who visited www.myxyz.com to be redirected to www.myotherxyz.com, all you'd have to do would be to add some simple code to your index.htm(l) or index.php file. In HTML, you could just add this line in the <head> section:

<meta http-equiv="refresh" content="30;url=http://myotherxyz.com/">

This would allow for thirty seconds to pass before the redirect was called. You might want to make that shorter or longer, depending upon how much interactivity you wanted your visitor to have before being redirected. You may want to allow them to use the old site if they want and redirect them if they don't click on a link in 30 seconds, or something like that. If you really want them to not have any choice, try setting the time (content) to 0. Although this, technically, redirects immediately, depending on someone's connection, the server hosting the website, etc, slow page load could cause the user to see the original page before it refreshes to the new site. If you're only using a page for this purpose, you should leave the body blank or with just a similar background image as your new site.

PHP is a bit faster, although still subject to the limitations of the interacting components that affect the HTML redirect (although not to the same degree). In PHP, you could do the same thing with this little chunk of code:

<?
Header( "HTTP/1.1 301 Moved Permanently" );
Header( "Location: http://www.myotherxyz.com/" );
?>


The most efficient method (of the three we're going run through here today) is to use htaccess. This point will be expanded upon to a good degree in tomorrow's post, since the combination of htaccess and "mod rewrite" can allow you to do a lot more than just standard redirection. Using htaccess, you could create a file called, strangely enough, .htaccess in your site's main directory (or root or home directory, or base directory or whatever you prefer to call it) that contained the same directions as above, although with yet another syntax. A simple 301 site redirect in .htaccess can be written this simply (the entire file from top to bottom):

redirect 301 / http://www.myotherxyz.com/

It just doesn't get any simpler than that :) For the htaccess method, since there are no double quotes surrounding your arguments (old-site-name new-site-name) you need to double quote any addresses that include spaces. Simple enough:

redirect 301 "/my old index.html" http://myotherxyz.com/

And that's all there is to it! For a little bit of trivia, you may have noted that we ended all of our redirect destinations with a closing / ( www.myotherxyz.com/ as opposed to www.myotherxyz.com ). The reason we do this is actually still standard protocol. You can actually do the test yourself right now to prove it out. When you send a standard web server a URI request for, say, http://www.google.com (for instance), that actually generates a 301 site redirect and plops you at http://www.google.com/, which is the properly formatted address. It happens very quickly and, of course, only counts when you're requesting a directory. If you specify a file, like http://www.google.com/index.html, you'll either get the page you were expecting or some other error (perhaps even a 301), although it should be noted that some web servers don't do this anymore in all instances (http://www.google.com/news, for example). Still, being a dinosaur, I prefer to stick to the way that should always work.

Give it a shot. It might be more fun than pick-up-sticks ;) If you find a site that does it, you can see the redirect in action using simple Telnet. Take this example using http://abc.go.com/daytime (Although this page actually does a 302 redirect - for temporary redirection - right now and takes you to a specific index page) - I grew tired of trying to find sites that use 301 redirection on sub-directories and you can't telnet to any server and not request a page, unless you want that 404 ("GET /" works, but proving the redirect by doing "GET " doesn't ;)

$ telnet abc.go.com 80
Trying 198.105.194.116...
Connected to abc.go.com.
Escape character is '^]'.
GET /daytime HTTP/1.0

HTTP/1.1 302 Found
Connection: close
Date: Thu, 26 Feb 2009 00:19:27 GMT
Location: /daytime/index?pn=index
Server: Microsoft-IIS/6.0
P3P: CP="CAO DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAi IVDi CONi
OUR SAMo OTRo BUS PHY ONL UNI PUR COM NAV INT DEM CNT STA PRE"
From: abc07
Set-Cookie: SWID=54AE3DC5-FB42-4F6C-8B10-82E506FFD442; path=/;
expires=Thu, 26-Feb-2029 00:19:27 GMT; domain=.go.com;
Content-Length: 163
X-UA-Compatible: IE=EmulateIE7

<HTML><HEAD><TITLE>Moved Temporarily</TITLE></HEAD><BODY>This document
has moved to <A HREF="/daytime/index?pn=index
">/daytime/index?pn=index
</A>.<BODY></HTML>Connection closed by foreign host.


See you tomorrow for some more-convoluted stuff.

Cheers,

, Mike




Discover the Free Ebook that shows you how to make 100% commissions on ClickBank!



Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.

Wednesday, July 23, 2008

Simple Multiple-Stream Output Redirection With Zsh On Linux and Unix

Hey there,

Following up on yesterday's post regarding using zsh's extended globbing functionality, today we're going to look at another feature supported by zsh, that can't be done nearly as easily in most other shells. Today we're going to look at some unique ways you can manipulate input and output redirection, even with multiple streams, while avoided a lot of extra code, and maybe a temp file or three :) This stuff is actually quite cool and I still count myself among the surprised that these things don't work in bash or ksh. The end objectives can be accomplished by all of the shells, of course, but we're looking for the most direct approach.

Again, these test were done on bash, ksh and zsh on Solaris Unix and RedHat Linux, so your results may vary. They probably won't though, because I couldn't find any version of bash or ksh that can do most of this stuff (see bullet point 4, later... :) So, without any further fanfare, let's get on with the zsh input/output redirection enhancements!

1. Redirecting output to two or more files on the command line: Generally, in bash and ksh (heretofore assumed to be the "other" shells), you can redirect output to multiple files using a variety of different methods. However, if you limit yourself to the standard output redirect operator, the following would not work (the output being limited to the last redirection to STDIN, since they just overwrite each other in succession):

bashksh # echo hi >file1 >file2
bashksh # cat file1
bashksh # cat file2
hi


although it will work in zsh, and for more than just two files (pick a number... I'm not sure how high you can go with this):

zsh # echo hi >file1 >file2 >file3
zsh # cat file1
hi
zsh # cat file2
hi
zsh # cat file3
hi


2. Redirecting output from two or more files on the command line: The same rules that applied to example 1, work the same way in reverse (with the each instance of redirection from STDOUT overwriting the previous). For instance, you'll get this output from bash and ksh:

bashksh # cat <file1 <file2
this is the content in file2


while in zsh, you get this:

zsh # cat <file1 <file2 <file3
this is the content in file1
this is the content in file2
this is the content in file3


3. Using a pipe to "cat," instead of the "tee" command, if you want to pump output to the screen while running an operation on a file. In other shells, you would normally use "tee" to capture output and watch as a process ran through it's paces. That would work great, but trying to do it with a pipe and "cat" would fail:

bashksh # pwd |tee filename
/home/techserv/mg131
bashksh # cat filename
/home/techserv/mg131
bashksh # pwd >filename|cat
bashksh # cat filename
/home/techserv/mg131


Note that, above, the "cat" command doesn't spit any output to the screen during the process' run; only to the file. In zsh, you can use the pipe to "cat" (shown above) as a substitute for "tee":

zsh # pwd >filename|cat
/home/techserv/mg131
zsh # cat filename
/home/techserv/mg131


4. And, lastly, we'll take a look at the redirection of command output (within parentheses) and go straight to the complicated stuff. This is actually listed as a feature of zsh (and, technically, it is), but my tests with ksh and bash have produced equal results, so it doesn't fit my definition of a "feature" of zsh (that being something unique to zsh, and not directly reproducible in other shells). For instance, this line returns the exact same output in all three shells:

bashkshzsh # sort <(grep -v "^#" <(paste -d: <(cut -d: -f1 /etc/passwd) <(cut -d: -f3 /etc/passwd) ) ) |egrep ':0|:1|:2|:3'
bin:2
daemon:1
listen:37
root:0
sys:3


While this is definitely cool stuff (And the redirection of lists generated by commands within parentheses can be used as multiple streams of input and output for all three shells, as well), my conclusion, to date, is that most advanced shells have this functionality built in. If you "must" see it fail, you can always rely on straight-up vanilla Bourne shell:

sh # sort <(grep -v "^#" <(paste -d: <(cut -d: -f1 /etc/passwd) <(cut -d: -f3 /etc/passwd) ) ) |egrep ':0|:1|:2|:3'
syntax error: `(' unexpected
sh # bin:2
bin:2: not found
sh # daemon:1
daemon:1: not found
sh # listen:37
listen:37: not found
sh # root:0
root:0: not found
sh # sys:3
sys:3: not found


Now, if bash and ksh had come back with that, I would have no reservations about labeling this type of multiple-stream output redirection and massaging a feature of zsh.

Yes, the ending to this post "was" anti-climactic, but at least you can be reasonably sure I'm remaining objective ;)

Cheers,

, Mike

Friday, July 4, 2008

Basic I/O Redirection Differences In Sh/Ksh, Bash and Zsh On Linux And Unix

Hey there,

Today we're going to look at four different shells (all tests were run on a Solaris 8 box and an old RedHat Linux 9 server) and some very basic I/O redirection (which can come in handy if you're ever stuck trying to read and write files in a blind shell), to show you how differently, and commonly, they all handle the same information. The only reason I find this sort of stuff remarkable is that it's so common, sometimes its hard to wrap my head around the fact that any distinctions exists (Okay, they're not HUGE, but the differences, where there are any, are enough to make you wonder ;) For instance, in our two experiments, we're only going to find one difference each. But, since the material we're working with is so basic (not meaning "simple"), it's a bit disconcerting (...oh, the drama ;)

First of all, we'll narrow down our list of shells and consider sh and ksh to be the same, since all of my testing, with regards to these two shells, yielded exactly the same results. Note that, for all of our tests, we only tried to create two conditions in a variety of ways; the first was to create an empty file, and the second was to redirect standard error (STDERR) to a file. See what I mean? This is very familiar ground for almost all Unix or Linux admins.

Now let's take a look at a how sh/ksh, bash and zsh are the same, when it comes to basic I/O redirection.

First test: Create an empty file. The following methods worked in all 4 shells (producing the expected output from the file and "wc -l" commands of "empty file" and 0, respectively):

host # : > FILE

This creates an empty file by using the colon (:) placeholder (which, technically, is a simple notation for "true") as output to be redirected into the blank FILE

host # /bin/true >FILE

Pretty much the same as the previous example, except we're running /bin/true explicitly.

host # /bin/false >FILE

Again, the same as the previous example, except we're using /bin/false for a goof. It's another program that doesn't produce output and is mainly used to generate a desired return status.

host # cat /dev/null >FILE

Just catting nothing to the FILE, and it ends up empty, as expected.

host # <>FILE

and this works as well (specifying empty redirection of STDIN and STDOUT) on all 4 shells.

host # echo <> FILE

While this, finally, spit a line of output to the screen, it still produced an empty file in all 4 shells, even with extra commands to echo, since they all spill out to the screen instead of going into the file. Kind of a waste of resources, but interesting somewhat ;)

host # echo how are ya <> FILE
how are ya


Now's here's the only basic thing I could find where they differed, in this respect:

host # >FILE

This produces an empty file on Solaris sh, ksh and bash (generally, it's shorthand for "cat /dev/null >FILE"), but results in a perpetual hang with zsh (zsh will not infer /dev/null (or true) from a lack of argument preceding the > redirection symbol).

Second test: Redirecting STDERR to a file. The similarities.

host # truss echo hi >FILE

This produces a non-empty file (with the word "hi" in it) in all 4 shells, since truss sends its output to STDERR and we're only redirecting STDOUT. This doesn't really prove any part of the experiment, but I wanted to put it out as a baseline, so we know that the truss output is going where we expect it to before we start goofing around :)

host # truss echo hi >FILE 2>&1

This, tying STDOUT and STDERR together to put all output into the file, works on all 4 shells as well :)

But, the following command only "really" works as expected in bash, and produces remarkably different results for the other shells:

host # truss echo hi &>FILE

In bash, the &> notation is shorthand for ">FILE 2>&1" - but this doesn't work for our other shells. In Solaris sh and ksh, the command spits output to the screen, since the & activates the shells' backgrounding feature, the job completes and the output file is completely empty. On zsh, "hi" gets spit to the output terminal and only STDERR goes into the output file (???)

Remember, these have just been really basic examples. Thinking about this sort of stuff makes you realize how truly "different" different shells are. Of course, among these very basic examples, we could only find two major
differences, but that's still a good number considering how rudimentary the shell functions are. In other words, these are I/O redirection issues which you can't change, except by script-wrapping (which probably isn't worth it, since, for each difference we found at least 2 similarities between the 4 shells and both experiments only tested one property).

If you're not sleeping yet, I'll assume this article was, at least somewhat, entertaining and/or helpful ;)

Have a Happy 4th of July!

, Mike