Christopher Stawarz ha scritto:
On May 21, 2008, at 1:34 PM, Manlio Perillo wrote:

Instead, the spec recommends that async servers pre-read the request body before invoking the app (either by default or as a configurable option).

This is the best solution most of the time (but not for all of the time), especially if the "server" can do some "pre-parsing" of multipart/form-data request body.

In fact I plan to write a custom function (in C for Nginx) that will "reduce", as an example:

  Content-Type: multipart/form-data; boundary=AaB03x

  --AaB03x
  Content-Disposition: form-data; name="submit-name"

  Larry
  --AaB03x
  Content-Disposition: form-data; name="files"; filename="file1.txt"
  Content-Type: text/plain

  ... contents of file1.txt ...
  --AaB03x--

to (not properly escaped):

Content-Type: application/x-www-form-urlencoded

submit-name=Larry&files.filename=file1.txt&files.ctype=text/plain&files.path=xxx


and the contents of file1.txt will be saved to a temporary file 'xxx'.

It seems like you're making this more complicated than it needs to be. Why not just store the entire request body in a temporary file, and then pass an open handle to it as wsgi.input?

Because if you have a big file (like a video of > 100 MB), your application will block everything while parsing the request body.

Parsing the body incrementally is far more efficient (although it is more hard).


That way, the server doesn't have to rewrite the request, and the application doesn't need to know how to interpret the files.* parameters.


How to interpret the files.* parameters is not really a problem.

1) Why not add a more generic poll like interface?

Because such an interface would be more complicated than what I've proposed and harder for server authors to implement. Also, I'm not sure that it gains you much.


Well, I have modelled my extension so that it has a "well know" interface and that it is not hard to implement.

But I have to say that I'm not sure if one want to poll multiple sockets.

Moreover in my implementation ngx.poll only returns one "ready" socket at a time.


By the way: I see a problem with you API.
What happens if an application do:

    read, write, exc = m.fdset()

    environ['x-wsgiorg.fdevent.readable'](read[0], 1.0)
    environ['x-wsgiorg.fdevent.writable'](write[0], 1.0)

    yield ''


There is no way to know, when the application is resumed, if the socket is ready for read or write.

This probabily should not be a problem, but I'm not sure.

Note that I'm not 100% sure on this, as I tried to indicate in the "Open Issues" section of my proposal. The approach I'd like to take is to try writing apps with my interface for a while, and if real-world usage shows that a poll-like interface would be very useful (or necessary), then the spec could be extended to add one. I think this is a safe route, since the readable/writable functions could easily be implemented in terms of a more generic poll-like interface, so existing apps that use the fdevent extensions would continue to work.

  Moreover IMHO storing a timeout variable in the environ to check if
  the previous call timedout, is not the best solution.

I think it's a simple and effective solution. Server authors don't need to implement any new functions or data types. They just create and hold on to a mutable object instance (the simplest being a list instance) for each app instance and toggle its truth value as required.

  In my implementation I return a function, but with generators in
  Python 2.5 this can be done in a better way.

What advantage does this have over what I've proposed?


You don't need to store a mutable variable in the environ.

2) In Nginx it is not possible to simply handle "plain" file
  descriptors, since these are wrapped in a connection structure.

  This is the reason why I had to add a connection_wrapper function in
  my WSGI module for Nginx.

But the connection structure just wraps an integer file descriptor, right? So the readable/writable functions can create the required wrapper to register with nginx. There's no reason to make the application author do it.


The "problem" is that Ninx keeps a list of preallocated connection objects (the size of the list being controlled by worker_connections).

This means that a newly constructed connection *must* be freed as soon as it is no more used, otherwise it can limit the number of concurrent connections that can be handled by Nginx.

Since with my API (register/unregister) a connection should be kept alive until is is unregistered, I have choosen to create a wrapper for the Nginx connection object.


Probabily with your API it can be possible to create temporary wrappers.
But I don't know if this is a good idea.

[...]


Chris



Manlio Perillo
_______________________________________________
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

Reply via email to