Add a space after comma and remove trailing spaces.

This commit is contained in:
Florent Xicluna 2010-08-28 17:49:32 +00:00
parent 2fc8df834e
commit c29c921482
1 changed files with 141 additions and 140 deletions

View File

@ -167,7 +167,7 @@ other is a class::
def simple_app(environ, start_response):
"""Simplest possible application object"""
status = '200 OK'
response_headers = [('Content-type','text/plain')]
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return ['Hello world!\n']
@ -179,7 +179,7 @@ other is a class::
returns an instance of 'AppClass', which is then the iterable
return value of the "application callable" as required by
the spec.
If we wanted to use *instances* of 'AppClass' as application
objects instead, we would have to implement a '__call__'
method, which would be invoked to execute the application,
@ -193,7 +193,7 @@ other is a class::
def __iter__(self):
status = '200 OK'
response_headers = [('Content-type','text/plain')]
response_headers = [('Content-type', 'text/plain')]
self.start(status, response_headers)
yield "Hello world!\n"
@ -204,9 +204,9 @@ The Server/Gateway Side
The server or gateway invokes the application callable once for each
request it receives from an HTTP client, that is directed at the
application. To illustrate, here is a simple CGI gateway, implemented
as a function taking an application object. Note that this simple
example has limited error handling, because by default an uncaught
exception will be dumped to ``sys.stderr`` and logged by the web
as a function taking an application object. Note that this simple
example has limited error handling, because by default an uncaught
exception will be dumped to ``sys.stderr`` and logged by the web
server.
::
@ -218,12 +218,12 @@ server.
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr
environ['wsgi.version'] = (1,0)
environ['wsgi.version'] = (1, 0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS','off') in ('on','1'):
if environ.get('HTTPS', 'off') in ('on', '1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
@ -246,7 +246,7 @@ server.
sys.stdout.write(data)
sys.stdout.flush()
def start_response(status,response_headers,exc_info=None):
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
@ -256,8 +256,8 @@ server.
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status,response_headers]
headers_set[:] = [status, response_headers]
return write
result = application(environ, start_response)
@ -268,7 +268,7 @@ server.
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
if hasattr(result, 'close'):
result.close()
@ -294,13 +294,13 @@ such functions as:
The presence of middleware in general is transparent to both the
"server/gateway" and the "application/framework" sides of the
interface, and should require no special support. A user who
desires to incorporate middleware into an application simply
provides the middleware component to the server, as if it were
desires to incorporate middleware into an application simply
provides the middleware component to the server, as if it were
an application, and configures the middleware component to
invoke the application, as if the middleware component were a
server. Of course, the "application" that the middleware wraps
may in fact be another middleware component wrapping another
application, and so on, creating what is referred to as a
application, and so on, creating what is referred to as a
"middleware stack".
For the most part, middleware must conform to the restrictions
@ -311,7 +311,7 @@ and these points will be noted in the specification.
Here is a (tongue-in-cheek) example of a middleware component that
converts ``text/plain`` responses to pig latin, using Joe Strout's
``piglatin.py``. (Note: a "real" middleware component would
``piglatin.py``. (Note: a "real" middleware component would
probably use a more robust way of checking the content type, and
should also check for a content encoding. Also, this simple
example ignores the possibility that a word might be split across
@ -320,17 +320,18 @@ a block boundary.)
::
from piglatin import piglatin
class LatinIter:
"""Transform iterated output to piglatin, if it's okay to do so
Note that the "okayness" can change until the application yields
its first non-empty string, so 'transform_ok' has to be a mutable
truth value."""
truth value.
"""
def __init__(self,result,transform_ok):
if hasattr(result,'close'):
def __init__(self, result, transform_ok):
if hasattr(result, 'close'):
self.close = result.close
self._next = iter(result).next
self.transform_ok = transform_ok
@ -347,31 +348,31 @@ a block boundary.)
class Latinator:
# by default, don't transform output
transform = False
transform = False
def __init__(self, application):
self.application = application
def __call__(self, environ, start_response):
transform_ok = []
def start_latin(status,response_headers,exc_info=None):
def start_latin(status, response_headers, exc_info=None):
# Reset ok flag, in case this is a repeat call
transform_ok[:]=[]
transform_ok[:] = []
for name,value in response_headers:
if name.lower()=='content-type' and value=='text/plain':
for name, value in response_headers:
if name.lower() == 'content-type' and value == 'text/plain':
transform_ok.append(True)
# Strip content-length if present, else it'll be wrong
response_headers = [(name,value)
for name,value in response_headers
if name.lower()<>'content-length'
response_headers = [(name, value)
for name, value in response_headers
if name.lower() <> 'content-length'
]
break
write = start_response(status,response_headers,exc_info)
write = start_response(status, response_headers, exc_info)
if transform_ok:
def write_latin(data):
@ -380,7 +381,7 @@ a block boundary.)
else:
return write
return LatinIter(self.application(environ,start_latin),transform_ok)
return LatinIter(self.application(environ, start_latin), transform_ok)
# Run foo_app under a Latinator's control, using the example CGI gateway
@ -397,7 +398,7 @@ the sake of illustration, we have named them ``environ`` and
``start_response``, but they are not required to have these names.
A server or gateway **must** invoke the application object using
positional (not keyword) arguments. (E.g. by calling
``result = application(environ,start_response)`` as shown above.)
``result = application(environ, start_response)`` as shown above.)
The ``environ`` parameter is a dictionary object, containing CGI-style
environment variables. This object **must** be a builtin Python
@ -414,25 +415,25 @@ of illustration, we have named these arguments ``status``,
``response_headers``, and ``exc_info``, but they are not required to
have these names, and the application **must** invoke the
``start_response`` callable using positional arguments (e.g.
``start_response(status,response_headers)``).
``start_response(status, response_headers)``).
The ``status`` parameter is a status string of the form
``"999 Message here"``, and ``response_headers`` is a list of
``(header_name,header_value)`` tuples describing the HTTP response
``"999 Message here"``, and ``response_headers`` is a list of
``(header_name, header_value)`` tuples describing the HTTP response
header. The optional ``exc_info`` parameter is described below in the
sections on `The start_response() Callable`_ and `Error Handling`_.
It is used only when the application has trapped an error and is
attempting to display an error message to the browser.
The ``start_response`` callable must return a ``write(body_data)``
callable that takes one positional parameter: a string to be written
callable that takes one positional parameter: a string to be written
as part of the HTTP response body. (Note: the ``write()`` callable is
provided only to support certain existing frameworks' imperative output
APIs; it should not be used by new applications or frameworks if it
can be avoided. See the `Buffering and Streaming`_ section for more
details.)
When called by the server, the application object must return an
When called by the server, the application object must return an
iterable yielding zero or more strings. This can be accomplished in a
variety of ways, such as by returning a list of strings, or by the
application being a generator function that yields strings, or
@ -440,10 +441,10 @@ by the application being a class whose instances are iterable.
Regardless of how it is accomplished, the application object must
always return an iterable yielding zero or more strings.
The server or gateway must transmit the yielded strings to the client
in an unbuffered fashion, completing the transmission of each string
The server or gateway must transmit the yielded strings to the client
in an unbuffered fashion, completing the transmission of each string
before requesting another one. (In other words, applications
**should** perform their own buffering. See the `Buffering and
**should** perform their own buffering. See the `Buffering and
Streaming`_ section below for more on how application output must be
handled.)
@ -456,21 +457,21 @@ other transformations for the purpose of implementing HTTP features
such as byte-range transmission. See `Other HTTP Features`_, below,
for more details.)
If a call to ``len(iterable)`` succeeds, the server must be able
to rely on the result being accurate. That is, if the iterable
returned by the application provides a working ``__len__()``
If a call to ``len(iterable)`` succeeds, the server must be able
to rely on the result being accurate. That is, if the iterable
returned by the application provides a working ``__len__()``
method, it **must** return an accurate result. (See
the `Handling the Content-Length Header`_ section for information
on how this would normally be used.)
If the iterable returned by the application has a ``close()`` method,
the server or gateway **must** call that method upon completion of the
current request, whether the request was completed normally, or
current request, whether the request was completed normally, or
terminated early due to an error. (This is to support resource release
by the application. This protocol is intended to complement PEP 325's
generator support, and other common iterables with ``close()`` methods.
(Note: the application **must** invoke the ``start_response()``
(Note: the application **must** invoke the ``start_response()``
callable before the iterable yields its first body string, so that the
server can send the headers before any body content. However, this
invocation **may** be performed by the iterable's first iteration, so
@ -480,8 +481,8 @@ before they begin iterating over the iterable.)
Finally, servers and gateways **must not** directly use any other
attributes of the iterable returned by the application, unless it is an
instance of a type specific to that server or gateway, such as a "file
wrapper" returned by ``wsgi.file_wrapper`` (see `Optional
Platform-Specific File Handling`_). In the general case, only
wrapper" returned by ``wsgi.file_wrapper`` (see `Optional
Platform-Specific File Handling`_). In the general case, only
attributes specified here, or accessed via e.g. the PEP 234 iteration
APIs are acceptable.
@ -496,19 +497,19 @@ unless their value would be an empty string, in which case they
**may** be omitted, except as otherwise noted below.
``REQUEST_METHOD``
The HTTP request method, such as ``"GET"`` or ``"POST"``. This
The HTTP request method, such as ``"GET"`` or ``"POST"``. This
cannot ever be an empty string, and so is always required.
``SCRIPT_NAME``
``SCRIPT_NAME``
The initial portion of the request URL's "path" that corresponds to
the application object, so that the application knows its virtual
the application object, so that the application knows its virtual
"location". This **may** be an empty string, if the application
corresponds to the "root" of the server.
corresponds to the "root" of the server.
``PATH_INFO``
The remainder of the request URL's "path", designating the virtual
The remainder of the request URL's "path", designating the virtual
"location" of the request's target within the application. This
**may** be an empty string, if the request URL targets the
**may** be an empty string, if the request URL targets the
application root and does not have a trailing slash.
``QUERY_STRING``
@ -547,7 +548,7 @@ unless their value would be an empty string, in which case they
absence of these variables should correspond with the presence or
absence of the appropriate HTTP header in the request.
A server or gateway **should** attempt to provide as many other CGI
A server or gateway **should** attempt to provide as many other CGI
variables as are applicable. In addition, if SSL is in use, the server
or gateway **should** also provide as many of the Apache SSL environment
variables [5]_ as are applicable, such as ``HTTPS=on`` and
@ -559,7 +560,7 @@ provide a meaningful ``DOCUMENT_ROOT`` or ``PATH_TRANSLATED``.)
A WSGI-compliant server or gateway **should** document what variables
it provides, along with their definitions as appropriate. Applications
**should** check for the presence of any variables they require, and
**should** check for the presence of any variables they require, and
have a fallback plan in the event such a variable is absent.
Note: missing variables (such as ``REMOTE_USER`` when no
@ -575,24 +576,24 @@ and **must** contain the following WSGI-defined variables:
===================== ===============================================
Variable Value
===================== ===============================================
``wsgi.version`` The tuple ``(1,0)``, representing WSGI
``wsgi.version`` The tuple ``(1, 0)``, representing WSGI
version 1.0.
``wsgi.url_scheme`` A string representing the "scheme" portion of
the URL at which the application is being
the URL at which the application is being
invoked. Normally, this will have the value
``"http"`` or ``"https"``, as appropriate.
``wsgi.input`` An input stream (file-like object) from which
the HTTP request body can be read. (The server
or gateway may perform reads on-demand as
or gateway may perform reads on-demand as
requested by the application, or it may pre-
read the client's request body and buffer it
in-memory or on disk, or use any other
technique for providing such an input stream,
according to its preference.)
``wsgi.errors`` An output stream (file-like object) to which
``wsgi.errors`` An output stream (file-like object) to which
error output can be written, for the purpose of
recording program or other errors in a
standardized and possibly centralized location.
@ -610,13 +611,13 @@ Variable Value
or gateway may supply different error streams
to different applications, if this is desired.
``wsgi.multithread`` This value should evaluate true if the
``wsgi.multithread`` This value should evaluate true if the
application object may be simultaneously
invoked by another thread in the same process,
and should evaluate false otherwise.
``wsgi.multiprocess`` This value should evaluate true if an
equivalent application object may be
``wsgi.multiprocess`` This value should evaluate true if an
equivalent application object may be
simultaneously invoked by another process,
and should evaluate false otherwise.
@ -646,8 +647,8 @@ the following methods:
Method Stream Notes
=================== ========== ========
``read(size)`` ``input`` 1
``readline()`` ``input`` 1,2
``readlines(hint)`` ``input`` 1,3
``readline()`` ``input`` 1, 2
``readlines(hint)`` ``input`` 1, 3
``__iter__()`` ``input``
``flush()`` ``errors`` 4
``write(str)`` ``errors``
@ -692,16 +693,16 @@ The ``start_response()`` Callable
---------------------------------
The second parameter passed to the application object is a callable
of the form ``start_response(status,response_headers,exc_info=None)``.
of the form ``start_response(status, response_headers, exc_info=None)``.
(As with all WSGI callables, the arguments must be supplied
positionally, not by keyword.) The ``start_response`` callable is
used to begin the HTTP response, and it must return a
``write(body_data)`` callable (see the `Buffering and Streaming`_
``write(body_data)`` callable (see the `Buffering and Streaming`_
section, below).
The ``status`` argument is an HTTP "status" string like ``"200 OK"``
or ``"404 Not Found"``. That is, it is a string consisting of a
Status-Code and a Reason-Phrase, in that order and separated by a
or ``"404 Not Found"``. That is, it is a string consisting of a
Status-Code and a Reason-Phrase, in that order and separated by a
single space, with no surrounding whitespace or other characters.
(See RFC 2616, Section 6.1.1 for more information.) The string
**must not** contain control characters, and must not be terminated
@ -733,11 +734,11 @@ examining application-supplied headers!)
Applications and middleware are forbidden from using HTTP/1.1
"hop-by-hop" features or headers, any equivalent features in HTTP/1.0,
or any headers that would affect the persistence of the client's
or any headers that would affect the persistence of the client's
connection to the web server. These features are the
exclusive province of the actual web server, and a server or gateway
**should** consider it a fatal error for an application to attempt
sending them, and raise an error if they are supplied to
sending them, and raise an error if they are supplied to
``start_response()``. (For more specifics on "hop-by-hop" features and
headers, please see the `Other HTTP Features`_ section below.)
@ -748,7 +749,7 @@ application return value that yields a non-empty string, or upon
the application's first invocation of the ``write()`` callable. In
other words, response headers must not be sent until there is actual
body data available, or until the application's returned iterable is
exhausted. (The only possible exception to this rule is if the
exhausted. (The only possible exception to this rule is if the
response headers explicitly include a ``Content-Length`` of zero.)
This delaying of response header transmission is to ensure that buffered
@ -771,13 +772,13 @@ However, if ``exc_info`` is provided, and the HTTP headers have already
been sent, ``start_response`` **must** raise an error, and **should**
raise the ``exc_info`` tuple. That is::
raise exc_info[0],exc_info[1],exc_info[2]
raise exc_info[0], exc_info[1], exc_info[2]
This will re-raise the exception trapped by the application, and in
principle should abort the application. (It is not safe for the
principle should abort the application. (It is not safe for the
application to attempt error output to the browser once the HTTP
headers have already been sent.) The application **must not** trap
any exceptions raised by ``start_response``, if it called
any exceptions raised by ``start_response``, if it called
``start_response`` with ``exc_info``. Instead, it should allow
such exceptions to propagate back to the server or gateway. See
`Error Handling`_ below, for more details.
@ -790,12 +791,12 @@ current invocation of the application. (See the example CGI
gateway above for an illustration of the correct logic.)
Note: servers, gateways, or middleware implementing ``start_response``
**should** ensure that no reference is held to the ``exc_info``
**should** ensure that no reference is held to the ``exc_info``
parameter beyond the duration of the function's execution, to avoid
creating a circular reference through the traceback and frames
involved. The simplest way to do this is something like::
def start_response(status,response_headers,exc_info=None):
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
# do stuff w/exc_info here
@ -833,7 +834,7 @@ dealing with the absence of ``Content-Length``.
(Note: applications and middleware **must not** apply any kind of
``Transfer-Encoding`` to their output, such as chunking or gzipping;
as "hop-by-hop" operations, these encodings are the province of the
as "hop-by-hop" operations, these encodings are the province of the
actual web server/gateway. See `Other HTTP Features`_ below, for
more details.)
@ -842,7 +843,7 @@ Buffering and Streaming
-----------------------
Generally speaking, applications will achieve the best throughput
by buffering their (modestly-sized) output and sending it all at
by buffering their (modestly-sized) output and sending it all at
once. This is a common approach in existing frameworks such as
Zope: the output is buffered in a StringIO or similar object, then
transmitted all at once, along with the response headers.
@ -850,37 +851,37 @@ transmitted all at once, along with the response headers.
The corresponding approach in WSGI is for the application to simply
return a single-element iterable (such as a list) containing the
response body as a single string. This is the recommended approach
for the vast majority of application functions, that render
for the vast majority of application functions, that render
HTML pages whose text easily fits in memory.
For large files, however, or for specialized uses of HTTP streaming
(such as multipart "server push"), an application may need to provide
output in smaller blocks (e.g. to avoid loading a large file into
output in smaller blocks (e.g. to avoid loading a large file into
memory). It's also sometimes the case that part of a response may
be time-consuming to produce, but it would be useful to send ahead the
portion of the response that precedes it.
In these cases, applications will usually return an iterator (often
a generator-iterator) that produces the output in a block-by-block
fashion. These blocks may be broken to coincide with mulitpart
boundaries (for "server push"), or just before time-consuming
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, gateways, and middleware **must not** delay the
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
1. Send the entire block to the operating system (and request
that any O/S buffers be flushed) before returning control
to the application, OR
2. Use a different thread to ensure that the block continues
to be transmitted while the application produces the next
block.
3. (Middleware only) send the entire block to its parent
gateway/server
@ -901,7 +902,7 @@ 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
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.
@ -914,7 +915,7 @@ 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
server's ``write()`` callable to transmit data that the
underlying application sent using a middleware-provided ``write()``
callable.
@ -936,7 +937,7 @@ Therefore, to allow these frameworks to continue using an
imperative API, WSGI includes a special ``write()`` callable,
returned by the ``start_response`` callable.
New WSGI applications and frameworks **should not** use the
New WSGI applications and frameworks **should not** use the
``write()`` callable if it is possible to avoid doing so. The
``write()`` callable is strictly a hack to support imperative
streaming APIs. In general, applications should produce their
@ -956,7 +957,7 @@ proceeds onward.
An application **must** return an iterable object, even if it
uses ``write()`` to produce all or part of its response body.
The returned iterable **may** be empty (i.e. yield no non-empty
strings), but if it *does* yield non-empty strings, that output
strings), but if it *does* yield non-empty strings, that output
must be treated normally by the server or gateway (i.e., it must be
sent or queued immediately). Applications **must not** invoke
``write()`` from within their return iterable, and therefore any
@ -970,7 +971,7 @@ Unicode Issues
HTTP does not directly support Unicode, and neither does this
interface. All encoding/decoding must be handled by the application;
all strings passed to or from the server must be standard Python byte
strings, not Unicode objects. The result of using a Unicode object
strings, not Unicode objects. The result of using a Unicode object
where a string object is required, is undefined.
Note also that strings passed to ``start_response()`` as a status or
@ -980,9 +981,9 @@ MIME encoding.
On Python platforms where the ``str`` or ``StringType`` type is in
fact Unicode-based (e.g. Jython, IronPython, Python 3000, etc.), all
"strings" referred to in this specification must contain only
"strings" referred to in this specification must contain only
code points representable in ISO-8859-1 encoding (``\u0000`` through
``\u00FF``, inclusive). It is a fatal error for an application to
``\u00FF``, inclusive). It is a fatal error for an application to
supply strings containing any other Unicode character or code point.
Similarly, servers and gateways **must not** supply
strings to an application containing any other Unicode characters.
@ -1012,33 +1013,33 @@ of its use::
try:
# regular application code here
status = "200 Froody"
response_headers = [("content-type","text/plain")]
response_headers = [("content-type", "text/plain")]
start_response(status, response_headers)
return ["normal body goes here"]
return ["normal body goes here"]
except:
# XXX should trap runtime issues like MemoryError, KeyboardInterrupt
# in a separate handler before this bare 'except:'...
status = "500 Oops"
response_headers = [("content-type","text/plain")]
response_headers = [("content-type", "text/plain")]
start_response(status, response_headers, sys.exc_info())
return ["error body goes here"]
If no output has been written when an exception occurs, the call to
``start_response`` will return normally, and the application will
``start_response`` will return normally, and the application will
return an error body to be sent to the browser. However, if any output
has already been sent to the browser, ``start_response`` will reraise
the provided exception. This exception **should not** be trapped by
has already been sent to the browser, ``start_response`` will reraise
the provided exception. This exception **should not** be trapped by
the application, and so the application will abort. The server or
gateway can then trap this (fatal) exception and abort the response.
Servers **should** trap and log any exception that aborts an
application or the iteration of its return value. If a partial
Servers **should** trap and log any exception that aborts an
application or the iteration of its return value. If a partial
response has already been written to the browser when an application
error occurs, the server or gateway **may** attempt to add an error
message to the output, if the already-sent headers indicate a
``text/*`` content type that the server knows how to modify cleanly.
Some middleware may wish to provide additional exception handling
Some middleware may wish to provide additional exception handling
services, or intercept and replace application error messages. In
such cases, middleware may choose to **not** re-raise the ``exc_info``
supplied to ``start_response``, but instead raise a middleware-specific
@ -1057,7 +1058,7 @@ long as application authors:
HTTP 1.1 Expect/Continue
------------------------
Servers and gateways that implement HTTP 1.1 **must** provide
Servers and gateways that implement HTTP 1.1 **must** provide
transparent support for HTTP 1.1's "expect/continue" mechanism. This
may be done in any of several ways:
@ -1069,7 +1070,7 @@ may be done in any of several ways:
response if/when the application first attempts to read from the
input stream. The read request must then remain blocked until the
client responds.
3. Wait until the client decides that the server does not support
expect/continue, and sends the request body on its own. (This
is suboptimal, and is not recommended.)
@ -1093,7 +1094,7 @@ a server should consider itself to be like an HTTP "gateway server",
with the application being an HTTP "origin server". (See RFC 2616,
section 1.3, for the definition of these terms.)
However, because WSGI servers and applications do not communicate via
However, because WSGI servers and applications do not communicate via
HTTP, what RFC 2616 calls "hop-by-hop" headers do not apply to WSGI
internal communications. WSGI applications **must not** generate any
"hop-by-hop" headers [4]_, attempt to use HTTP features that would
@ -1103,7 +1104,7 @@ WSGI servers **must** handle any supported inbound "hop-by-hop" headers
on their own, such as by decoding any inbound ``Transfer-Encoding``,
including chunked encoding if applicable.
Applying these principles to a variety of HTTP features, it should be
Applying these principles to a variety of HTTP features, 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. However, it is
@ -1113,9 +1114,9 @@ the server/gateway is not required to do such validation.
Similarly, a server **may** re-encode or transport-encode an
application's response, but the application **should** use a
suitable content encoding on its own, and **must not** apply a
suitable content encoding on its own, and **must not** apply a
transport encoding. A server **may** transmit byte ranges of the
application's response if requested by the client, and the
application's response if requested by the client, and the
application doesn't natively support byte ranges. Again, however,
the application **should** perform this function on its own if desired.
@ -1124,7 +1125,7 @@ that every application must reimplement every HTTP feature; many HTTP
features can be partially or fully implemented by middleware
components, thus freeing both server and application authors from
implementing the same features over and over again.
Thread Support
--------------
@ -1227,17 +1228,17 @@ principle can configure these externally to the server, or in the
CGI case they may be able to be set via the server's configuration
files.
Applications **should** try to keep such required variables to a
minimum, since not all servers will support easy configuration of
them. Of course, even in the worst case, persons deploying an
Applications **should** try to keep such required variables to a
minimum, since not all servers will support easy configuration of
them. Of course, even in the worst case, persons deploying an
application can create a script to supply the necessary configuration
values::
from the_app import application
def new_app(environ,start_response):
def new_app(environ, start_response):
environ['the_app.configval1'] = 'something'
return application(environ,start_response)
return application(environ, start_response)
But, most existing applications and frameworks will probably only need
a single configuration value from ``environ``, to indicate the location
@ -1267,8 +1268,8 @@ may do so using the following algorithm, contributed by Ian Bicking::
if environ['SERVER_PORT'] != '80':
url += ':' + environ['SERVER_PORT']
url += quote(environ.get('SCRIPT_NAME',''))
url += quote(environ.get('PATH_INFO',''))
url += quote(environ.get('SCRIPT_NAME', ''))
url += quote(environ.get('PATH_INFO', ''))
if environ.get('QUERY_STRING'):
url += '?' + environ['QUERY_STRING']
@ -1317,7 +1318,7 @@ more complex:
also implement this protocol.)
Finally, middleware that wishes to support pre-2.2 versions of Python,
and iterates over application return values or itself returns an
and iterates over application return values or itself returns an
iterable (or both), must follow the appropriate recommendations above.
(Note: It should go without saying that to support pre-2.2 versions
@ -1342,7 +1343,7 @@ into an iterable that it then returns, e.g.::
return iter(lambda: filelike.read(block_size), '')
If the server or gateway supplies ``wsgi.file_wrapper``, it must be
a callable that accepts one required positional parameter, and one
a callable that accepts one required positional parameter, and one
optional positional parameter. The first parameter is the file-like
object to be sent, and the second parameter is an optional block
size "suggestion" (which the server/gateway need not use). The
@ -1367,7 +1368,7 @@ must occur **after** the application returns, and the server or
gateway checks to see if a wrapper object was returned. (Again,
because of the presence of middleware, error handlers, and the like,
it is not guaranteed that any wrapper created will actually be used.)
Apart from the handling of ``close()``, the semantics of returning a
file wrapper from the application should be the same as if the
application had returned ``iter(filelike.read, '')``. In other words,
@ -1378,7 +1379,7 @@ reached.
Of course, platform-specific file transmission APIs don't usually
accept arbitrary "file-like" objects. Therefore, a
``wsgi.file_wrapper`` has to introspect the supplied object for
things such as a ``fileno()`` (Unix-like OSes) or a
things such as a ``fileno()`` (Unix-like OSes) or a
``java.nio.FileChannel`` (under Jython) in order to determine if
the file-like object is suitable for use with the platform-specific
API it supports.
@ -1394,10 +1395,10 @@ file wrapper class, suitable for old (pre 2.2) and new Pythons alike::
def __init__(self, filelike, blksize=8192):
self.filelike = filelike
self.blksize = blksize
if hasattr(filelike,'close'):
if hasattr(filelike, 'close'):
self.close = filelike.close
def __getitem__(self,key):
def __getitem__(self, key):
data = self.filelike.read(self.blksize)
if data:
return data
@ -1408,9 +1409,9 @@ access to a platform-specific API::
environ['wsgi.file_wrapper'] = FileWrapper
result = application(environ, start_response)
try:
if isinstance(result,FileWrapper):
if isinstance(result, FileWrapper):
# check if result.filelike is usable w/platform-specific
# API, and if so, use that API to transmit the result.
# If not, fall through to normal iterable handling
@ -1418,10 +1419,10 @@ access to a platform-specific API::
for data in result:
# etc.
finally:
if hasattr(result,'close'):
result.close()
if hasattr(result, 'close'):
result.close()
Questions and Answers
@ -1578,15 +1579,15 @@ or are on the PEP author's "to-do" list:
* Should ``wsgi.input`` be an iterator instead of a file? This would
help for asynchronous applications and chunked-encoding input
streams.
* Optional extensions are being discussed for pausing iteration of an
application's ouptut until input is available or until a callback
occurs.
* Add a section about synchronous vs. asynchronous apps and servers,
the relevant threading models, and issues/design goals in these
areas.
Acknowledgements
================
@ -1608,7 +1609,7 @@ thoughtful feedback made this revised draft possible. Especially:
function. His input also guided the design of the exception handling
facilities, especially in the area of allowing for middleware that
overrides application error messages.
* Alan Kennedy, whose courageous attempts to implement WSGI-on-Jython
(well before the spec was finalized) helped to shape the "supporting
older versions of Python" section, as well as the optional
@ -1617,7 +1618,7 @@ thoughtful feedback made this revised draft possible. Especially:
* Mark Nottingham, who reviewed the spec extensively for issues with
HTTP RFC compliance, especially with regard to HTTP/1.1 features that
I didn't even know existed until he pointed them out.
References
==========
@ -1631,7 +1632,7 @@ References
.. [3] "Chunked Transfer Coding" -- HTTP/1.1, section 3.6.1
(http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1)
.. [4] "End-to-end and Hop-by-hop Headers" -- HTTP/1.1, Section 13.5.1
.. [4] "End-to-end and Hop-by-hop Headers" -- HTTP/1.1, Section 13.5.1
(http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1)
.. [5] mod_ssl Reference, "Environment Variables"