2 from twisted.web import http, server
3 from zope.interface import Interface
4 from nevow import loaders, appserver
5 from nevow.inevow import IRequest
6 from nevow.util import resource_filename
7 from allmydata.interfaces import ExistingChildError
9 class IClient(Interface):
14 return loaders.xmlfile(resource_filename('allmydata.web', '%s' % name))
16 def boolean_of_arg(arg):
18 assert arg.lower() in ("true", "t", "1", "false", "f", "0", "on", "off")
19 return arg.lower() in ("true", "t", "1", "on")
21 def get_arg(req, argname, default=None, multiple=False):
22 """Extract an argument from either the query args (req.args) or the form
23 body fields (req.fields). If multiple=False, this returns a single value
24 (or the default, which defaults to None), and the query args take
25 precedence. If multiple=True, this returns a tuple of arguments (possibly
26 empty), starting with all those in the query args.
29 if argname in req.args:
30 results.extend(req.args[argname])
31 if req.fields and argname in req.fields:
32 results.append(req.fields[argname].value)
39 def abbreviate_time(data):
47 return "%dms" % (1000*s)
49 return "%.1fms" % (1000*s)
50 return "%dus" % (1000000*s)
52 def abbreviate_rate(data):
53 # 21.8kBps, 554.4kBps 4.37MBps
58 return "%1.2fMBps" % (r/1000000)
60 return "%.1fkBps" % (r/1000)
63 def abbreviate_size(data):
64 # 21.8kB, 554.4kB 4.37MB
69 return "%1.2fGB" % (r/1000000000)
71 return "%1.2fMB" % (r/1000000)
73 return "%.1fkB" % (r/1000)
76 def text_plain(text, ctx):
78 req.setHeader("content-type", "text/plain")
79 req.setHeader("content-length", len(text))
82 class WebError(Exception):
83 def __init__(self, text, code=http.BAD_REQUEST):
87 # XXX: to make UnsupportedMethod return 501 NOT_IMPLEMENTED instead of 500
88 # Internal Server Error, we either need to do that ICanHandleException trick,
89 # or make sure that childFactory returns a WebErrorResource (and never an
90 # actual exception). The latter is growing increasingly annoying.
92 def should_create_intermediate_directories(req):
93 t = get_arg(req, "t", "").strip()
94 return bool(req.method in ("PUT", "POST") and
95 t not in ("delete", "rename", "rename-form", "check"))
98 class MyExceptionHandler(appserver.DefaultExceptionHandler):
99 def simple(self, ctx, text, code=http.BAD_REQUEST):
101 req.setResponseCode(code)
102 req.setHeader("content-type", "text/plain;charset=utf-8")
103 if isinstance(text, unicode):
104 text = text.encode("utf-8")
106 req.finishRequest(False)
108 def renderHTTP_exception(self, ctx, f):
109 if f.check(ExistingChildError):
110 return self.simple(ctx,
111 "There was already a child by that "
112 "name, and you asked me to not "
115 elif f.check(WebError):
116 return self.simple(ctx, f.value.text, f.value.code)
117 elif f.check(server.UnsupportedMethod):
118 # twisted.web.server.Request.render() has support for transforming
119 # this into an appropriate 501 NOT_IMPLEMENTED or 405 NOT_ALLOWED
120 # return code, but nevow does not.
123 return self.simple(ctx,
124 "I don't know how to treat a %s request." % method,
125 http.NOT_IMPLEMENTED)
126 super = appserver.DefaultExceptionHandler
127 return super.renderHTTP_exception(self, ctx, f)