public
Description: TinyURL service in Ramaze
Homepage:
Clone URL: git://github.com/zh/turl.git
Click here to lend your support to: turl and make a donation at www.pledgie.com !
turl / turl.rb
100755 147 lines (121 sloc) 3.292 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env ruby
 
require 'rubygems'
require 'sequel'
require 'validatable'
require 'ramaze'
 
DB_FILE = __DIR__/'turl.db'
DB = Sequel.connect("sqlite://#{DB_FILE}")
 
BASE_URL = 'http://localhost:7000/'.freeze
 
#
# Model
#
class TinyURL < Sequel::Model(:turl)
  set_schema do
    primary_key :id
    varchar :url
    integer :hits
    timestamp :created
    index [:url], :unique => true
    index [:created]
    index [:hits]
  end
 
  include Validatable
 
  validates do
    presence_of :url
    format_of :url, :with =>
      /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix,
      :message => 'invalid URL'
  end
 
  after_create do
    update_values(:created => Time.now, :hits => 1)
  end
 
  def self.add(uri)
    t = TinyURL.create(:url => uri)
    return '' unless t && t.valid?
    t.save!
    return t.id.to_s(36)
  end
 
  def self.pack(uri,prefix=BASE_URL)
    return uri if uri.length < prefix.length
    exists = TinyURL[:url => uri]
    turl = exists ? exists.id.to_s(36) : TinyURL.add(uri)
    # 'index' is a controller name so insert the link once more
    turl = TinyURL.add(uri) if turl == 'index'
    return "#{prefix}#{turl}"
  end
 
  def self.unpack(turl)
    return nil unless t = TinyURL[:id => turl.to_i(36)]
    t.update_values(:hits => t.hits.to_i + 1)
    t.url
  end
 
  def self.count(turl)
    return 0 unless t = TinyURL[:id => turl.to_i(36)]
    t.hits
  end
 
end
 
TinyURL.create_table unless TinyURL.table_exists?
 
#
# Controller and View
#
 
class MainController < Ramaze::Controller
 
  LOGINS = {
    :admin => 'secret'
  }.map{|k,v| ["#{k}:#{v}"].pack('m').strip} unless defined? LOGINS
 
  helper :aspect
 
  before(:_api) do
    response['WWW-Authenticate'] = %(Basic realm="Login Required")
    respond 'Unauthorized', 401 unless auth = request.env['HTTP_AUTHORIZATION'] and
                                       LOGINS.include? auth.split.last
  end
  
  layout :_page
 
  def index turl=nil, *params
    if turl
      url = TinyURL.unpack(turl)
      redirect(url ? url : Rs())
    end
    ""
  end
 
  def _add
    redirect(Rs()) unless request.post?
    turl = TinyURL.pack(request[:url])
    "Tiny URL: <a href=\"#{turl}\">#{turl}</a><br/><br/>"
  end
 
  # _api?turl=http://... will return short url
  # _ari?url=.. will restore the original url
  # _ari?hits=.. will return the number of hits to given turl
  def _api
    res = TinyURL.pack(request[:turl]) if request[:turl]
    res = TinyURL.unpack(request[:url].split('/').last) if request[:url]
    res = TinyURL.count(request[:hits].split('/').last).to_s if request[:hits]
    res = '' unless res
    respond res
  end
 
  def _page
    %{
<html>
<head>
<title>TinyURL Service</title>
</head>
<body>
#@content
<form id="tinyurl" method="post" action="/_add">
<div>
Enter long URL:
<input id="url" name="url" type="text" />
<input type="submit" value="Pack" />
</div>
</form>
</body>
</html>
}
  end
end
 
 
if __FILE__ == $0
  Ramaze::Log.loggers = [ Ramaze::Logger::Informer.new( File.join(__DIR__, 'turl.log'))]
  begin
    require 'mongrel'
    Ramaze.start :adapter => :mongrel, :port => 7000
  rescue LoadError
    Ramaze.start :adapter => :webrick, :port => 7000
  end
end