Skip to content

Instantly share code, notes, and snippets.

@myobie
Created June 21, 2011 12:30
Show Gist options
  • Save myobie/1037750 to your computer and use it in GitHub Desktop.
Save myobie/1037750 to your computer and use it in GitHub Desktop.
unfurler.heroku.com
The Unfurler!
=============
## What is it?
You give it a shortened url and it looks up where it would take you. There is a
version running at http://unfurler.heroku.com if you want to try it out.
## How do I run it?
$ bundle install
$ shotgun
## How do I deploy it?
$ gem install heroku
$ heroku create
$ git push heroku master
$ heroku open
## How do I use it?
Navigate to http://localhost:9393/ and type in a shortend url. You can also just
use the address bar like so: http://localhost:9393/u/bit.ly/ieHELP
## API?
There is a json api, believe it or not. Just use /j/ instead of /u/ to get json
back, like so: http://localhost:9393/j/bit.ly/ieHELP
To do this with jQuery, this would look like:
$.get('http://localhost:9393/j/bit.ly/ieHELP', {}, function(data) {
console.log(JSON.stringify(data))
}, "json")
or if you want to use a `script` tag and have it fire a callback, you can do:
<script>
function foo(json) {
alert(JSON.stringify(json));
}
node = document.createElement('script');
node.src = "http://unfurler.heroku.com/j/bit.ly/ieHELP?callback=foo";
document.body.appendChild(node); // this loads and runs the script
</script>
If you want it to run on page load, just put it in a script tag manually like so:
<!-- define `foo` in a script tag before this one -->
<script src="http://unfurler.heroku.com/j/bit.ly/ieHELP?callback=foo"></script>
The callback is provided to help get around XSS protections.
require 'sinatra'
require 'httparty'
require 'haml'
require 'json'
set :haml, :format => :html5
class Unfurler
attr_accessor :redirects, :protocol, :url, :response
def initialize new_url
self.url, self.redirects = new_url, []
end
def url= new_url
@protocol = if proto = new_url.match(%r{^(http[s]*://)})
proto[1]
else
"http://"
end
@url = new_url.gsub %r{^http[s]*://}, ''
end
def full_url
protocol + url
end
def head
HTTParty.head full_url, follow_redirects: false
end
def fetch!
@response = head
if @response.code.to_s =~ /30[12]/
@redirects << response.headers['location']
unfurler = self.class.new(@redirects.last).fetch!
@redirects.concat unfurler.redirects
end
self # return self so it's chainable
end
end
helpers do
def title new_title
@title = new_title
end
def partial name, locals = {}
haml name.to_sym, :layout => false, :locals => locals
end
end
get '/' do
title 'Home'
haml :index
end
get '/u/*', :provides => 'html' do
expires 604800, :public # cache for a week
# :url and :splat to support js and non-js users
url_param = params[:url] || (params[:splat] || []).join("/")
throw 404 if url_param.nil? || url_param.empty?
@unfurler = Unfurler.new(url_param).fetch!
title "Unfurling #{@unfurler.url}"
if @unfurler.redirects.empty?
haml :not_a_redirect
else
haml :unfurled
end
end
get '/j/*' do
content_type :json
@url_to_request = params[:splat].join("/").gsub(/http:\/\//, '')
@url_response = Unfuler.new(@url_to_request).head
json = @url_response.headers.to_hash.to_json
unless params[:callback].nil? || params[:callback].empty?
json = params[:callback] + "(#{json})"
end
json
end
get '/style.css' do
content_type :css
erb :stylesheet, layout: false
end
get '/site.js' do
content_type :js
erb :javascript, layout: false
end
template :layout do
%q{
!!!
%html
%head
%title= "#{@title} - Unfurler"
%link(rel="stylesheet" href="/style.css")
%link(rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKBJREFUeNpidHNzYyAFMDGQCGivgQWIAwMD5eTkJk6cCBGCc/Pz8zU0NOBKb9y4ARQEaQBKI0ugcdevXw9hfPv2DWoDfrBr1y50J+EH8HA/d+7cmzdvCGvQ1NSE+4EoG+CBgQjW69evA8no6GigX4EOAJIQw3AG65EjR4D22oABkAt0KDxkMAEj3E8iYAAMu0ePHhGIOAh4AwaDIC0BBBgAvws9sktyKQMAAAAASUVORK5CYII=")
%body
%h1
%a(href="/") The Unfurler!
= yield
%script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js")
%script(src="/site.js")
}
end
template :index do
%q{
%form#the-form(action="/u/")
%p
%label(for="url") URL to unfurl:
%input(name="url" id="url" placeholder="URL to unfurl" autofocus)
%p
%button(type="submit") Unfurl
}
end
template :unfurled do
%q{
%p
You provided
%a(href="#{@unfurler.full_url}")= @unfurler.url
- @unfurler.redirects.each do |r|
= partial(:redirect, redirect: r)
}
end
template :redirect do
%q{
which redirects to
%a(href="#{redirect}")= redirect
}
end
template :not_a_redirect do
%q{
%p
You provided
%a(href="#{@unfurler.full_url}")= @unfurler.url
which doesn't redirect anywhere.
}
end
template :stylesheet do
%q[
html { background: #eee; }
body {
width: 500px;
margin: 0 auto;
padding: 20px;
background: #fff;
-webkit-box-shadow: 0 1px 9px rgba(0,0,0,0.1);
-moz-box-shadow: 0 1px 9px rgba(0,0,0,0.1);
box-shadow: 0 1px 9px rgba(0,0,0,0.1);
font: 16px/1.6 Helvetica Neue, Arial, sans-serif;
color: #333;
}
h1 { text-align: center; }
h1, p { margin: 0 0 1em; }
h1 a {
color: #333;
text-decoration: none;
}
h1 a:hover { color: #000; }
body.loaded label { display: none; }
input {
width: 400px;
font: 16px/1.3 Helvetica Neue, Arial, sans-serif;
}
form p { text-align: center; }
]
end
template :javascript do
%q@
document.body.className = "loaded";
if (document.getElementById('the-form')) {
document.getElementById('the-form').onsubmit = function(event) {
var url = document.getElementsByTagName('input')[0].value;
window.location = window.location.protocol + "//" +
window.location.host + "/u/" + url.replace(/http:\/\//, '');
return false;
};
}
@
end
run Sinatra::Application
source :rubygems
gem 'sinatra'
gem 'httparty'
gem 'haml'
gem 'json'
group :development do
gem 'shotgun'
end
GEM
remote: http://rubygems.org/
specs:
crack (0.1.8)
haml (3.1.2)
httparty (0.7.8)
crack (= 0.1.8)
json (1.5.3)
rack (1.3.0)
shotgun (0.9)
rack (>= 1.0)
sinatra (1.2.6)
rack (~> 1.1)
tilt (< 2.0, >= 1.2.2)
tilt (1.3.2)
PLATFORMS
ruby
DEPENDENCIES
haml
httparty
json
shotgun
sinatra
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment