Desacortador de URLs en nodejs y express

No siento un especial aprecio hacia los acortadores de urls, como tinyurl o t.co, no digo que no sean necesarios, pero me resultan muchas veces molestos. Además considero que lo que consiguen en ofuscar y segmentar de forma arbitraria la web.

Aprovechando mi ambición por acabar con las urls cortas y que ultimamente estoy probando nodejs, vamos a hacer una copia de unshort.me usando express.

Empecemos por crear la aplicación express:

$ express unshorter

   create : unshorter
   create : unshorter/package.json
   create : unshorter/app.js
   create : unshorter/public
   create : unshorter/public/javascripts
   create : unshorter/public/images
   create : unshorter/public/stylesheets
   create : unshorter/public/stylesheets/style.css
   create : unshorter/routes
   create : unshorter/routes/index.js
   create : unshorter/views
   create : unshorter/views/layout.jade
   create : unshorter/views/index.jade

   dont forget to install dependencies:
   $ cd unshorter && npm install

Instalamos las dependencias como nos indica la salida:

$ cd unshorter 
$ npm install
jade@0.25.0 ./node_modules/jade 
├── commander@0.5.2
└── mkdirp@0.3.0
express@2.5.8 ./node_modules/express 
├── qs@0.4.2
├── mkdirp@0.3.0
├── mime@1.2.4
└── connect@1.8.7

Y probamos a arrancar el servidor:

$ node app
Express server listening on port 3000 in development mode

Provemos en nuestro navegador

Aunque no parezca mucho, ya llevamos como un tercio de nuestra aplicación hecha ;)

Para nuestro acortador necesitaremos un formulario donde el usuario introduzca una url corta, pongamos lo en la vista index que encontrarás en views/index.jade
Jade es un lenguaje con cierto parecido a haml. Cambiamos el contenido actual por

h1= title
p Welcome to #{title}
form(action="/unshort", method="get")
  p Enter URL 
  p
    input(type="text", name="q")
  .btn
    input(type="submit", value="unshorten")

Ya tenemos nuestro formulario esperando que /unshort sepa respondernos a nuestra consulta “q”.

Para desacortar las urls “bastaría” con conectar con la url e ir siguiendo redirects (30X) hasta conseguir un 200. Pero como queremos ser, no se, asi, como, productivos ;) Vamos a usar un componente ya hecho, node-unshortener, que nos aporta abstracción y bastantes características interesantes. Lo añadimos a package.json

...
    , "jade": ">= 0.0.1"
    , "unshortener": ">= 0.0.9"

y lo instalamos

$ npm install
unshortener@0.0.9 ./node_modules/unshortener 
└── bitly@1.1.2

Ya tenemos la magia, ahora solo falta juntarla con js.

Tendremos que añadir una nueva ruta a nuestra aplicación que reside en app.js. Modificamos las rutas para que queden

app.get('/', routes.index);
app.get('/unshort', routes.unshorten);

Y modificamos routes/index.js para que quede

var unshortener = require('unshortener');
                        
/*
 * GET home page.
 */

exports.index = function(req, res){
  res.render('index', { title: 'Express', action:null })
};

exports.unshorten = function(req, res){
  unshortener.expand(req.query.q, function (url) {
     res.render('index', { title: 'Unshorted', action:{unshort:url, orig:req.query.q} });
  });
};

Usamos el componente para desacortar la url que se nos envia en req.query.q y renderizamos la misma vista index con el campo extra action, que tambien hemos añadido para /. Añadimos a continuación en la vista index

...
p Welcome to #{title}

- if (action)
  p
    | unshorted 
    a(href="#{action.orig}") #{action.orig} 
    | is 
    a(href="#{action.unshort.href}") #{action.unshort.href}

form(action="/unshort", method="get")
...

Para que, si hemos definido action desde nuestro “controlador”, nos muestre también la información capturada.

Y podemos probarlo

Y ya tenemos nuestro mini desacortador de urls nodejs powa!.

Happy coding :)