Permanent Redirect with HTTP 301

cnttbachkhoa , 2010/12/16 23:10 , Programming , Comments (0) , Reads (3319) , Via Original Large | Medium | Small

This article describes how to properly redirect a  web page using an HTTP 301 status code and Location header.  The 301  status code is used to indicate that a page has permanently moved.  Multiple techniques are presented with recommendations.

  

In order to redirect an out-of-print web page to another location,  return the HTTP 301 status code and a location header in the HTTP  response of the deprecated web page.  The HTTP 301 response code will  tell user-agents that the location has permanently moved.  This is  particularly useful for search engines like Google, which will carry  over page rank to the new page if this status code is seen.   If you do  not need to indicate permanent displacement, you can accomplish  redirection by setting a Location header in PHP or using  Response.Redirect in ASP.  The location header does the actual redirection to the new location, and can be used by itself.

  

HTTP headers are sent for every web page.  If you want to see what HTTP headers look like for a particular page, visit Rex Swain's HTTP Viewer. For advanced users, I would recommend you download the Firefox web browser and install Chris Pederick's Web Developer Extensions.  Then, use the Information->View Response Headers  function.  In scripts, HTTP headers must be sent before sending any  page content, including white space, or else an error will result.  

HTTP 301 Redirect in ASP-VBScript

  
<%@ Language=VBScript %>
<%
' Permanent redirection
Response.Status = "301 Moved Permanently"
Response.AddHeader "Location", "http://www.somacon.com/"
Response.End
%>
  

In Active Server Pages (ASP), Response.Redirect does not work the same as the code shown in the example.  Response.Redirect will set the location header as shown, but it will set the status code to HTTP/1.1 302 Object moved instead.  When you set the Location header with Response.AddHeader, the status code must be manually defined, otherwise it stays 200 OK.  

If you send any page content prior to the headers, you will get an error like, "Response  object error 'ASP 0156 : 80004005'; Header Error; The HTTP headers are  already written to the client browser. Any HTTP header modifications  must be made before writing page content.".  Normally, you do not  see this error even if there is content prior to the redirect, because  page buffering is enabled by default in IIS.  If you want to be sure  there is no content being sent before the redirect, call Response.Flush just before it, disable page buffering with Response.Buffer = False, or configure IIS to disable page buffering. (Disabling buffering reduces performance.)  

HTTP 301 Redirect in PHP

  
<?php
// Permanent redirection
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.somacon.com/");
exit();
?>
  

If you set the Location header by itself, PHP automatically sets the status code to HTTP/1.1 302 Found.  

Note, if you attempt to send headers after content has been sent, you will get a warning like, "Warning: Cannot modify header information - headers already sent by ...".  Watch out for empty lines and spaces between PHP open and close tags.  ASP ignores these, but PHP does not.  

HTTP 301 Redirect in ColdFusion

  
<CFHEADER statuscode="301" statustext="Moved Permanently">
<CFHEADER name="Location" value="http://www.somacon.com/">
  

Do not use a CFFLUSH command before the above tags, or in Application.cfm. This Coldfusion code was provided by Toll Free Forwarding.com.  

HTTP 301 Redirect in Perl

  
#!/usr/bin/perl      -w
use strict;
print "Status: 301 Moved Permanently\n";
print "Location: http://somewhere/page.htm\n\n";
exit;
  

As in PHP, if you do not supply the 301 code explicitly, Apache will  send a "302 Found" status code. Note the subtle difference as compared  to PHP.  This example prints a "Status" header rather than an HTTP  status code line.   This is because you can not set the HTTP  status code directly as you typically can in PHP.  If you do, the server  will return a 500 Internal Server Error, and the error log will show:  

malformed header from script. Bad header=HTTP/1.1 301 Moved Permanently: /cgi/test.pl
  

The "Status" header is an alternative way of setting the HTTP status  code.  This is not passed to the browser directly, but the web server  (Apache) converts it into a suitable HTTP status code.  (The CGI  specification does not allow directly setting the HTTP status code.   Perl typically runs as a CGI, whereas PHP does not. For more  information, see this PHP header FAQ or the PHP header function documentation.)  

You must supply the carraige returns as specified above.  Two  carriage returns (\n\n) are needed after the last header, since they  signify the end of the HTTP header and the beginning of content.  

As in PHP, it is good practice to exit the script explicitly,  otherwise, the Perl script continues executing.  There should not be any  print "Content-type: text/html\n\n"; or other output before printing these headers, or the headers will be printed as part of the content visible in the browser.  

Redirection with mod_rewrite

  

The Apache module, mod_rewrite,  is typically used to transform URLs from one form to another.  It can  also be used for permanent redirection. The rewriting rules can be  placed in httpd.conf (for server-wide rules), or in .htaccess files (for  directory-specific rules). Consider the following example that is in  the .htaccess file of this website:  

rewriteEngine on
rewriteRule ^contact\.php$ http://www.somacon.com/p2.php [R=permanent,L]
  

The first line tells Apache to turn the mod_rewrite engine on.  The  second line tells mod_rewrite to match requests where the URI is exactly  contact.php.  The ^ and $ match the beginning and end of  the expression, respectively, and the \ is used to escape the period,  which otherwise would match any character.  After the match pattern is a  space, and then the substitution.  In this case, I want the server to  substitute contact.php with http://www.somacon.com/p2.php.  

In brackets are the comma-separated rule flags.  The R=permanent flag tells Apache to issue a permanent redirect 301 response, with the location as the substituted URL.  The L flag tells mod_rewrite that no other subsequent rules should be processed.  

Note that I specified the full destination URL in the  substitution, because otherwise mod_rewrite uses the short form of my  hostname somacon.com. To avoid Google indexing issues, I've  redirected all non-www traffic to the www prefixed host.  I also  redirect the default, index pages to the root directory.  The rules to  achieve this are as follows:  

# redirect all non-www traffic
RewriteCond %{HTTP_HOST} ^somacon\.com$
RewriteRule ^.*$ http://www.somacon.com%{REQUEST_URI} [R=permanent,L]

# Redirect aliases of home page to the root website
rewriteRule ^index\.(php|html|htm) http://www.somacon.com/ [R=permanent,L]
  

I leave it up to the reader to understand this example by reading the  mod_rewrite documentation.  The mod_rewrite module offers a very  powerful and effective way to perform redirection.  It is preferable to  use mod_rewrite over a server-side script.  The drawback is the steep  learning curve, requiring you to learn both its syntax and the syntax of  regular expressions.  

Redirection with Javascript or META tags

  

If you don't have server-side scripting or mod_rewrite on your web  server, you can still do redirection, but not as elegantly.  The  Javascript/META method will redirect after both the headers and the page  have loaded.  By contrast, the HTTP header method described  above redirects immediately after the headers have loaded.  While both  methods require two requests to the web server, the Javascript/META  method causes the user's browser to flicker or refresh as the old page  is loading.  Redirection with HTTP headers is seamless, and saves time.  

You can not send a 301 status code via Javascript or META tags. Since the HTTP status code of the page will remain 200 OK,  most search engines will continue to think the location is valid.  Any  page rank of the old location will not be transferred to the new  location.  

Another disadvantage is that some browsers disable Javascript or  META refresh.  Therefore, one must include a link to the destination  page in the body of the page.  One can also add a delay between when the  page is displayed, and when it redirects.  However, I would strongly  discourage this and will not even describe it here.    

Unfortunately, it is very common to see delayed META/Javascript  refresh used when a site or page has moved.  The page typically shows a  message saying, "This site has moved to ...  Your browser will be  automatically forwarded in X seconds. Click here if your browser does  not automatically forward you."  Some website, particularly government  and legal websites, add such an intermediate page whenever you click a  link to an external site.  

Not only is this search-engine unfriendly, but it has the  additional drawback of wasting the visitor's precious time while they  read wholly unneccessary information and wait for the redirect.  The  first rule of web design (and writing) is to treat your reader's time  with respect.  All visitors except the most novice can tell when they  are leaving your site for another, and that your site has no authority  over the external site, so there is no need to waste everyone else's  time.  

Redirection with Javascript

  
<html>
<head>
<script type="text/javascript">
window.location.href='http://www.somacon.com/';
</script>
</head>
<body>
This page has moved to <a xhref="http://somacon.com/">http://somacon.com/</a>

</body>
</html>
  

Note that they syntax document.location=''; has been deprecated.  Use the above code, or alternately, document.URL='';.  

Redirection with META Refresh

  
<html>
<head>
<meta http-equiv="refresh" content="0;url=http://www.somacon.com/">
</head>
<body>
This page has moved to <a xhref="http://somacon.com/">http://somacon.com/</a>
</body>
</html>
  

As I've pointed out, the META refresh tag should be avoided as a  method of redirection.  There are other times when it is more useful.  A  common situation is on a page where information is constantly changing,  like news or stock tickers. For example, most major news websites  include META refresh tags in their home pages.  CNN sets the refresh  interval to 1800 seconds, while Google sets it to 900 and Yahoo, to 300.  If the user switches to another application for awhile, when they  return, they are presented with the most up to date information.  

Another situation is in the status page for the execution of a  long-running server-side task.  A good site design principle is that  every web page load within a fraction of a second.  For longer tasks,  queue and run them on the server, and simply show a status page via the  web.  The three states of the status page would be queued, running, and completed.  The refresh tag would be printed in the queued and running  states, with an appropriate refresh interval like 15 or 30 seconds.   You should always put a link to manually refresh the status page, in  case the user disabled this META tag in their browser.  

Redirection Live Example

  

If you try to go to this page:
http://www.somacon.com/color/html_css_table_border_styles.php
You will automatically be redirected to this page via mod_rewrite:
http://www.somacon.com/p141.php
The actual HTTP headers for the old page are shown below. The headers were captured using the freeware utility, HTTPSpy.  

HTTP/1.1 301 Moved Permanently
Date: Thu, 07 Apr 2005 18:52:27 GMT
Server: Apache/1.3.33 (Debian GNU/Linux) mod_throttle/3.1.2 mod_ssl/2.8.22 OpenSSL/0.9.7d
Location: http://www.somacon.com/p141.php
Keep-Alive: timeout=15, max=100
Proxy-Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1
Via: 1.1 HttpSpy

HTTP/1.1 301 Status Code Definition

  

From the HTTP/1.1 Status Code Definitions section of the Hypertext Transfer Protocol -- HTTP/1.1  RFC 2616, Fielding, et al.  See the RFC for all the possible  redirection status codes, which include 300-Multiple Choices, 301-Moved  Permanently, 302-Found, 303-See Other, 304-Not Modified, 305-Use Proxy,  and 307-Temporary Redirect.  Using the appropriate status code is  worthwhile for public websites, but you can probably leave it  unspecified when redirecting in a private or intranet application.  

The requested resource has been assigned a new permanent URI and any  future references to this resource SHOULD use one of the returned URIs.  Clients with link editing capabilities ought to automatically re-link  references to the Request-URI to one or more of the new references  returned by the server, where possible. This response is cacheable  unless indicated otherwise.  

The new permanent URI SHOULD be given by the Location field in  the response. Unless the request method was HEAD, the entity of the  response SHOULD contain a short hypertext note with a hyperlink to the  new URI(s).  

If the 301 status code is received in response to a request other  than GET or HEAD, the user agent MUST NOT automatically redirect the  request unless it can be confirmed by the user, since this might change  the conditions under which the request was issued.  

Note: When automatically redirecting a POST request after       receiving a 301 status code, some existing HTTP/1.0 user agents       will erroneously change it into a GET request.


Tags:
Add a comment

Nickname

Website (Optional)

Email (Optional)

You can also login with your OpenID:
Enable HTML Enable UBB Enable Emots Hidden Remember [Login] [Register]