Moved middleware introduction to "Specification Overview" section,
adding a code example for a trivial middleware component.
This commit is contained in:
parent
45b26f3c1f
commit
3f6ca60005
126
pep-0333.txt
126
pep-0333.txt
|
@ -125,6 +125,17 @@ Other servers and gateways may use configuration files or other
|
||||||
mechanisms to specify where an application object should be
|
mechanisms to specify where an application object should be
|
||||||
imported from, or otherwise obtained.
|
imported from, or otherwise obtained.
|
||||||
|
|
||||||
|
In addition to "pure" servers/gateways and applications/frameworks,
|
||||||
|
it is also possible to create "middleware" components that implement
|
||||||
|
both sides of this specification. Such components act as an
|
||||||
|
application to their containing server, and as a server to a
|
||||||
|
contained application, and can be used to provide extended APIs,
|
||||||
|
content transformation, navigation, and other useful functions.
|
||||||
|
|
||||||
|
|
||||||
|
The Application/Framework Side
|
||||||
|
------------------------------
|
||||||
|
|
||||||
The application object is simply a callable object that accepts
|
The application object is simply a callable object that accepts
|
||||||
two arguments. The term "object" should not be misconstrued as
|
two arguments. The term "object" should not be misconstrued as
|
||||||
requiring an actual object instance: a function, method, class,
|
requiring an actual object instance: a function, method, class,
|
||||||
|
@ -184,6 +195,10 @@ invoking a callable must *not* have any dependency on what kind of
|
||||||
callable was provided to it. Callables are only to be called, not
|
callable was provided to it. Callables are only to be called, not
|
||||||
introspected upon.
|
introspected upon.
|
||||||
|
|
||||||
|
|
||||||
|
The Server/Gateway Side
|
||||||
|
-----------------------
|
||||||
|
|
||||||
The server or gateway invokes the application callable once for each
|
The server or gateway invokes the application callable once for each
|
||||||
request it receives from an HTTP client, that is directed at the
|
request it receives from an HTTP client, that is directed at the
|
||||||
application. To illustrate, here is a simple CGI gateway, implemented
|
application. To illustrate, here is a simple CGI gateway, implemented
|
||||||
|
@ -254,8 +269,89 @@ server.
|
||||||
if hasattr(result,'close'):
|
if hasattr(result,'close'):
|
||||||
result.close()
|
result.close()
|
||||||
|
|
||||||
In the next section, we will specify the precise semantics that
|
|
||||||
these illustrations are examples of.
|
Middleware: Components that Play Both Sides
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Note that a single object may play the role of a server with respect
|
||||||
|
to some application(s), while also acting as an application with
|
||||||
|
respect to some server(s). Such "middleware" components can perform
|
||||||
|
such functions as:
|
||||||
|
|
||||||
|
* Routing a request to different application objects based on the
|
||||||
|
target URL, after rewriting the ``environ`` accordingly.
|
||||||
|
|
||||||
|
* Allowing multiple applications or frameworks to run side-by-side
|
||||||
|
in the same process
|
||||||
|
|
||||||
|
* Load balancing and remote processing, by forwarding requests and
|
||||||
|
responses over a network
|
||||||
|
|
||||||
|
* Perform content postprocessing, such as applying XSL stylesheets
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
"middleware stack".
|
||||||
|
|
||||||
|
For the most part, middleware must conform to the restrictions
|
||||||
|
and requirements of both the server and application sides of
|
||||||
|
WSGI. In some cases, however, requirements for middleware
|
||||||
|
are more stringent than for a "pure" server or application,
|
||||||
|
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
|
||||||
|
probably use a more robust way of checking the content type, and
|
||||||
|
should also check for a content encoding.)
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from piglatin import piglatin
|
||||||
|
|
||||||
|
class Latinator:
|
||||||
|
|
||||||
|
# by default, don't transform output
|
||||||
|
transform = str
|
||||||
|
|
||||||
|
def __init__(self, application):
|
||||||
|
self.application = application
|
||||||
|
|
||||||
|
def __call__(environ, start_response):
|
||||||
|
|
||||||
|
def write_latin(data):
|
||||||
|
self.write(self.transform(data))
|
||||||
|
|
||||||
|
def start_latin(status,headers,exc_info=None):
|
||||||
|
|
||||||
|
for name,value in headers:
|
||||||
|
if name.lower()=='content-type' and value=='text/plain':
|
||||||
|
self.transform = piglatin
|
||||||
|
# Strip content-length if present, else it'll be wrong
|
||||||
|
headers = [(name,value)
|
||||||
|
for name,value in headers
|
||||||
|
if name.lower()<>'content-length'
|
||||||
|
]
|
||||||
|
break
|
||||||
|
|
||||||
|
self.write = start_response(status,headers,exc_info)
|
||||||
|
return write_latin
|
||||||
|
|
||||||
|
for data in self.application(environ,start_latin):
|
||||||
|
yield self.transform(data)
|
||||||
|
|
||||||
|
# Run foo_app under a Latinator's control, using the example CGI gateway
|
||||||
|
from foo_app import foo_app
|
||||||
|
run_with_cgi(Latinator(foo_app))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Specification Details
|
Specification Details
|
||||||
|
@ -851,6 +947,8 @@ of its use::
|
||||||
start_response(status, headers)
|
start_response(status, headers)
|
||||||
return ["normal body goes here"]
|
return ["normal body goes here"]
|
||||||
except:
|
except:
|
||||||
|
# XXX should trap runtime issues like MemoryError, KeyboardInterrupt
|
||||||
|
# in a separate handler before this bare 'except:'...
|
||||||
status = "500 Oops"
|
status = "500 Oops"
|
||||||
headers = [("content-type","text/plain")]
|
headers = [("content-type","text/plain")]
|
||||||
start_response(status, headers, sys.exc_info())
|
start_response(status, headers, sys.exc_info())
|
||||||
|
@ -976,30 +1074,6 @@ course, applications should cache such configuration, to avoid having
|
||||||
to re-read it upon each invocation.)
|
to re-read it upon each invocation.)
|
||||||
|
|
||||||
|
|
||||||
Middleware
|
|
||||||
----------
|
|
||||||
|
|
||||||
Note that a single object may play the role of a server with respect
|
|
||||||
to some application(s), while also acting as an application with
|
|
||||||
respect to some server(s). Such "middleware" components can perform
|
|
||||||
such functions as:
|
|
||||||
|
|
||||||
* Routing a request to different application objects based on the
|
|
||||||
target URL, after rewriting the ``environ`` accordingly.
|
|
||||||
|
|
||||||
* Allowing multiple applications or frameworks to run side-by-side
|
|
||||||
in the same process
|
|
||||||
|
|
||||||
* Load balancing and remote processing, by forwarding requests and
|
|
||||||
responses over a network
|
|
||||||
|
|
||||||
* Perform content postprocessing, such as applying XSL stylesheets
|
|
||||||
|
|
||||||
Given the existence of applications and servers conforming to this
|
|
||||||
specification, the appearance of such reusable middleware becomes
|
|
||||||
a possibility.
|
|
||||||
|
|
||||||
|
|
||||||
Supporting Older (<2.2) Versions of Python
|
Supporting Older (<2.2) Versions of Python
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue