On Mon, May 20, 2013 at 7:11 PM, Shannon Cruey <shannon.cr...@cloudsidekick.com> wrote: > I fiddled with that a lot to get it right, so my memory of the process is a > little hazy. Give it a try! >
I will. > My issue was that I needed handle_with_processors to *not* catch the > exceptions at all - because I wanted to do my own error handling end-to-end > by actually returning specific exception types and handling them. > Handle_with_processors was hijacking the exceptions. > If application processors were allowed to catch exceptions, would you still be in need of subclassing web.Application? Probably not, you could simply chain a custom processor with a custom try-catch and everything should work like a charm. (Please, correct me if I am wrong) Matteo > I'd suggest the best case for usability would be that handle_with_processors > not have a try block, and leave it up to a higher level wrapper to handle > them appropriately. However, I didn't dig deep enough into web.py to see if > there's a reason it's done like that, and my overload is working just fine. > > > On Mon, May 20, 2013 at 12:50 PM, Matteo Landi <mat...@matteolandi.net> > wrote: >> >> On Sun, May 19, 2013 at 6:19 PM, Shannon Cruey >> <shannon.cr...@cloudsidekick.com> wrote: >> > The problem is the processor function in the application.py module has a >> > try >> > block in it, so it's redirecting to the internal error handler. I have >> >> I am looking at the code of the method ``handle_with_processors`` of >> the application module: am I wrong saying that the try-catch block >> could be safely moved out of the ``process`` function and put around >> the line containing ``return process(self.processors)``? This way >> processors will be able to handle certain kind of exceptions and still >> propagate unhandled ones to the framework (to enable default exception >> management). >> >> What do you think about that? If you don't see any issue I can >> provide a pull request with these changes. >> >> >> Regards, >> >> Matteo >> >> > successfully overloaded this function in my main module and am able to >> > return different status codes as I like. Here's what I did in my main >> > code: >> > (You can see the entire file at >> > >> > app = ExceptionHandlingApplication(urls, globals(), autoreload=True) >> > >> > >> > Then here's that class: >> > >> > class ExceptionHandlingApplication(web.application): >> > >> > """ >> > >> > This is an overload of the standard web.application class. >> > >> > Main reason? In application.py, the 'handle_with_processors' >> > function >> > >> > converts *any* exception into the generic web.py _InternalError. >> > >> > >> > >> > This interferes, because we wanna trap the original error an make >> > determinations >> > >> > on how to reply to the client. >> > >> > >> > >> > So, we overloaded the function and fixed the error handing. >> > >> > """ >> > >> > def handle_with_processors(self): >> > >> > def process(processors): >> > >> > try: >> > >> > if processors: >> > >> > p, processors = processors[0], processors[1:] >> > >> > return p(lambda: process(processors)) >> > >> > else: >> > >> > return self.handle() >> > >> > except (web.HTTPError, KeyboardInterrupt, SystemExit): >> > >> > raise >> > >> > except InfoException as ex: >> > >> > # I use a custom HTTP status code to indicate >> > 'information' >> > back to the user. >> > >> > web.ctx.status = "280 Informational Response" >> > >> > logger.exception(ex.__str__()) >> > >> > return ex.__str__() >> > >> > except SessionError as ex: >> > >> > logger.exception(ex.__str__()) >> > >> > # now, all our ajax calls are from jQuery, which sets a >> > header - X-Requested-With >> > >> > # so if we have that header, it's ajax, otherwise we can >> > redirect to the login page. >> > >> > >> > >> > # a session error means we kill the session >> > >> > session.kill() >> > >> > >> > >> > if web.ctx.env.get("HTTP_X_REQUESTED_WITH") == >> > "XMLHttpRequest": >> > >> > web.ctx.status = "480 Session Error" >> > >> > return ex.__str__() >> > >> > else: >> > >> > logger.debug("Standard Request - redirecting to the >> > login page...") >> > >> > raise web.seeother('/static/login.html') >> > >> > except Exception as ex: >> > >> > # web.ctx.env.get('HTTP_X_REQUESTED_WITH') >> > >> > web.ctx.status = "400 Bad Request" >> > >> > logger.exception(ex.__str__()) >> > >> > return ex.__str__() >> > >> > >> > >> > return process(self.processors) >> > >> > >> > >> > On Sun, May 19, 2013 at 6:46 AM, Matteo Landi <mat...@matteolandi.net> >> > wrote: >> >> >> >> Hi there, >> >> >> >> What is the best way to manage certain type of exceptions so that they >> >> don't produce a '500 Internal Error' HTTP status? >> >> >> >> First I thought about request decorators but then I realized that >> >> decorating *each* request seem to be a bit overkill. Then I thought >> >> about application decorators: the documentation even contains an >> >> example where a try-except block is put within an handler. So I come >> >> up with the following handler: >> >> >> >> def manage_content_exceptions(handler): >> >> web.ctx.logger.info("before_manage") >> >> try: >> >> return handler() >> >> except app.exceptions.ResponseContent as r: >> >> return r.content >> >> finally: >> >> web.ctx.logger.info("after_manage") >> >> >> >> What happens here is that the finally block is never executed and >> >> consequently the exception is caught by the application and an >> >> internal error is sent back to the client. >> >> >> >> Could you please shed some light on the subject and tell me what's >> >> wrong with my handler? I even found another discussion [1] about same >> >> issue but unfortunately it is unanswered. >> >> >> >> >> >> Regards, >> >> >> >> Matteo >> >> >> >> [1] https://groups.google.com/d/msg/webpy/f7IBxCgvIoY/GQxeHKVw8pcJ >> >> >> >> -- >> >> You received this message because you are subscribed to the Google >> >> Groups >> >> "web.py" group. >> >> To unsubscribe from this group and stop receiving emails from it, send >> >> an >> >> email to webpy+unsubscr...@googlegroups.com. >> >> To post to this group, send email to webpy@googlegroups.com. >> >> Visit this group at http://groups.google.com/group/webpy?hl=en. >> >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> >> >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups >> > "web.py" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to webpy+unsubscr...@googlegroups.com. >> > To post to this group, send email to webpy@googlegroups.com. >> > Visit this group at http://groups.google.com/group/webpy?hl=en. >> > For more options, visit https://groups.google.com/groups/opt_out. >> > >> > >> >> -- >> You received this message because you are subscribed to the Google Groups >> "web.py" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to webpy+unsubscr...@googlegroups.com. >> To post to this group, send email to webpy@googlegroups.com. >> Visit this group at http://groups.google.com/group/webpy?hl=en. >> For more options, visit https://groups.google.com/groups/opt_out. >> >> > > -- > You received this message because you are subscribed to the Google Groups > "web.py" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to webpy+unsubscr...@googlegroups.com. > To post to this group, send email to webpy@googlegroups.com. > Visit this group at http://groups.google.com/group/webpy?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > -- You received this message because you are subscribed to the Google Groups "web.py" group. To unsubscribe from this group and stop receiving emails from it, send an email to webpy+unsubscr...@googlegroups.com. To post to this group, send email to webpy@googlegroups.com. Visit this group at http://groups.google.com/group/webpy?hl=en. For more options, visit https://groups.google.com/groups/opt_out.