37b8bfccbc0060bc7ae0a273cfd4fb7836fd575e
[webvac] / config.ru
1 %w(
2         watts
3         webvac
4 ).each &method(:require)
5
6 Encoding.default_external = Encoding::BINARY
7
8 module WebVac
9         class R < Watts::Resource
10                 # This is a stupid feature.
11                 # Fortunes lifted shamelessly from http://quotes.cat-v.org/programming/
12                 Fortunes = <<-EOFORTUNES.gsub(/\t+/, '').split(/\n+/)
13                         There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
14                         When in doubt, use brute force.
15                         Deleted code is debugged code.
16                         Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
17                         The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.
18                         Controlling complexity is the essence of computer programming.
19                         UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things.
20                         Beware of those who say that their software does not suck, for they are either fools or liars.
21                         Unix is simple. It just takes a genius to understand its simplicity.
22                         If you want to go somewhere, goto is the best way to get there.
23                         I object to doing things that computers can do.
24                         A good way to have good ideas is by being unoriginal.
25                         a program is like a poem: you cannot write a poem without writing it.
26                 EOFORTUNES
27
28                 def headers t, path, score, contents
29                         name = (request.params['name'] || File.basename(path)).
30                                 gsub('"', "'")
31                         {
32                                 'Content-Disposition' => "filename=\"#{name}\"",
33                                 'Fortune' => Fortunes.sample,
34                         }.merge!(t.metadata(score) || {}).tap { |h|
35                                 if contents
36                                         h['Content-Type'] ||= t.guess_mime(contents) rescue nil
37                                         h['Content-Length'] ||= contents.bytesize.to_s
38                                 end
39                         }
40                 end
41         end
42
43         class Root < R
44                 auto_head
45                 get {
46                         "++++++++++++[>+++++++++<-]>.+++.---."
47                 }
48         end
49
50         class Serv < R
51                 # We can cheat a little with closures because there's just one "real"
52                 # endpoint.  No need to memoize.
53
54                 config = Config.load
55                 vac = Vac.new config
56                 tab = Table.new config
57
58                 head { |*|
59                         p = config.path_fixup(CGI.unescape(env['REQUEST_PATH']))
60                         s = tab.path2score p
61                         return [404, {}, ["404 Not found\nNo such path: #{p}\n"]] unless s
62                         [200, headers(tab, p, s, nil), []]
63                 }
64                 get { |*|
65                         p = config.path_fixup(CGI.unescape(env['REQUEST_PATH']))
66                         s = tab.path2score p
67                         return [404, {}, ["404 Not found\nNo such path: #{p}\n"]] unless s
68                         ct = Time.parse(env['HTTP_IF_MODIFIED_SINCE']) rescue nil
69                         if ct && ct.to_i > 0
70                                 hs = headers(tab, p, s, nil)
71                                 mt = Time.parse(hs['Last-Modified']) rescue nil
72                                 return [304, hs, []] if mt && mt > ct
73                         end
74                         contents = vac.load! s
75                         hs = headers(tab, p, s, contents)
76                         [200, headers(tab, p, s, contents), [contents]]
77                 }
78         end
79
80         class App < Watts::App
81                 resource('/', Root) {
82                         resource(:filename, Serv)
83                         resource(['media', :l1], Serv) { resource(:l2, Serv) }
84                 }
85         end
86 end
87
88 run WebVac::App.new