allow easier, single-file options for TC and TDB
[metropolis.git] / lib / metropolis / common.rb
blobd9cadba8c0d3d783c7aabc786d5079f95387de15
1 # -*- encoding: binary -*-
2 module Metropolis::Common
3   include Rack::Utils # unescape
4   autoload :RO, 'metropolis/common/ro'
6   def setup(opts)
7     @headers = { 'Content-Type' => 'application/octet-stream' }
8     @headers.merge!(opts[:response_headers] || {})
9     @nr_slots = opts[:nr_slots]
11     if @path_pattern
12       @nr_slots ||= 3
13       @uri.path == '/' or
14         raise ArgumentError, ":path_pattern may only be used if path is '/'"
15       @path_pattern.scan(/%\d*x/).size == 1 or
16         raise ArgumentError, "only one '/%\d*x/' may appear in #@path_pattern"
17     else
18       @nr_slots and
19         raise ArgumentError, ":nr_slots may be used with :path_pattern"
20     end
22     @readonly = !!opts[:readonly]
23     @exclusive = !!opts[:exclusive]
24     if @readonly && @exclusive
25       raise ArgumentError, ":readonly and :exclusive may not be used together"
26     end
27     case @encoding = opts[:encoding]
28     when nil
29     when :deflate
30       extend(Metropolis::Deflate)
31     when :gzip
32       extend(Metropolis::Gzip)
33     else
34       raise ArgumentError, "unsupported encoding"
35     end
36   end
38   def r(code, body = nil)
39     body ||= "#{HTTP_STATUS_CODES[code]}\n"
40     [ code,
41       { 'Content-Length' => body.size.to_s, 'Content-Type' => 'text/plain' },
42       [ body ] ]
43   end
45   def call(env)
46     if %r{\A/(.*)\z} =~ env["PATH_INFO"]
47       key = unescape($1)
48       case env["REQUEST_METHOD"]
49       when "GET"
50         get(key, env)
51       when "HEAD"
52         head(key, env)
53       when "DELETE"
54         delete(key)
55       when "PUT"
56         put(key, env)
57       else
58         r(405)
59       end
60     else # OPTIONS
61       r(405)
62     end
63   end
65   # generic HEAD implementation, some databases can optimize this by
66   # not retrieving the value
67   def head(key, env)
68     r = get(key, env)
69     r[2].clear
70     r
71   end
72 end