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:
parent
262383a208
commit
0611ed922e
54
pep-0333.txt
54
pep-0333.txt
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
Loading…
Reference in New Issue