Archive

Posts Tagged ‘mod_rewrite’

Redirect HTTPS To HTTP

April 9th, 2009 Tech No comments

To redirect from HTTPS to HTTP on the home page only using the following rule.

RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/ [R=301,L]

The variable %{HTTPS} will be either "on" or "off" and will be enabled even if SSL is not installed on your site. The rule above sees that HTTPS is on and redirects the home page to the HTTP version. You can even chain lots of rules together like this.

RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/ [R=301]
RewriteRule ^inner/directory/?$ http://%{SERVER_NAME}/inner/directory/ [R=301,L]

Note that you should end your last rule with L so that no other rules on the page are run. Also, you need to make absolutely sure that you are not redirecting any pages that are integral to the security of your shopping cart as this will turn off HTTPS for those pages.

You can also do the same thing using the ${SERVER_PORT} variable.

RewriteCond %{SERVER_PORT} 443
RewriteRule ^/?$ http://%{SERVER_NAME}/ [R=301,L]

The port for HTTPS is 443 so if the port being communicated through is 443 we need to redirect.

Creating A URI Slug With PHP

March 28th, 2008 Tech No comments

The use of mod_rewrite on a site can have a powerful effect on search engine positioning, but to do it properly you will need to create a "slug" for each page. A slug is a lowercase alphanumeric version of the page title, with any spaces removed.

To get a slug you will need to use a function to turn a readable page title into a string that can be used as part of a URI.

This function is taken from Bramus and his excellent article about creating a post slug, and it does the job very nicely.

function fixForUri($string){
 $slug = trim($string); // trim the string
 $slug= preg_replace('/[^a-zA-Z0-9 -]/','',$slug ); // only take alphanumerical characters, but keep the spaces and dashes too…
 $slug= str_replace(' ','-', $slug); // replace spaces by dashes
 $slug= strtolower($slug); // make it lowercase
 return $slug;
}

To use the function just pass your page title (and it can be as messy as you like) into the function and capture the output.

$string = '"I\'ve got a lovely *bunch* of coconuts!"';
echo fixForUri($string);

UPDATE:

I recently found a bug in this function where any trailing spaces where converted into hyphens and used as part of the slug. To stop this I have added a call to trim() in order to prevent this from happening.

Categories: PHP Strings Tags: , , , , ,

Using mod_rewrite On Form Parameters

March 5th, 2008 Tech 11 comments

Using mod_rewrite on websites is fairly straightforward and can create some lovely looking URL structures. Instead of having a URL that contains lots of odd looking parameters like this:
http://www.example.com/example.php?parameter1=value1&parameter2=value2

You can use a .htaccess file to rewrite the URL on the server side in order to shorten this to something like this:
http://www.example.com/p-value1

In this occasion the value of parameter2 will always be value2 so we can just include that in the rewrite rule, which would look something like the following. $1 is a back-reference to the first parenthesized value matched in the RewriteRule.
RewriteRule ^p-(.*)$ /example.php?parameter1=$1&parameter2=value2 [L]

Remember to turn ensure that the FollowSynLinks directive is enabled and that the rewrite engine is turned on before starting your rewrite rules. FollowSynLinks should have been enabled by your server administrator, but you can include here just in case they haven’t.
Options +FollowSymLinks
RewriteEngine On

You can also make sure that mod_rewrite is actually installed by enclosing all of this in an if statement. This will stop the server throwing an error if you don’t have mod_rewrite.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
</IfModule>

What PHP sees on the server side is exactly the same as normal so you can retrieve the parameters with a standard $_GET lookup.

However, the default behaviour of forms messes this up. Lets say that we had a search page that we created a rewrite rule so that it read like this:
http://www.example.com/s-value1

This redirects to the page search.php and passes any parameters to that page. The problem here is if we call the same page through a form. Here is an example search form.
<form action="search.php" method="get">
<input type="text" name="q" value="" />
<input type="submit" name="s" value="Search" />
</form>

When this is run with the string "test" the URL looks like this.
search.php?q=test&s=Search

This is the default browser behaviour, but it still messes up the nice URL structure created previously. There is a way to fix this. Have a look at the following .htaccess file.

<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
 
RewriteCond %{REQUEST_URI} /search.php$
RewriteCond %{QUERY_STRING} ^q=([A-Za-z0-9\+]+)&s=Search$
RewriteRule ^(.*)$ /s-%1? [R=301,L]
 
RewriteRule ^s-(.*)$ /search.php?q=$1&s=Search&a=1 [L]
</IfModule>

Here we are using the RewriteCond directive which allows us to test for certain conditions. In this case we have two conditions.
RewriteCond %{REQUEST_URI} /search.php$
RewriteCond %{QUERY_STRING} ^q=([A-Za-z0-9\+]+)&s=Search$

The first condition allows us to only run the rule on the page search.php. This stops any annoying confusion if we want to pass a similar query string to a different page. The second condition allows us to test the query string to see if it contains the parameters we are looking for. The %{QUERY_STRING} bit is a reference to the actual query string passed, minus the question mark at the beginning. In this case we want to trap the parameter q with any value and the parameter s with the value of Search. The dollar sign at the end is very important, but I’ll come back to that.

The first rewrite rule redirects the page search.php to the URL /s- and whatever the query string was. The %1 is a back-reference to the first parenthesized value matched in the most-recently-matched RewriteCond.
RewriteRule ^(.*)$ /s-%1? [R=301,L]

We then also need to include a rewrite rule that will recognise the new URL and act on it. However, want we don’t want to do is confuse the server and put it into an endless loop, which is quite easy since we are redirecting from search.php to search.php. So what we do is include the parameter "a" at the end of our rewrite rule with the value of 1.
RewriteRule ^s-(.*)$ /search.php?q=$1&s=Search&a=1 [L]

Going back to the second rewrite condition above we included a dollar sign at the end of the rule. This meant that the string had to end there, so if we include anything else after the end of the query string the rewrite condition will return false. So although we don’t actually use the a in our script it is needed there to stop the server going into an infinite loop of redirects.

For more information on mod_rewrite and other .htaccess examples have a look at the excellent tutorial at Ask Apache.

Avoiding URL Canonicalisation With mod_rewrite And Apache

February 22nd, 2008 Tech No comments

URL canonicalisation is where you have a website with different URLs outputting the same content. When search engine spiders see all this content that is the same they can get confused as to what page to display in search engine result pages. The following URLs, although they are different, actually produce the same content.

http://www.example.com
http://example.com
http://www.example.com/
http://www.example.com/index.html

The way to solve this issue is to redirect any requests to a single page using mod_rewrite. Add a .htaccess file to your root directory and include the following line to turn on the engine.

RewriteEngine On

The following rule will redirect the www page to the non-www page.

#Redirecting non-www to www.domain.com:
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

Use the following rule to redirect from the index.html page to the directory name.

#Redirecting /index.html to /:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.html
RewriteRule ^index\.html$ http://www.domain.com/ [R=301,L]

If you want to detect for the existence of mod_rewrite you can include all of the previous lines in an if statement like this.

<IfModule mod_rewrite.c>
RewriteEngine On
 
#Redirecting non-www to www.domain.com:
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
 
#Redirecting /index.html to /:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.html
RewriteRule ^index\.html$ http://www.domain.com/ [R=301,L]
</IfModule>