Created
October 11, 2013 09:42
-
-
Save lsongdev/6932196 to your computer and use it in GitHub Desktop.
网址压缩
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'sinatra' | |
require 'dm-core' | |
require 'dm-timestamps' | |
require 'dm-migrations' | |
require 'dm-serializer' | |
require 'json' | |
require 'net/http' | |
require 'openssl' | |
configure do | |
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/default.db") | |
class URLInfo | |
include DataMapper::Resource | |
property :id, Serial | |
property :name, String, :required => true | |
property :url, String, :required => true | |
property :hit, Integer, :default => 0 | |
property :created_at, DateTime | |
property :updated_at, DateTime | |
end | |
# automatically migrate database if needed | |
DataMapper.auto_migrate! | |
end | |
def keygen_sub | |
arr = [] | |
[0 .. 9, 'a' .. 'z', 'A' .. 'Z'].each do |range| | |
arr += range.to_a | |
end | |
word = "" | |
5.times { word += arr[ rand( arr.size ) ].to_s } | |
word | |
end | |
def keygen | |
key = keygen_sub | |
URLInfo.all(:name => key).size == 0 ? key : keygen | |
end | |
def fetch_title(url) | |
uri = URI(url) | |
http = Net::HTTP.new(uri.host,uri.port) | |
http.verify_mode=OpenSSL::SSL::VERIFY_NONE | |
http.use_ssl=uri.scheme == 'https' | |
res = http.get(uri.path.empty? ? '/' : uri.path) | |
if res.is_a? Net::HTTPRedirection | |
return fetch_title res['Location'] | |
end | |
charset=res.type_params['charset'] || 'utf-8' | |
html = res.body.encode('utf-8',charset) | |
title_re = /<title\b[^>]*>([^<]+)<\/title>/ | |
return title_re.match(html) && title_re.match(html)[1] || '' | |
end | |
before do | |
headers "Content-Type" => "text/html; charset=utf8" | |
end | |
get '/' do | |
erb :index | |
end | |
get '/:name' do | |
info = URLInfo.first(:name => params[:name]) | |
info.update(:hit => info.hit + 1) unless info.nil? | |
redirect info.url unless info.nil? | |
end | |
get '/info/:name' do | |
@info = URLInfo.first(:name => params[:name]) | |
@title = fetch_title @info.url | |
#@info[:title] = title | |
erb :info | |
end | |
# | |
#URL | |
#Alias | |
post '/api/short_url' do | |
info = URLInfo.first_or_create({:url => params[:url]},{ | |
:name => (params[:alias].empty? || !URLInfo.first(:name => params[:alias]).nil?) ? keygen : params[:alias], | |
:url => params[:url] | |
}) | |
info.to_json | |
#{ :id => info.id, }.to_json | |
end | |
enable :inline_templates | |
__END__ | |
@@ layout | |
<!DOCTYPE html> | |
<html lang="en" > | |
<head> | |
<meta charset="utf-8" ></meta> | |
<title >GO! - URL Shorter</title> | |
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'> | |
<link rel="stylesheet" href="//static.lsong.org/css/bootstrap.css"> | |
<link rel="stylesheet" href="//static.lsong.org/css/bootstrap-responsive.css"> | |
<script src="//static.lsong.org/js/jquery.js" ></script> | |
<script > | |
(function($){ | |
$(function($){ | |
var tinyUrl = function(url, alias){ | |
$('.result').hide(); | |
$('.show-result').hide(); | |
$.ajax({ | |
url: '/api/short_url', | |
data: { 'url' : url, 'alias': alias}, | |
type: 'POST', | |
dataType: 'json', | |
error:function(err){ | |
$('.alert').removeClass('alert-success alert-error').addClass('alert-error').text('Error').show(); | |
$('.show-result').show(); | |
}, | |
success:function(data){ | |
$('.txt-tiny-url').val(location.href + data.name); | |
$('.btn-view').attr('href',location.href + "info/" + data.name); | |
$('.btn-open').attr('href',location.href + data.name); | |
$('.alert').removeClass('alert-success alert-error').addClass('alert-success').text('Success').show(); | |
$('.show-result').show('fast'); | |
$('.result').show(); | |
} | |
}); | |
}; | |
$('.form-short').submit(function(ev){ | |
ev.preventDefault(); | |
var url = $('.txt-long-url').val(); | |
var alias = $('.txt-alias').val(); | |
tinyUrl(url,alias); | |
}); | |
$('.txt-tiny-url').on('click',function(ev){ | |
ev.preventDefault(); | |
this.select(); | |
}); | |
$('.btn-open').click(function(ev){ | |
ev.preventDefault(); | |
window.open(this.href); | |
}); | |
}); | |
})(jQuery); | |
</script> | |
<style> | |
html,body{ | |
font-family: 'Open Sans' | |
} | |
.footer{ | |
height: 60px; | |
margin-top: 60px; | |
background-color: #f5f5f5; | |
} | |
.container{ | |
width: auto; | |
max-width: 680px; | |
} | |
.footer p { | |
margin: 20px 0; | |
} | |
input[readonly]{ | |
background-color: #fff; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container" > | |
<div class="header page-header" > | |
<ul class="nav nav-pills pull-right" > | |
<li><a href="//lsong.org" >Home</a></li> | |
</ul> | |
<h1><a href="/">Go! </a></h1> | |
</div> | |
<div class="content" > | |
<%= yield %> | |
</div> | |
<div class="footer" > | |
<p class="muted" >©LSONG.ORG</p> | |
</div> | |
</div> | |
</body> | |
</html> | |
@@ index | |
<h2>Short URL</h2> | |
<form class="form-short" > | |
<fieldset> | |
<div class="controls controls-row" > | |
<input type="url" class="input span6 txt-long-url" placeholder="Enter another long URL to make tiny" required /> | |
<input type='text' value="" class="span1 txt-alias" placeholder="Alias" /> | |
</div> | |
<button class="btn btn-large btn-block btn-primary" type="submit">Go!</button> | |
</fieldset> | |
</form> | |
<div class="show-result hide" > | |
<div class="alert" >Success</div> | |
<div class="result" > | |
<div class="input-prepend input-append" > | |
<span class="add-on" >URL:</span> | |
<input class="input txt-tiny-url" readonly="readonly" type="text" /> | |
<a class="btn btn-mini btn-share add-on" >Share</a> | |
<a class="btn btn-mini btn-view add-on" >Info</a> | |
<a class="btn btn-mini btn-open add-on" >Continue</a> | |
</div> | |
</div> | |
</div> | |
@@ info | |
<span class="badge badge-success pull-right" ><%= @info.hit %></span> | |
<h2>Preview</h2> | |
<div class="well"> | |
<h3><%= @title %></h3> | |
<a href=<%= @info.url %> ><%= @info.url %></a> | |
<a href=<%= @info.url %> class="btn btn-primary btn-mini" >Continue</a> | |
</div> | |
<div id="disqus_thread"></div> | |
<script type="text/javascript"> | |
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ | |
var disqus_shortname = 'tinyurl'; // required: replace example with your forum shortname | |
var disqus_identifier = '<%= @info.name %>'; | |
/* * * DON'T EDIT BELOW THIS LINE * * */ | |
(function() { | |
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; | |
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; | |
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); | |
})(); | |
</script> | |
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> | |
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment