[Web-SIG] [extension] x-wsgiorg.flush

Thomas Broyer t.broyer at gmail.com
Mon Oct 8 19:49:06 CEST 2007


2007/10/8, Manlio Perillo:
> Phillip J. Eby ha scritto:
> > [...]
> >
> > I don't think there's any point to having a WSGI extension for If-*
> > header support.
>
> I have just found that the WSGI spec says:
> """...it should be clear that a server may handle cache validation via
> the If-None-Match and If-Modified-Since request headers and the
> Last-Modified and ETag response headers."""
>
>
> So a WSGI implementation is *allowed* to perform cache validation, but
> it is not clear *how* this should be done.
>
> As an example, without the need of an extension, the start_response
> callable may check if Last-Modified or ETag is in the headers.
> In this case, it may perform a cache validation, and if the client
> representation is fresh, it may omit to send the body.
>
> However there are two problems here:
> 1) It is not clear if WSGI explicitly allows an implementation to skip
>    the iteration over the app_iter object, for optimization purpose
> 2) For a WSGI implementation embedded in an existing webserver, the
>    most convenient method to perform cache validation is to let the
>    server do it; however this requires to send the headers as soon as
>    start_response is called, and this is not allowed.

How about (not tested, and simplified to require the app to return an
iterable, and without support for If-Range):

def has_precondition(environ):
     return "HTTP_IF_MATCH" in environ or
            "HTTP_IF_NONE_MATCH" in environ or
            "HTTP_IF_MODIFIED_SINCE" in environ or
            "HTTP_IF_UNMODIFIED_SINCE" in environ

def matches_preconditions(environ, headers):
    # TODO

def notmodifed_middleware(application):
    def middleware(environ, start_response):
        notmodified = [False]
        def sr(status, headers, exc_info=None):
            if status[0] == "2" and matches_preconditions(environ, headers):
                start_response("304 Not Modified", headers, exc_info)
                notmodified[0] = True
                return lambda s: raise NotSupportedError("The write
callback is deprecated")
            else:
               notmodified[0] = False
               return start_response(status, headers, exc_info)
        app_iter = application(environ,
            environ["wsgi.method"] == "GET" and
has_preconditions(environ) and sr or start_response)
        if notmodified[0]:
            return ("", )
        else:
            return app_iter
    return middleware


We're still waiting for the app to complete (and return its app_iter)
before sending anything to the client but this doesn't prevent us from
checking preconditions and in this case replace the status with a 304
Not Modified and an empty body (ignoring the app_iter all together;
but maybe we should iterate it to allow the wrapped application to
*really* complete its execution)

-- 
Thomas Broyer


More information about the Web-SIG mailing list