Better internal error pages.

This commit is contained in:
Aldo Cortesi 2012-04-28 14:43:57 +12:00
parent 2c8f17eae7
commit 5fc2a63781
5 changed files with 55 additions and 32 deletions

View File

@ -16,7 +16,6 @@ def application(**settings):
(r"/preview", handlers.Preview), (r"/preview", handlers.Preview),
(r"/p/.*", handlers.Pathod, settings), (r"/p/.*", handlers.Pathod, settings),
], ],
debug=True,
static_path = utils.data.path("static"), static_path = utils.data.path("static"),
template_path = utils.data.path("templates"), template_path = utils.data.path("templates"),
) )

View File

@ -36,9 +36,9 @@ class Pathod(object):
try: try:
self.response = rparse.parse(self.settings, spec) self.response = rparse.parse(self.settings, spec)
except rparse.ParseException, v: except rparse.ParseException, v:
self.response = rparse.StubResponse( self.response = rparse.InternalResponse(
800, 800,
"Error parsing response spec:" + str(v) "Error parsing response spec: %s\n"%v.msg + v.marked()
) )
def _execute(self, transforms, *args, **kwargs): def _execute(self, transforms, *args, **kwargs):

View File

@ -5,7 +5,17 @@ import tornado.ioloop
TESTING = False TESTING = False
class ParseException(Exception): pass class ParseException(Exception):
def __init__(self, msg, s, col):
Exception.__init__(self)
self.msg = msg
self.s = s
self.col = col
def marked(self):
return "%s\n%s"%(self.s, " "*(self.col-1) + "^")
class ServerError(Exception): pass class ServerError(Exception): pass
@ -304,19 +314,9 @@ class Response:
code = 200 code = 200
msg = LiteralGenerator(http.RESPONSES[code]) msg = LiteralGenerator(http.RESPONSES[code])
body = LiteralGenerator("OK") body = LiteralGenerator("OK")
def __init__(self, settings, tokens): def __init__(self):
self.tokens = tokens
self.headers = [] self.headers = []
self.pauses = [] self.pauses = []
for i in tokens:
i.mod_response(settings, self)
if self.body and not self.get_header("Content-Length"):
self.headers.append(
(
LiteralGenerator("Content-Length"),
LiteralGenerator(str(len(self.body))),
)
)
def get_header(self, hdr): def get_header(self, hdr):
for k, v in self.headers: for k, v in self.headers:
@ -393,6 +393,14 @@ class Response:
fp.finish() fp.finish()
def render(self, fp): def render(self, fp):
if self.body and not self.get_header("Content-Length"):
self.headers.append(
(
LiteralGenerator("Content-Length"),
LiteralGenerator(str(len(self.body))),
)
)
hdrs = [] hdrs = []
for k, v in self.headers: for k, v in self.headers:
hdrs.extend([ hdrs.extend([
@ -423,8 +431,17 @@ class Response:
return "\n".join(parts) return "\n".join(parts)
class StubResponse: class CraftedResponse(Response):
def __init__(self, settings, tokens):
Response.__init__(self)
self.tokens = tokens
for i in tokens:
i.mod_response(settings, self)
class InternalResponse(Response):
def __init__(self, code, body): def __init__(self, code, body):
Response.__init__(self)
self.code = code self.code = code
self.msg = LiteralGenerator(http.RESPONSES.get(code, "Unknown error")) self.msg = LiteralGenerator(http.RESPONSES.get(code, "Unknown error"))
self.body = LiteralGenerator(body) self.body = LiteralGenerator(body)
@ -442,6 +459,6 @@ class StubResponse:
def parse(settings, s): def parse(settings, s):
try: try:
return Response(settings, Response.expr().parseString(s, parseAll=True)) return CraftedResponse(settings, Response.expr().parseString(s, parseAll=True))
except pp.ParseException, v: except pp.ParseException, v:
raise ParseException(v) raise ParseException(v.msg, v.line, v.col)

View File

@ -4,6 +4,17 @@ from libpathod import rparse
rparse.TESTING = True rparse.TESTING = True
class DummyRequest(StringIO.StringIO):
def write(self, d, callback=None):
StringIO.StringIO.write(self, d)
if callback:
callback()
def finish(self):
return
class uMisc(libpry.AutoTree): class uMisc(libpry.AutoTree):
def test_generators(self): def test_generators(self):
v = rparse.Value.parseString("val")[0] v = rparse.Value.parseString("val")[0]
@ -130,8 +141,10 @@ class uMisc(libpry.AutoTree):
r = e.parseString('10')[0] r = e.parseString('10')[0]
assert r.msg.val == "Unknown code" assert r.msg.val == "Unknown code"
def test_stub_response(self): def test_internal_response(self):
s = rparse.StubResponse(400, "foo") d = DummyRequest()
s = rparse.InternalResponse(400, "foo")
s.render(d)
class uDisconnects(libpry.AutoTree): class uDisconnects(libpry.AutoTree):
@ -175,6 +188,10 @@ class uPauses(libpry.AutoTree):
class uparse(libpry.AutoTree): class uparse(libpry.AutoTree):
def test_parse_err(self): def test_parse_err(self):
libpry.raises(rparse.ParseException, rparse.parse, {}, "400:msg,b:") libpry.raises(rparse.ParseException, rparse.parse, {}, "400:msg,b:")
try:
rparse.parse({}, "400:msg,b:")
except rparse.ParseException, v:
print v.marked()
def test_parse_header(self): def test_parse_header(self):
r = rparse.parse({}, "400,h:foo:bar") r = rparse.parse({}, "400,h:foo:bar")
@ -193,16 +210,6 @@ class uparse(libpry.AutoTree):
assert ("random", 10) in r.pauses assert ("random", 10) in r.pauses
class DummyRequest(StringIO.StringIO):
def write(self, d, callback=None):
StringIO.StringIO.write(self, d)
if callback:
callback()
def finish(self):
return
class uResponse(libpry.AutoTree): class uResponse(libpry.AutoTree):
def dummy_response(self): def dummy_response(self):
return rparse.parse({}, "400:msg") return rparse.parse({}, "400:msg")

4
todo
View File

@ -1,6 +1,6 @@
- Files
- Shortcuts - Shortcuts
- HTTPS - HTTPS
- Sequences
- Anchors - Anchors
- Sequences