PEP 444

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

PEP 444

Alice Bevan–McGregor
(A version of this is is available at http://web-core.org/2.0/pep-0444/ — links are links, code may be easier to read.)

PEP 444 is quite exciting to me.  So much so that I’ve been spending a few days writing a high-performance (C10K, 10Krsec) Py2.6+/3.1+ HTTP/1.1 server which implements much of the proposed standard.  The server is functional (less web3.input at the time of this writing), but differs from PEP 444 in several ways.  It also adds several features I feel should be part of the spec.

Source for the server is available on GitHub:

        https://github.com/pulp/marrow.server.http

I have made several notes about the PEP 444 specification during implementation of the above, and concern over some implementation details:

First, async is poorly defined:

> If the origin server advertises that it has the web3.async capability, a Web3 application callable used by the server is permitted to return a callable that accepts no arguments. When it does so, this callable is to be called periodically by the origin server until it returns a non-None response, which must be a normal Web3 response tuple.

Polling is not true async.  I believe that it should be up to the server to define how async is utilized, and that the specification should be clarified on this point.  (“Called periodically” is too vague.)  “Callable” should likely be redefined as “generator” (a callable that yields) as most applications require holding on to state and wrapping everything in functools.partial() is somewhat ugly.  Utilizing generators would improve support for existing Python async frameworks, and allow four modes of operation: yield None (no response, keep waiting), yield response_tuple (standard response), return / raise StopIteration (close the async connection) and allow for data to be passed back to the async callable by the higher-level async framework.

Second, WSGI middleware, while impressive in capability, are somewhat… heavy-weight.  Heavily nesting function calls is wasteful of CPU and RAM, especially if the middleware decides it can’t operate, for example, GZip compression disabling itself for non-text/ mimetypes.  The majority of WSGI middleware can, and probably should be, implemented as linear ingress or egress filters.  For example, on-disk static file serving could be an ingress filter, and GZip compression an egress filter.  m.s.http supports this filtering and demonstrates one API for such.  Also, I am in the process of writing an example egress CompressionFilter.

An example API and filter use implementation: (paraphrased from marrow.server.http)

> # No filters, near 0 overhead.
> for filter_ in ingress_filters:
>     # Can mutate the environment.
>     result = filter_(env)
>    
>     # Allow the filter to return a response rather than continuing.
>     if result:
>         # result is a status, headers, body_iter tuple
>         return result[0], result[1], result[2]
>
> status, headers, body = application(env)
>
> for filter_ in egress_filters:
>     # Can mutate the environment, status, headers, body, or
>     # return completely new status, headers, and body.
>     status, headers, body = filter_(env, status, headers, body)
>
> return status, headers, body

The environment has some minor issues.  I’ll write up my changes in RFC-style:

SERVER_NAME is REQUIRED and MUST contain the DNS name of the server OR virtual server name for the web server if available OR an empty bytestring if DNS resolution is unavailable.  SERVER_ADDR is REQUIRED and MUST contain the web server’s bound IP address.  URL reconstruction SHOULD use HTTP_HOST if available, SERVER_NAME if there is no HTTP_HOST, and fall back on SERVER_ADDR if SERVER_NAME is an empty bytestring.

CONTENTL_LENGTH is REQUIRED and MUST be None if not defined by the client.  Testing explicitly for None is more efficient than armoring against missing values; also, explicit is better than implicit.  (Paste’s WSGI1 server defines CONTENT_LENGTH as 0, but this implies the client explicitly declared it as zero, which is not the case.)

FRAGMENT and PARAMETERS are REQUIRED and are parsed out of the URL in the same way as the QUERY_STRING. FRAGMENT is the text after a hash mark (a.k.a. “anchor” to browsers, e.g. /foo#bar). PARAMETERS come before QUERY_STRING, and after PATH_INFO separated by a semicolon, e.g. /foo;bar?baz.  Both values MUST be empty bytestrings if not present in the URL. (Rarely used — I’ve only seen it in Java and ColdFusion applications — but still useful.)

Points of contention:

Changing the namespace seems needless.  Using the wsgi.* namespace with a wsgi.version of (2, 0) will allow applications to easily armor themselves against incompatible use.  That’s what wsgi.version is for!  I’d add this as a strong “point of contention”.  m.s.http keeps the wsgi namespace and uses a version of (2, 0).

That’s it so far.  I may occasionally write in with additional ideas as I continue with my HTTP server implementation.

        — Alice.

_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Chris McDonough
PEP 444 has no champion currently.  Both Armin and I have basically left
it behind.  It would be great if you wanted to be its champion.

- C

On Sun, 2010-11-21 at 03:12 -0800, Alice Bevan-McGregor wrote:

> (A version of this is is available at http://web-core.org/2.0/pep-0444/ — links are links, code may be easier to read.)
>
> PEP 444 is quite exciting to me.  So much so that I’ve been spending a few days writing a high-performance (C10K, 10Krsec) Py2.6+/3.1+ HTTP/1.1 server which implements much of the proposed standard.  The server is functional (less web3.input at the time of this writing), but differs from PEP 444 in several ways.  It also adds several features I feel should be part of the spec.
>
> Source for the server is available on GitHub:
>
> https://github.com/pulp/marrow.server.http
>
> I have made several notes about the PEP 444 specification during implementation of the above, and concern over some implementation details:
>
> First, async is poorly defined:
>
> > If the origin server advertises that it has the web3.async capability, a Web3 application callable used by the server is permitted to return a callable that accepts no arguments. When it does so, this callable is to be called periodically by the origin server until it returns a non-None response, which must be a normal Web3 response tuple.
>
> Polling is not true async.  I believe that it should be up to the server to define how async is utilized, and that the specification should be clarified on this point.  (“Called periodically” is too vague.)  “Callable” should likely be redefined as “generator” (a callable that yields) as most applications require holding on to state and wrapping everything in functools.partial() is somewhat ugly.  Utilizing generators would improve support for existing Python async frameworks, and allow four modes of operation: yield None (no response, keep waiting), yield response_tuple (standard response), return / raise StopIteration (close the async connection) and allow for data to be passed back to the async callable by the higher-level async framework.
>
> Second, WSGI middleware, while impressive in capability, are somewhat… heavy-weight.  Heavily nesting function calls is wasteful of CPU and RAM, especially if the middleware decides it can’t operate, for example, GZip compression disabling itself for non-text/ mimetypes.  The majority of WSGI middleware can, and probably should be, implemented as linear ingress or egress filters.  For example, on-disk static file serving could be an ingress filter, and GZip compression an egress filter.  m.s.http supports this filtering and demonstrates one API for such.  Also, I am in the process of writing an example egress CompressionFilter.
>
> An example API and filter use implementation: (paraphrased from marrow.server.http)
>
> > # No filters, near 0 overhead.
> > for filter_ in ingress_filters:
> >     # Can mutate the environment.
> >     result = filter_(env)
> >    
> >     # Allow the filter to return a response rather than continuing.
> >     if result:
> >         # result is a status, headers, body_iter tuple
> >         return result[0], result[1], result[2]
> >
> > status, headers, body = application(env)
> >
> > for filter_ in egress_filters:
> >     # Can mutate the environment, status, headers, body, or
> >     # return completely new status, headers, and body.
> >     status, headers, body = filter_(env, status, headers, body)
> >
> > return status, headers, body
>
> The environment has some minor issues.  I’ll write up my changes in RFC-style:
>
> SERVER_NAME is REQUIRED and MUST contain the DNS name of the server OR virtual server name for the web server if available OR an empty bytestring if DNS resolution is unavailable.  SERVER_ADDR is REQUIRED and MUST contain the web server’s bound IP address.  URL reconstruction SHOULD use HTTP_HOST if available, SERVER_NAME if there is no HTTP_HOST, and fall back on SERVER_ADDR if SERVER_NAME is an empty bytestring.
>
> CONTENTL_LENGTH is REQUIRED and MUST be None if not defined by the client.  Testing explicitly for None is more efficient than armoring against missing values; also, explicit is better than implicit.  (Paste’s WSGI1 server defines CONTENT_LENGTH as 0, but this implies the client explicitly declared it as zero, which is not the case.)
>
> FRAGMENT and PARAMETERS are REQUIRED and are parsed out of the URL in the same way as the QUERY_STRING. FRAGMENT is the text after a hash mark (a.k.a. “anchor” to browsers, e.g. /foo#bar). PARAMETERS come before QUERY_STRING, and after PATH_INFO separated by a semicolon, e.g. /foo;bar?baz.  Both values MUST be empty bytestrings if not present in the URL. (Rarely used — I’ve only seen it in Java and ColdFusion applications — but still useful.)
>
> Points of contention:
>
> Changing the namespace seems needless.  Using the wsgi.* namespace with a wsgi.version of (2, 0) will allow applications to easily armor themselves against incompatible use.  That’s what wsgi.version is for!  I’d add this as a strong “point of contention”.  m.s.http keeps the wsgi namespace and uses a version of (2, 0).
>
> That’s it so far.  I may occasionally write in with additional ideas as I continue with my HTTP server implementation.
>
> — Alice.
>
> _______________________________________________
> Web-SIG mailing list
> [hidden email]
> Web SIG: http://www.python.org/sigs/web-sig
> Unsubscribe: http://mail.python.org/mailman/options/web-sig/chrism%40plope.com


_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
> PEP 444 has no champion currently.  Both Armin and I have basically left it behind.  It would be great if you wanted to be its champion.

Done.

As I already have a functional, performant HTTP server[1] and example filter[2] (compression) utilizing a slightly modified version of PEP 444, and hope to be giving a presentation on its design and related utilities[3] early next year, I’d love to have the opportunity to directly shape its future.  My server may be a bit large to be a reference implementation, but until it has its first user I have the benefit of being able to experiment whole-heartedly with features and proposals.

Since Python 3 was released I haven’t heard of much forward-progress in getting web frameworks compatible.  The largest complaint I’ve heard is that there are too few things already ported, which is a chicken and the egg problem.  This is one scenario where re-inventing the wheel may be the only way to see forward movement.  So far, I seem to be buckling down and Getting Things Done™ in this regard.

How would I go about getting access to the PEP in order to fix the issues I’ve been catching up on?  (I’ve been reading through quite a bit of old mailing list traffic these last few hours in-between writing docs and unit tests for the compression egress filter.)

Now I’m even more excited.  I’ll make a separate post to confirm and get some input on the issues I’ve encountered thus far.

        — Alice.

[1] https://github.com/pulp/marrow.server.http
[2] https://github.com/pulp/marrow.wsgi.egress.compression — full documentation included
[3] http://web-core.org/marrow/confoo/ — input welcome; the deadline for modification is the 26th
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Chris McDonough
On Sun, 2010-11-21 at 09:32 -0800, Alice Bevan-McGregor wrote:
> > PEP 444 has no champion currently.  Both Armin and I have basically left it behind.  It would be great if you wanted to be its champion.
>
> Done.
>
> As I already have a functional, performant HTTP server[1] and example filter[2] (compression) utilizing a slightly modified version of PEP 444, and hope to be giving a presentation on its design and related utilities[3] early next year, I’d love to have the opportunity to directly shape its future.  My server may be a bit large to be a reference implementation, but until it has its first user I have the benefit of being able to experiment whole-heartedly with features and proposals.
>
> Since Python 3 was released I haven’t heard of much forward-progress in getting web frameworks compatible.  The largest complaint I’ve heard is that there are too few things already ported, which is a chicken and the egg problem.  This is one scenario where re-inventing the wheel may be the only way to see forward movement.  So far, I seem to be buckling down and Getting Things Done™ in this regard.
>
> How would I go about getting access to the PEP in order to fix the issues I’ve been catching up on?  (I’ve been reading through quite a bit of old mailing list traffic these last few hours in-between writing docs and unit tests for the compression egress filter.)

Georg Brandl has thus far been updating the canonical PEP on python.org.
I don't know how you get access to that.  My working copy is at
https://github.com/mcdonc/web3 .

- C


_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
Would you prefer to give me collaboration permissions on your repo, or should I fork it?

This message was sent from a mobile device. Please excuse any terseness and spelling or grammatical errors. If additional information is indicated it will be sent from a desktop computer as soon as possible. Thank you.

On 2010-11-21, at 11:40 PM, Chris McDonough <[hidden email]> wrote:

Georg Brandl has thus far been updating the canonical PEP on python.org.
I don't know how you get access to that.  My working copy is at
https://github.com/mcdonc/web3 .

_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Chris McDonough
On Mon, 2010-11-22 at 00:08 -0800, Alice Bevan-McGregor wrote:
> Would you prefer to give me collaboration permissions on your repo, or
> should I fork it?

Please fork it or create another repository entirely. I have no plans to
do more work on it personally, so I don't think it should really be
associated with me.  To that end, I think I'd prefer my name to either
be off the PEP entirely or just listed as a helper or typist or
something. ;-)

- C


>
> This message was sent from a mobile device. Please excuse any
> terseness and spelling or grammatical errors. If additional
> information is indicated it will be sent from a desktop computer as
> soon as possible. Thank you.
>
> On 2010-11-21, at 11:40 PM, Chris McDonough <[hidden email]> wrote:
>
>
> > Georg Brandl has thus far been updating the canonical PEP on
> > python.org.
> > I don't know how you get access to that.  My working copy is at
> > https://github.com/mcdonc/web3 .
>


_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
I’ve forked it, now available at:

        https://github.com/GothAlice/wsgi2

Re-naming it to wsgi2 will be my first order of business during the week, altering your association the second.  I’ll post change descriptions for discussion as I go.

        — Alice.

On 2010-11-22, at 12:12 AM, Chris McDonough wrote:

>> Would you prefer to give me collaboration permissions on your repo, or
>> should I fork it?
>
> Please fork it or create another repository entirely. I have no plans to
> do more work on it personally, so I don't think it should really be
> associated with me.  To that end, I think I'd prefer my name to either
> be off the PEP entirely or just listed as a helper or typist or
> something. ;-)

_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Mark Ramm
I would very much prefer it if we could keep the current name or
choose a new unrelated name, not wsgi2 as I think there API changes
warrant a new name to prevent confusion.

--Mark

On Mon, Nov 22, 2010 at 3:18 AM, Alice Bevan-McGregor
<[hidden email]> wrote:

> I’ve forked it, now available at:
>
>        https://github.com/GothAlice/wsgi2
>
> Re-naming it to wsgi2 will be my first order of business during the week, altering your association the second.  I’ll post change descriptions for discussion as I go.
>
>        — Alice.
>
> On 2010-11-22, at 12:12 AM, Chris McDonough wrote:
>
>>> Would you prefer to give me collaboration permissions on your repo, or
>>> should I fork it?
>>
>> Please fork it or create another repository entirely. I have no plans to
>> do more work on it personally, so I don't think it should really be
>> associated with me.  To that end, I think I'd prefer my name to either
>> be off the PEP entirely or just listed as a helper or typist or
>> something. ;-)
>
> _______________________________________________
> Web-SIG mailing list
> [hidden email]
> Web SIG: http://www.python.org/sigs/web-sig
> Unsubscribe: http://mail.python.org/mailman/options/web-sig/mark.mchristensen%40gmail.com
>



--
Mark Ramm-Christensen
email: mark at compoundthinking dot com
blog: www.compoundthinking.com/blog
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

ianb
On Mon, Nov 22, 2010 at 5:05 PM, Mark Ramm <[hidden email]> wrote:
I would very much prefer it if we could keep the current name or
choose a new unrelated name, not wsgi2 as I think there API changes
warrant a new name to prevent confusion.

Why?  Obviously "2" implies some breaking changes, and the changes are reasonable enough that it's not a complete change.  Most of the changes have been discussed as "WSGI 2" for a long time preceding this spec anyway.

--
Ian Bicking  |  http://blog.ianbicking.org

_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
In reply to this post by Mark Ramm
On 2010-11-22, at 3:05 PM, Mark Ramm <[hidden email]> wrote:

> I would very much prefer it if we could keep the current name or choose a new unrelated name, not wsgi2 as I think there API changes warrant a new name to prevent confusion.

Web3, as mentioned in previous mailing list traffic, is a registered trademark. Python Web and WSGI are closely linked in the public mind-space. (Sleep deprived an can't think of a better way to phrase that.) Finally, I, and seemingly Python core, interpret major version number changes as breaking; py3k having backwards-incompatible syntax changes.

At a high level PEP 444 is /similar/ to WSGI in so far as the environ is a dict, and the returned values are a bytestring status, list of tuples for headers, and an iterable body. The inner implementation details seem a progressive enhancement and clarification of details which just happen to be backwards-incompatible.

Preserving the WSGI name has marketing benefits, refines existing understanding of the server/middleware/application semantics rather than implying something /completely/ new, and increasing the version to 2.0 "clearly" declares the backwards-incompatibility.

I think that Python 2 vs. 3 is a good comparison here; Python 3 has a different syntax and grammar, making it a fundamentally different language and is incompatible because of this. Why is it called Python and not Xyzzy?  #python wouldn’t have to have  ;)

Web frameworks have been encountering this problem for some time; TurboGerars developers, e.g., have been mulling over migrating to Pyramid or another top-level metaframework and debating strategies for migration: point everyone at something else, create something new, or keep the name and associated recognition?

Technically PEP 444 is incompatible, and wsgi.version = (2, 0) (and clear documentation) should indicate that.

   — Alice.
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Georg Brandl-2
In reply to this post by Chris McDonough
Am 22.11.2010 08:40, schrieb Chris McDonough:

>> How would I go about getting access to the PEP in order to fix the issues
>> I’ve been catching up on?  (I’ve been reading through quite a bit of old
>> mailing list traffic these last few hours in-between writing docs and unit
>> tests for the compression egress filter.)
>
> Georg Brandl has thus far been updating the canonical PEP on python.org. I
> don't know how you get access to that.

Basically, you don't -- you send updates to [hidden email] and we'll handle
the editing and committing for you.

Georg


_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Mark Ramm
In reply to this post by ianb
Ok.  Retracted.

I have been admiring the purity and simplicity of the JSON spec which
intentionally has no version number.  New changes are therefore only
allowed with a new name.  That removes a lot of complexity around
figuring out what versions of the spec what server implements, etc.

But the wsgi spec is far more complicated than JSON, and I expect that
complexity is probably unavoidable.

--Mark Ramm

On Monday, November 22, 2010, Ian Bicking <[hidden email]> wrote:

> On Mon, Nov 22, 2010 at 5:05 PM, Mark Ramm <[hidden email]> wrote:
>
>
> I would very much prefer it if we could keep the current name or
> choose a new unrelated name, not wsgi2 as I think there API changes
> warrant a new name to prevent confusion.
>
> Why?  Obviously "2" implies some breaking changes, and the changes are reasonable enough that it's not a complete change.  Most of the changes have been discussed as "WSGI 2" for a long time preceding this spec anyway.
>
>
> --
> Ian Bicking  |  http://blog.ianbicking.org
>

--
Mark Ramm-Christensen
email: mark at compoundthinking dot com
blog: www.compoundthinking.com/blog
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
I’ve updated my copy of the PEP, re-naming non-commentary and non-revision text to reference WSGI2, wsgi2, or wsgi (environment variables) as appropriate.  I’ve also added the first draft of the text describing filters and some sample code, including a middleware adapter for filters.  Here are some additional notes:

        https://gist.github.com/719763 — filter vs. middleware
        http://dirtsimple.org/2007/02/wsgi-middleware-considered-harmful.html

It might be worth another PEP to describe interfaces to common data to encourage interoperability between filters/middleware, such as GET/POST data, cookies, session data (likely using Beaker’s API as a base), etc.  Also something I’ve been exploring is automatic resolution of middleware/filter dependance by utilizing “uses”, “needs”, and “provides” properties on the callables and a middleware stack factory which can graph the dependancy tree.

On a side note, I do not appear to be receiving posts to this mailing list, only the out-of-list CC/BCCs.  :/  And here I’ve been getting used to reading and posting to comp.lang.python[.announce] on Usenet.  ;)

        — Alice.
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: PEP 444

Alice Bevan–McGregor
In reply to this post by Mark Ramm
The updated text is available at:

https://github.com/GothAlice/wsgi2/blob/master/pep-0444.rst

Forgot to mention that in the last message.

— Alice.

_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com