GVS is now part of Acquia.
Build Your Own TinyURL With Drupal AND Everything You Need to Know About Paths in Drupal
Drupal has some pretty amazing features to handle aliases and aliasing. They are also commonly misunderstood. This article is an attempt to shed some light on how URLs and aliases and redirects work in Drupal which, with the help of some contributed modules, automatically turn a Drupal site into a TinyURL-like service.
It All Starts With the Menu System
Most modules in Drupal have a hook into the menu system which allows them to declare paths to which they will respond. For example, the node module's hook to the menu system allows it to respond to requests for "/node/".
Clean URLs vs. ... Dirty? URLs
Drupal responds to the "q" parameter from the URL. http://growingventuresolutions.com/?q=node/1 tells Drupal to serve up the page for "node/1". Ever since about 2003 Drupal has used features of the web server so that http://growingventuresolutions.com/?q=node/1 can be "rewritten" to http://growingventuresolutions.com/node/1. This is the so-called "Clean URL" which removes the main query parameter from every Drupal page request. Sure, there are still some page requests like for the second page in a list of nodes but they are much less common.
Ever since Drupal 6.x, if your web server supports clean urls then they will be enabled during installation. This is great.
Internal Path vs. Path Alias
In various administration screens and documentation Drupal uses the phrase "internal path" or "system path" or "Drupal path" to mean things like node/1 or taxonomy/term/1. This is in contrast to a path alias like those provided by the Drupal Core Path module. Let me reiterate: Drupal Core Path module. Drupal core lets you create any alias for any system path. On this site about is the alias for node/1.
You can have multiple aliases for one internal path, but it is not recommended. This is confusing, both to your users and search engines, to have the same content available at two paths. The problem is not limited to creating multiple aliases for a single internal path. Even having just the alias and the internal path creates multiple URLs for the same content. For solutions to both of these problems, see below.
Of course you don't want to build your own alias for every path so you use something like Pathauto to create your aliases for you. These are additions to the Drupal core modules, but they simply extend the features of the core Path module.
user/1 vs. members/admin - What does Drupal see?
If you have created an alias (manually or via Pathauto, no difference) so that the internal path of "user/1" is accessible via the alias "members/admin" what does Drupal actually see? The answer depends on the context of the question. For block visibility rules and a few other things, the rules are checked against both "user/1" and "members/admin" to determine which blocks to show. However, the arg function only sees the internal values so that for a user visiting "members/admin" arg(0) is "user" and arg(1) is "1".
Extending Pathauto for Other Things (like Views!)
Pathauto only creates aliases for paths based on the system paths used in Drupal core for nodes, users, and taxonomies. This leaves arbitrary URLs that accept node IDs, user ids, and term IDs without any solution (and by arbitrary URLs I'm of course thinking of Views and Panels. It would be possible to write a plugin to Pathauto that uses the Pathauto API and a little custom code to build aliases for Views or Panels. Unfortunately it is fairly difficult to write such a plugin in a generalized way. That remains a topic for a future blog post...
WWW or no-www
Do you use a www in front of your url or not? This is up to your personal preferences. My advice is that sites focused on less savvy visitors should use the "www" in the front of the domain while the wave of the future is to get rid of www. Regardless of which you choose (and you should choose one) Drupal's core .htaccess file provides an example of how to redirect from one to the other. But, if you want a tiny url, then ommitting it (or at least redirecting it) is a good idea. See this old blog post for more discussion.
Path Redirection and Global R
These two modules that provide some additional benefits for most sites.
Path Redirect allows site admins to create redirects. Unlike aliases, redirects send the visitor to a new page using an HTTP 3xx redirect code. This is a benefit when you want two paths to work for the same content without the duplication problems mentioned earlier. While Path Redirect provides all the 3xx redirects, the most common and recommended one is a 301 redirect. When Path Redirect is installed, Pathauto will present a new "Update action" for situations where a URL changes to create a new alias and redirect from the old alias. This is the recommended configuration.
Global Redirect removes the duplicate content problems created in other parts of Drupal such as the "?q=node/1" vs. "node/1" vs. "about" on this site. You may have noticed earlier that while the links I created in this article pointed to the "Dirty URL" or the "internal path" for the page the browser was redirected to the one true alias for a page. That is the work of the very useful Global Redirect module. It provides several benefits and has very little impact on performance or user interface which makes Global Redirect a "must have" on most every site.
Building a Site-Specific TinyURL Feature with Drupal
There are many sites around the internet like TinyURL or NotLong which provided shortened links to really long urls. Links provide an opportunity for branding and building trust - why outsource this function to third party services when you can build it yourself?
If you made it this far you already know the answer to the question of "how to build tinyurl with Drupal"
- Start with a short domain name - maybe one that is a shortened version of your normal name.
- Remove the www from the front of it.
- Use the "node/nid" url instead of the alias
- Celebrate!
For example, this story is also accessible at http://growvs.com/node/243.
- From http://growvs.com/node/243 the DNS system forwards to http://growingventuresolutions.com/node/243
- From http://growingventuresolutions.com/node/212 you get forwarded to the aliased version of the page by Global Redirect
Yay!
P.S. My thanks to merlin and ezra-g for their reviews of this post.
- Login to post comments
GVS projects
GVS is now part of Acquia.
Contact Acquia if you are interested in a Drupal Support or help with any products GVS offered such as the Conference Organizing Distribution (COD).
Comments
Thaks for pointing such a
Thaks for pointing such a simple solution to tiny urls in Drupal. It seems really obvious, but I never thought about it until I read this and thought it could be useful in several scenarios, such as sending an e-mail.
I have not checked if there is a module for this (and if a module is too big for the job, since all you have to output is the base url and the node id) but I can imagine it would be a good idea to include a simple link pointing to the "tiny url" in each an every site node, so that our readers can also use that short url whenever they need it.
It could also be useful hiding that url in node types with short alias already, such as pages (e.g. http://host/about).
BTW, this will also work with comments (in the form "http://host/node/[id]/#comment[cid]") as they are part of the node, but probably not with things like media (images and such).
Thanks again
I've been thinking about that
I've been thinking about that feature more ever since writing this post. I think the easiest way to achieve it would be with something like Custom Links which uses the Token module.
Is it possible to drop the
Is it possible to drop the "node/" part of the URL, to get an even shorter URL something similar to tinyurl.com?
For example,
FROM:
http://growvs.com/node/243
TO:
http://growvs.com/243
If that's not possible, do you know how to change the word "node" to 1 letter like "n" to get:
http://growvs.com/n/243
This is totally possible, but
This is totally possible, but I'm not sure of the exact technical details. Our DNS forwarding allows to forward from growvs.com to growingventuresolutions.com/something/ so we could do example.com/123 to example.com/node/123. However, we also like the idea of forwarding from http://growvs.com/user/1 to our user pages so we don't want to forward all urls to the node/ namespace. It would also be possible to create a .htacess forwarding rule to go from growvs.com/n/123 to growvs.com/node/123 which also logically allows growvs.com/u/123 to forward to growvs.com/user/123. This should be possible using mod_alias.
Thanks. And thanks for the
Thanks.
And thanks for the very quick reply.
I also found this, pathauto-6.x-1.1.tar.gz, a module that might do what I want to do.
I haven't tried it yet.
yep path auto works great,
yep path auto works great, you can have "yoursite.net/article" point to "yoursite.net/node/23" where node 23 is the article. then just be sure to edit your robots.txt to dissallow crawling /node because of the duplicate content that path auto creates
Yes, but no! One point of
Yes, but no!
One point of this article is to teach people about Global Redirect. That module solves the Duplicate content penalty.
If you just need tiny URLs
If you just need tiny URLs for nodes it is pretty easy with mod_rewrite / .htaccess
If you open your .htaccess which comes with drupal, you will see something like:
# Rewrite current-style URLs of the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
This causes apache to do the following:
if the requested filename is not an existing file on the server and is not an existing directory, then redirect to index.php/q=[complete filepath here], e.g. node/123 -> index.php/q=node/123
You may want to define your own rule right before the one mentioned above, which should redirect any numeric filename to the according node path. This would look like:
# Rewrite straight numeric URLs of the form 'index.php?q=node/x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([0-9])$ index.php?q=node/$1 [L]
# Rewrite current-style URLs of the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.)$ index.php?q=$1 [L,QSA]
I don't think this method
I don't think this method will work for user pages (i.e. user/#)
well path auto works for user
well path auto works for user pages but im not sure about global redirect