Expanding shortened URLs in a Ruby String

Everyone and their dog uses some sort of URL shortening service these days. While it's handy to cram an URL into short messages like those used on Twitter it's not always considered best practice for a bunch of reasons.

Since quite a few applications these days use Twitter feeds and similar services to gather new content, it'd be great to expand those URLs and undo any damage that these services cause.

Borrowing heavily from a Ruby based Twitter client I've extracted a module which can be used to do just that. Without further ado... here it is.

require 'net/http'

module BarkingIguana
  module ExpandUrl
    def expand_urls!
      ExpandUrl.services.each do |service|
        gsub!(service[:pattern]) { |match|
          ExpandUrl.expand($2, service[:host]) || $1
        }
      end
    end

    def expand_urls
      s = dup
      s.expand_urls!
      s
    end

    def ExpandUrl.services
      [
        { :host => "tinyurl.com", :pattern => %r'(http://tinyurl\.com(/[\w/]+))' },
        { :host => "is.gd", :pattern => %r'(http://is\.gd(/[\w/]+))' },
        { :host => "bit.ly", :pattern => %r'(http://bit\.ly(/[\w/]+))' },
        { :host => "ff.im", :pattern => %r'(http://ff\.im(/[\w/]+))'},
      ]
    end

    def ExpandUrl.expand(path, host)
      result = ::Net::HTTP.new(host).head(path)
      case result
      when ::Net::HTTPRedirection
        result['Location']
      end
    end
  end
end

To use it, first include the module into String.

class String
  include BarkingIguana::ExpandUrl
end

Then simply call expand_urls or expand_urls! on the text that contains shortened URLs. The bang method changes the string in-place where the regular method returns a copy of the string and leaves the original unchanged.

s = "http://tinyurl.com/asdf"
s.expand_urls!
puts s.inspect
# => "http://support.microsoft.com/default.aspx?scid=kb;EN-US;158122"

At the moment it supports ff.im, is.gd, bit.ly and tinyurl. If you can suggest any other services I'd love to hear about them. This code - like the original implementation - is released under the MIT licence. The full code including licence and RDoc can be found at http://pastie.org/471016. Enjoy!

Leave feedback...

  1. This looks pretty cool. You should try to package this up as a gem to make it easier to share.

    As a shameless plug, give jeweler a shot. You can easily generate a new gem project, and push it up to github.

  2. I would suggest http://aafter.us/ It is a fail-safe free URL shortening service provider. Hope, it would satisfy you.

    Regards,
    SharonHill

Commenting is closed for this article.

About the boy

A picture of Craig in grayscale

Craig Webster is a software engineer living in London. He usually works with Ruby although sometimes he sneaks in some Erlang or JavaScript. He's into rock climbing, snowboarding, skating, photography and fencing. Yes, this does mean he has a sword.

Near here you'll find Craig's homepage, contact details, PGP key and keysigning policy, and talks.

Licence

The entire content of this blog is public domain. Use it however you fancy. You don't even need to attribute it to me, although it would be nice if you did. Just don't sue me and we'll all be happy.

I Work With Rails

Recommend Me

My Travels

I go places. Do you go places too? Let's meet up!.