This is a very interesting initiative. However there are few problems: - there is no support for chunked input - that would require having support for readline in the first place, also, it should be the gateway's business decoding the chunked input. - the original wsgi spec somewhat has some support for streaming and asynchronicity [*1] - i don't see how removing the write callable will help (i don't see a issue having the server providing a stringio.write as the write callable for synchronous apps) - passing nonstring values though middleware will make using/porting existing wsgi middleware hairy (suppose you have a middleware that applies some filter to the appiter - you'll have your code full of isinstance nastiness)
Also, have you looked at the existing gateway implementations with asynchronous support? There are a bunch of them: http://trac.wiretooth.com/public/wiki/asycwsgi http://chiral.j4cbo.com/trac http://wiki.secondlife.com/wiki/Eventlet my own shot at the problem: http://code.google.com/p/cogen/ and manlio's mod_wsgi for nginx (I may be missing some) However there is absolutely no unity in handling the wsgi.input (or equivalent) [*1]In my implementation i do a bunch of tricks to make use of regular wsgi middleware with async apps possible - i have a bunch of working examples using pylons: - the extensions in the environ (like your environ['awsgi.readable']) return a empty string that penetrates most[*2] middleware and set the actual message (like your (token, fd, timeout) tuple on some internal object) >From this point of view, an async middleware stack is just a set of middleware that supports streaming. Please see: http://cogen.googlecode.com/svn/trunk/docs/cogen.web.async.html http://cogen.googlecode.com/svn/trunk/docs/cogen.web.wsgi.html [*2] middleware that consume the app iter ruin that pattern, but regardless, they are not compliant to the wsgi spec (see http://www.python.org/dev/peps/pep-0333/#middleware-handling-of-block-boundaries ) - notable examples are most of the exception handling middleware (they can't work otherwise anyway) On Tue, May 6, 2008 at 4:30 AM, Christopher Stawarz <[EMAIL PROTECTED]> wrote: > (I'm new to the list, so please forgive me for making my first post a > specification proposal :) > > Browsing through the list archives, I see there's been some > inconclusive discussions on adding better support for asynchronous web > servers to the WSGI spec. Since such support would be very useful for > some upcoming projects of mine, I decided to take a shot at specing > out and implementing it. I'd be grateful for any feedback you have. > If this seems like something worth pursuing, I would also welcome > collaborators to help develop the spec further. > > The name for this proposed specification is the Asynchronous Web > Server Gateway Interface (AWSGI). As the name suggests, the spec is > closely related to WSGI and is most easily described in terms of how > it differs from WSGI. AWSGI eliminates the following parts of WSGI: > > - the environment variables wsgi.version and wsgi.input > > - the write() callable returned by start_response() > > AWSGI adds the following environment variables: > > - awsgi.version > - awsgi.input > - awsgi.readable > - awsgi.writable > - awsgi.timeout > > In addition, AWSGI allows the application iterable to yield two types > of data: > > - byte strings, handled as in WSGI > > - the result of calling awsgi.readable or awsgi.writable, which > indicates that the application should be paused and restarted when > a specified file descriptor is ready for reading or writing > > Because of AWSGI's similarity to WSGI, a simple wrapper can be used to > run AWSGI applications on WSGI servers without alteration. > > The following example application demonstrates typical usage of AWSGI. > This application simply reads the request body and sends it back to > the client. Each time it wants to receive data from the client, it > first tests awsgi.input for readability and then calls its recv() > method. If awsgi.input is not readable after one second, the > application sends a "408 Request Timeout" response to the client and > terminates: > > > def echo_request_body(environ, start_response): > input = environ['awsgi.input'] > readable = environ['awsgi.readable'] > > nbytes = int(environ.get('CONTENT_LENGTH') or 0) > output = '' > while nbytes: > yield readable(input, 1.0) # Time out after 1 second > > if environ['awsgi.timeout']: > msg = 'The request timed out.' > start_response('408 Request Timeout', > [('Content-Type', 'text/plain'), > ('Content-Length', str(len(msg)))]) > yield msg > return > > data = input.recv(nbytes) > if not data: > break > output += data > nbytes -= len(data) > > start_response('200 OK', [('Content-Type', 'text/plain'), > ('Content-Length', str(len(output)))]) > yield output > > > I have rough but functional implementations of a number of AWSGI > components available in a Bazaar branch at > http://pseudogreen.org/bzr/awsgiref/. The package includes an > asyncore-based AWSGI server and an AWSGI-to-WSGI application wrapper. > In addition, the file spec.txt contains a more detailed description of > the specification (which is also appended below). > > Again, I'd very much appreciate comments and criticism. > > > Thanks, > Chris > > > > > Detailed AWSGI Specification > ---------------------------- > > - Required AWSGI environ variables: > > * All variables required by WSGI, except for wsgi.version and > wsgi.input, which must *not* be present > > * awsgi.version => the tuple (1, 0) > > * awsgi.input > > This is an object with one method, recv(bufsize), which behaves > like the socket method of the same name (although it doesn't > support the optional flags parameter). Before each call to > recv(), the application must test awsgi.input for readability via > awsgi.readable. The result of calling recv() without doing so is > undefined. > > (XXX: Should recv() handle EINTR for the application?) > > * awsgi.readable > * awsgi.writable > > These are callables with the signature f(fd, timeout=None). fd is > either a file descriptor (i.e. int or long) or an object with a > fileno() method that returns a file descriptor. > > timeout has the same semantics as the timeout parameter to > select.select(). If the operation times out, awsgi.timeout will > be true when the application resumes. > > In addition to checking readiness for reading or writing, servers > should also monitor file descriptors for "exceptional" conditions > (e.g. out-of-band data) and restart the application if they occur. > > * awsgi.timeout => boolean indicating whether the most recent read > or write wait timed out (false if there have been no waits) > > - start_response() must *not* return a write() callable, as this > method of providing application output to the server is incompatible > with asynchronous execution. > > - The server must accept awsgi.input as input to awsgi.readable, > either by providing an actual socket object or by special-case > handling (i.e. awsgi.input needn't have a fileno() method, as long > as the server handles it as if it did). > > - Applications return iterators, which can yield: > > * a string => sent to client, just as in standard WSGI > > * the result of a call to awsgi.readable or awsgi.writable => > application is resumed when either the file descriptor is ready > for reading/writing or the wait times out (in which case, > awsgi.timeout will be true) > > - Although AWSGI applications will *not* be directly compatible with > WSGI servers, middleware will allow them to run as standard WSGI > apps (with all I/O waits returning immediately). > > - AWSGI servers will not support unmodified WSGI applications. There > are several reasons for this: > > - If the app does blocking I/O, it will block the entire server. > > - Calls to the read() method of wsgi.input may fail with > EWOULDBLOCK, which an app expecting synchronous I/O probably won't > be prepared to deal with. > > - The readline(), readlines(), and __iter__() methods of wsgi.input > can require multiple network I/O operations, which is incompatible > with asynchronous execution. > > - The write() callable returned by start_response() is inherently > incompatible with asynchronous execution. > > Because of these issues, this specification aims for one-way > compatibility between AWSGI and WSGI (i.e. the ability to run AWSGI > apps on WSGI servers via middleware, but not vice versa). > > _______________________________________________ > Web-SIG mailing list > Web-SIG@python.org > Web SIG: http://www.python.org/sigs/web-sig > Unsubscribe: > http://mail.python.org/mailman/options/web-sig/ionel.mc%40gmail.com > -- http://ionelmc.wordpress.com
_______________________________________________ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com