
(Note: Thanks to gizmo, I have corrected an abbreviation expansion problem.)
Uniform Resource Locators
are an addressing scheme at the heart of the Web. Without them, there would
be no stardard way to refer to a resource offered by a web server. URLs
remove the ambiguity of addressing a resource, but at the cost of creating
some rather formidable namespaces (e.g.
https://addons.mozilla.org/en-US/firefox/addon/9549
).
In general, long URLs aren’t a problem. Either through web page hyperlinks or web browser bookmarks, URLs fade into the background for most users. However, sometimes it is more convenient to have a shorter reference to a resource than the fully qualified URL. For example in the late nineties on IRC, it was common to see tiny.cc URLs pasted into chat rooms. Long URLs tend to clutter up already busy chat room windows. With the advent of text message-based systems like Twitter, which limit status updates to 140 characters, long URLs are actually consuming a valuable resource. The most common URL shortener used on Twitter.com appears to be bit.ly
There are several URL shortening services out there and they all work
pretty much the same way. The user supplies the full URL. The service
hashes the URL into something smaller and appends this to its own namespace.
Using the bit.ly service, the mozilla URL becomes:
http://bit.ly/g0Z9
. When someone accesses this bit.ly URL, he
will be seemlessly redirected to the original resource.
Bit.ly provides a REST interface to their service
(API).
To use this, create an account on
bit.ly’s system. Now you are ready to build a Perl REST client for the shorten
service (http://api.bit.ly/shorten
).
The following code is a listing of a small command line Perl script that expects to be passed a long URL. It uses the bit.ly REST service to return a shortened version.
use strict; use LWP::UserAgent; use Getopt::Std; use HTTP::Request; use URI; my $VERSION = "1.0"; my $Opts = {}; my $bitly_api_url = q[http://api.bit.ly/shorten]; my $long_url = pop @ARGV; getopts('u:p:?', $Opts); if (!$long_url || $Opts->{'?'}) { print usage(); exit; } set_defaults($Opts); my $ua = LWP::UserAgent->new; my $fetch_url = URI->new($bitly_api_url); $fetch_url->query_form({'version' => "2.0.1", 'format' => "xml", 'longUrl' => $long_url, }); my $req = HTTP::Request->new(GET => $fetch_url); $req->authorization_basic($Opts->{u} => $Opts->{p}); my $res = $ua->request($req); if ($res->code == 200) { my ($url) = ($res->content =~ m!(+) !); unless ($url) { warn("FAIL: [". $res->content . "]\n"); exit 1; } print "$url\n"; exit; } else { warn("FAIL:[".$res->content."]\n"); exit 1; } #----- # sub #----- sub usage { return <OPTIONS ? - Display this screen u [USERNAME] - Bit.ly username p [PASSWORD] - Bit.ly password EOT } sub set_defaults { my ($h) = @_; $h->{u} ||= "taskboy3000"; $h->{p} ||= "s3c3rt"; }
This code uses the standard Perl module Getopt::Std to parse optinal
command line arguments. The set_defaults
function merely uses
my bit.ly credentials if none are provided through optional parameters. Next,
a new LWP::UserAgent object is created to make client HTTP calls. The bit.ly
shorten service expects a GET request with optional arguments encoded as
query parameters in the URL. The bit.ly service can respond to requests with
data in various formats (e.g. XML, JSON). In this case, the format parameter
is set to “xml.”
The URI class manages the extra parameters through the
query_form
method and urlencodes these into the new
URL. A simple HTTP::Request object is passed the new URL and the bit.ly
credentials are added to the HTTP request header using the
authorization_basic
method.
Once the HTTP request has all the information, it is ready to be sent to the bit.ly server. The HTTP::Request object is passed to the LWP::UserAgent::request method, which contacts the server and encodes the response as an HTTP::Response object.
If an error occurred in transmission, the response will have a HTTP status code other than 200. Even if the requests succeeds, the service might fail due to missing or bad credentials. A simple regex extracts the shortend URL from the XML message and reports on the command line for easy consumption by other command line tools.
This script will run on any platform supported by Perl.