是否应该捕获HTTP参数问题的不可恢复的异常?

时间:2014-03-11 04:30:57

标签: django web-services http exception django-views

是否有必要捕获源自HTTP输入的错误?让它自然失败是不是一个好主意(允许异常冒泡)?

我有一个用于AJAX调用的服务器端接口的Django视图,如下所示:

def some_view(request):
    try:
        some_int = int(request.POST.get('some_int')) # May raise ValueError or TypeError
    except (ValueError, TypeError):
        return HttpResponseBadRequest('some_int must be an int')
    # ... Code that assumes some_int is an int
    return HttpResponse('The normal response')

生产代码中是否可以接受这样的内容?

def some_view(request):
    some_int = int(request.POST.get('some_int')) # Ignore ValueError or TypeError raised
    # ... Code that assumes some_int is an int
    return HttpResponse('normal_response')

当我接受更多参数时,我发现维持如此多的try / except块是很令人沮丧的,这些块大部分是相同的,我最终得到了大量的锅炉板代码。

当然我试着将它重构为一个单独的函数,但由于Django需要返回HttpResponse,而不是作为异常引发,我不能将它插入到没有try / except块的视图中。此外,转换为int并不是我检查的唯一内容...根据输入也执行了许多业务逻辑健全性检查。例如,我将验证传递的JSON是否为特定格式(即int数组的对象数组等)。

我的观点最终只有70多行代码用于完整性检查和几行实际生成响应的代码。不知何故,我觉得应该有一个更优雅的方式,但我没有找到一个所以我正在考虑放弃所有检查,只是让Django照顾它。 这是个坏主意吗?

如果我没有发现例外情况,我会发现以下潜在问题:

  1. 为所有错误返回相同的HTTP 500
  2. 如果在生产中启用了日志记录,则每次发生无效输入时都可能会记录错误
  3. 我还应该注意其他问题吗?即使在恢复逻辑方面我无能为力,也不会从用户输入中捕获异常,这是错误的。

1 个答案:

答案 0 :(得分:0)

我认为处理此问题的最佳方法是编写自己的middleware,捕获异常并将其转换为您想要的响应。

这可能看起来像这样:

# views.py
def some_view(request): 
    some_int = int(request.POST.get('some_int'))
    # ... Code that assumes some_int is an int
    return HttpResponse('normal_response')


# middleware.py
class MyValidationMiddleware(object):
    def process_exception(self, request, e):
        if isinstance(e, ValueError):
            return HttpResponseBadRequest('Input did not validate')
        else:
            return None  # let it bubble up

(由于中间件是站点范围的,您可能希望显式定义自己的输入验证异常,以区别于可能发生的其他类型的异常。)

或者,您可以使用每个视图装饰器执行相同的操作。