Allow applications to yield empty strings, and require middleware

to respect applications' block boundaries, so that asynchronous
applications can potentially pause their output while waiting for
(non-browser) I/O.  See these posts and the associated threads
for the discussion:

http://mail.python.org/pipermail/web-sig/2004-September/000868.html
http://mail.python.org/pipermail/web-sig/2004-September/000880.html
This commit is contained in:
Phillip J. Eby 2004-09-16 21:22:39 +00:00
parent 262383a208
commit 0611ed922e
1 changed files with 45 additions and 11 deletions

View File

@ -246,9 +246,10 @@ server.
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # force headers to be sent
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
result.close()
@ -579,10 +580,11 @@ such output, so that users who cannot fix a broken application are not
forced to bear the pain of its error.)
The ``start_response`` callable **must not** actually transmit the
HTTP headers. It must store them until the first ``write`` call,
or until after the first iteration of the application return value.
This is to ensure that buffered applications can replace their
originally intended output with error output, up until the last
HTTP headers. It must store them until the first ``write`` call that
is passed a non-empty string, or until after the first iteration of
the application return value that yields a non-empty string. This is
to ensure that buffered and asynchronous applications can replace
their originally intended output with error output, up until the last
possible moment.
The ``exc_info`` argument, if supplied, must be a Python
@ -690,11 +692,12 @@ fashion. These blocks may be broken to coincide with mulitpart
boundaries (for "server push"), or just before time-consuming
tasks (such as reading another block of an on-disk file).
WSGI servers and gateways **must not** delay the transmission
of any block; they **must** either fully transmit the block to
the client, or guarantee that they will continue transmission
even while the application is producing its next block. A
server/gateway may provide this guarantee in one of two ways:
WSGI servers, gateways, and middleware **must not** delay the
transmission of any block; they **must** either fully transmit
the block to the client, or guarantee that they will continue
transmission even while the application is producing its next block.
A server/gateway or middleware may provide this guarantee in one of
three ways:
1. Send the entire block to the operating system (and request
that any O/S buffers be flushed) before returning control
@ -704,6 +707,9 @@ server/gateway may provide this guarantee in one of two ways:
to be transmitted while the application produces the next
block.
3. (Middleware only) send the entire block to its parent
gateway/server
By providing this guarantee, WSGI allows applications to ensure
that transmission will not become stalled at an arbitrary point
in their output data. This is critical for proper functioning
@ -711,6 +717,34 @@ of e.g. multipart "server push" streaming, where data between
multipart boundaries should be transmitted in full to the client.
Middleware Handling of Block Boundaries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to better support asynchronous applications and servers,
middleware components **must not** block iteration waiting for
multiple values from an application iterable. If the middleware
needs to accumulate more data from the application before it can
produce any output, it **must** yield an empty string.
To put this requirement another way, a middleware component **must
yield at least one value** each time its underlying application
yields a value. If the middleware cannot yield any other value,
it must yield an empty string.
This requirement ensures that asynchronous applications and servers
can conspire to reduce the number of threads that are required
to run a given number of application instances simultaneously.
Note also that this requirement means that middleware **must**
return an iterable as soon as its underlying application returns
an iterable. It is also forbidden for middleware to use the
``write()`` callable to transmit data that is yielded by an
underlying application. Middleware may only use their parent
server's ``write()`` callable to transmit data that the
underlying application sent using a middleware-provided ``write()``
callable.
The ``write()`` Callable
~~~~~~~~~~~~~~~~~~~~~~~~