如何正确拦截WSGI的start_response?

5 投票
2 回答
1221 浏览
提问于 2025-04-15 20:02

我有一个WSGI中间件,需要捕捉内部中间件通过调用start_response返回的HTTP状态(比如说200 OK)。目前我正在这样做,但我觉得用列表来解决这个问题不是最好的办法:

class TransactionalMiddlewareInterface(object):
    def __init__(self, application, **config):
        self.application = application
        self.config = config

    def __call__(self, environ, start_response):
        status = []

        def local_start(stat_str, headers=[]):
            status.append(int(stat_str.split(' ')[0]))
            return start_response(stat_str, headers)

        try:
            result = self.application(environ, local_start)

        finally:
            status = status[0] if status else 0

            if status > 199 and status 

之所以用列表,是因为我不能在一个完全封闭的函数里面直接给外面的变量赋值。

2 个回答

-1

只需要用一个简单的变量,并加上 nonlocal 这个关键词就可以了。

class TransactionalMiddlewareInterface(object):
    def __init__(self, application, **config):
        self.application = application
        self.config = config

    def __call__(self, environ, start_response):
        status = 0

        def local_start(stat_str, headers=[]):
            nonlocal status
            status = int(stat_str.split(' ')[0])
            return start_response(stat_str, headers)

        try:
            result = self.application(environ, local_start)

        finally:
            if status > 199 and status 
5

你可以把状态直接作为local_start函数的一个内部字段来使用,而不是用status这个列表。我用过类似的方法,效果很好:

class TransactionalMiddlewareInterface(object):
    def __init__(self, application, **config):
        self.application = application
        self.config = config

    def __call__(self, environ, start_response):
        def local_start(stat_str, headers=[]):
            local_start.status = int(stat_str.split(' ')[0])
            return start_response(stat_str, headers)
        try:
            result = self.application(environ, local_start)
        finally:
            if local_start.status and local_start.status > 199:
                pass

撰写回答