Issue #186 resolved

exceptions can't escape CP and up into WSGI middleware

Anonymous created an issue

I'm trying to get exceptions in CP to propagate up into WSGI middleware, but they are caught in _cphttptools.handleError eventually with no way to escape.

Reported by John Speno

Comments (13)

  1. Robert Brewer

    I think the only way to do this would be to remove error handling from the CP core completely, and move it to WSGI middleware. Anyone want to take a crack at it? Or is there one somewhere else we should use (e.g. Paste)?

  2. Anonymous

    Paste has paste.errormiddleware, which is what I was trying to use when I discovered this issue. Does the wsgi pep discuss what should be done with exceptions in the application?

  3. Robert Brewer

    From PEP 333:

    "In general, applications should try to trap their own, internal errors, and display a helpful message in the browser. (It is up to the application to decide what "helpful" means in this context.)"

    That's the approach I followed in _cpwsgi. If followed strictly, the only errors that paste should receive and handle would be errors in paste itself, or in WSGI middleware between CP and paste (but not between paste and the server). In other words, sticking paste.errormiddleware between _cpwsgi and _cpwsgiserver doesn't buy you anything unless you have other middleware.

  4. anonymous

    Well, in WSGI, the middleware is also defined as the "application", isn't it? :-)

    I think you could make a case either way, but for maximum utility and ease of set up, CP should have a way to let exceptions escape itself so that something like paste.errormiddleware could handle them.

    How about a global config option that allows that? Put the check in the except clause of handleError and if set, just re raise the exception? You'd still have to raise the exception in _cpOnError though unless this setting also affected that.

  5. Anonymous

    Personally I disagree with the PEP here, though since it's just a suggestion in the PEP it doesn't matter too much.

    If the Paste error middleware is installed, the WSGI environment will have a "paste.throw_errors" key in it (that will be true). This should signal that there is an error handler already installed, and ''unexpected'' exceptions should not be caught. (Expected exceptions can always be caught, of course, like a redirect exception.) I also use this in tests, where I want the exception to go up to the test runner.

    So, a special case for that key, that re-raises the exception, would do it. I would like this to actually be a "wsgi.throw_errors" key, i.e., a standard way of saying that unexpected errors shouldn't be caught. I've brought it up on Web-SIG -- there weren't any objections, but also no interest. If CherryPy people want to bring it up too, we could probably make this generally standard.

    For exceptions, there's a little-known property of "raise", that you can pass it three arguments, that are the values that sys.exc_info() returns. This preserves the traceback. This might be useful during implementation.

  6. Robert Brewer

    The current dilemma with this: you have to tell both the CherryPy request (_cphttptools) and the wsgi interface (_cpwsgi) that you want to re-raise trapped errors. The first should probably inspect a CP config entry, but the second should respect a "wsgi.throw_errors" entry. However, requiring both seems a bit cumbersome.

  7. Robert Brewer

    The CP config key "server.throw_wsgi_errors" could be "never", "always", or "on request", where "on request" means, "throw it if the wsgi environ has paste.throw_errors or wsgi.throw_errors".

  8. Log in to comment