-
Notifications
You must be signed in to change notification settings - Fork 2
/
hello.rb
100 lines (80 loc) · 1.93 KB
/
hello.rb
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
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
require 'tipi'
module TeenyURL
## The servic encapsulate everything needed to access this API
class Service
attr_reader :urls
def initialize
@urls = {}
end
## This is our entry point
def root
Root.new(service: self)
end
## We use these to generate random-ish URLs
ALPHABET = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a
ALPHABET.shuffle!
def next_id
numid = urls.size + 1
id = ""
while numid > 0
numid, offset = numid.divmod(ALPHABET.size)
id << ALPHABET[offset]
end
id
end
end
## Setup a base class for all our Resources
class Resource < Tipi::Resource
parse_system <<-EOF
ShortURL = { id: String, url: String }
EOF
def service
state[:service]
end
end
## Entry point
class Root < Resource
input "{ url: String }"
output "ShortURL"
def create(data)
id = service.next_id
service.urls[id] = data[:url]
{ id: id, url: data[:url] }
end
def url(id)
url = state[:service].urls[id]
raise_not_found unless url
state[:id] = id
state[:url] = url
URL.new(state)
end
end
## A single URL. Instantiate this through Root#url
class URL < Resource
output "ShortURL"
def lookup
{ id: state[:id], url: state[:url] }
end
def redirect
redirect_response(state[:url])
end
end
## The router hooks everything up
ROUTER = Tipi::Router.new do
resource Root do
path '/urls/{id}', to: 'url', returns: URL
post '/urls', to: 'create'
end
resource URL do
get to: 'lookup'
get '/redirect', to: 'redirect'
end
end
end
require 'rack'
service = TeenyURL::Service.new
# Add a default URLs
p service.root.create(url: "http://ruby-lang.org/")
app = Tipi::Rack.new(service, TeenyURL::ROUTER)
Rack::Server.start(app: app, Port: 5678)