Damjan | 20 May 2012 14:12
Picon
Gravatar

websocket support in WSGI

Recently I was enquiring about the possibility to implement websocket as 
a WSGI middleware, but I learned that to do that the middleware would 
need access to the underlying socket.

Has there been any thought about this? A wsgi addendum perhaps?

--

-- 
дамјан
_______________________________________________
Web-SIG mailing list
Web-SIG <at> python.org
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
Alex Grönholm | 21 May 2012 14:36
Picon

Re: websocket support in WSGI

20.05.2012 15:12, Damjan kirjoitti:
> Recently I was enquiring about the possibility to implement websocket 
> as a WSGI middleware, but I learned that to do that the middleware 
> would need access to the underlying socket.
>
> Has there been any thought about this? A wsgi addendum perhaps?
>
>
>
This has been discussed before and it's impossible to implement since 
proxying such things does not work over a number of protocols (FCGI, 
SCGI). IIRC, the front-end web server likes to send its own 1xx response 
before the application has a chance to send its own. The original 
discussion was about implement WebDAV, but WebSocket has the same issues.
_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Simon Sapin | 21 May 2012 15:47
Gravatar

Re: websocket support in WSGI

Le 21/05/2012 14:36, Alex Grönholm a écrit :
> This has been discussed before and it's impossible to implement since
> proxying such things does not work over a number of protocols (FCGI,
> SCGI). IIRC, the front-end web server likes to send its own 1xx response
> before the application has a chance to send its own. The original
> discussion was about implement WebDAV, but WebSocket has the same issues.

What would be possible is a server that does HTTP + WebSocket on the 
network side and WSGI + (some other API for WebSocket) on the 
application side, although I don’t know a server doing this.

--

-- 
Simon Sapin
_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Marcel Hellkamp | 21 May 2012 23:48
Picon
Gravatar

Re: websocket support in WSGI

Am 21.05.2012 15:47, schrieb Simon Sapin:
> Le 21/05/2012 14:36, Alex Grönholm a écrit :
>> This has been discussed before and it's impossible to implement since
>> proxying such things does not work over a number of protocols (FCGI,
>> SCGI). IIRC, the front-end web server likes to send its own 1xx response
>> before the application has a chance to send its own. The original
>> discussion was about implement WebDAV, but WebSocket has the same issues.
> 
> What would be possible is a server that does HTTP + WebSocket on the
> network side and WSGI + (some other API for WebSocket) on the
> application side, although I don’t know a server doing this.
> 

gevent and the gevent-websocket does this.
http://bottlepy.org/docs/dev/async.html#finally-websockets

The idea: A modified gevent server detects WebSocket requests and
immediately answers with handshake headers. Then it puts a socket-like
object in environ['wsgi.websocket'] and calls the WSGI application with
a dummy start_response() callable.

In this mode, the start_response() does nothing and the body iterator is
ignored. As long as the application callable blocks (or the body
iterator yields something), the socket stays open.

Problems with this API: The application is required to block, thus
blocking the handling server thread. Traditional threading servers have
limited thread-pools. Non-blocking servers (twisted/tornado) would
freeze completely.

(Continue reading)

Sylvain Hellegouarch | 22 May 2012 09:38
Gravatar

Re: websocket support in WSGI


In other words: The responsibility for the connection (and socket) is
passed to the application.

This works well with traditional threaded servers. The application can
spawn a new worker thread, put the job into a queue or whatever and then
return from the application callable, allowing the server thread to
continue handling new connections. 


This is exactly how ws4py was implemented when using CherryPy for the HTTP server performing the handshake [1]. There's also a WSGI middleware [2] but it's heavily geared towards gevent and may not be reusable easily elsewhere I'm afraid.

--
- Sylvain
http://www.defuze.org
http://twitter.com/lawouach

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
Alex Grönholm | 22 May 2012 15:39
Picon

Re: websocket support in WSGI

22.05.2012 10:38, Sylvain Hellegouarch kirjoitti:

In other words: The responsibility for the connection (and socket) is
passed to the application.

This works well with traditional threaded servers. The application can
spawn a new worker thread, put the job into a queue or whatever and then
return from the application callable, allowing the server thread to
continue handling new connections. 


This is exactly how ws4py was implemented when using CherryPy for the HTTP server performing the handshake [1]. There's also a WSGI middleware [2] but it's heavily geared towards gevent and may not be reusable easily elsewhere I'm afraid.
It's also a hack that violates the WSGI spec. It's also not usable through reverse proxying or FCGI/SCGI.

--
- Sylvain
http://www.defuze.org
http://twitter.com/lawouach



_______________________________________________ Web-SIG mailing list Web-SIG-+ZN9ApsXKcEdnm+yROfE0A@public.gmane.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/alex.gronholm%40nextday.fi

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
Sylvain Hellegouarch | 22 May 2012 15:45
Gravatar

Re: websocket support in WSGI



On Tue, May 22, 2012 at 3:39 PM, Alex Grönholm <alex.gronholm-S2Gd0AnZGk/HOG6cAo2yLw@public.gmane.org> wrote:
22.05.2012 10:38, Sylvain Hellegouarch kirjoitti:

In other words: The responsibility for the connection (and socket) is
passed to the application.

This works well with traditional threaded servers. The application can
spawn a new worker thread, put the job into a queue or whatever and then
return from the application callable, allowing the server thread to
continue handling new connections. 


This is exactly how ws4py was implemented when using CherryPy for the HTTP server performing the handshake [1]. There's also a WSGI middleware [2] but it's heavily geared towards gevent and may not be reusable easily elsewhere I'm afraid.
It's also a hack that violates the WSGI spec. It's also not usable through reverse proxying or FCGI/SCGI.


Yeap that's very true and it'll stay a hack until WSGI is updated to support it or explicitely reject protocols such as WebSocket. In the meanwhile, I'm personally fine having projects like ws4py to play with and decide what could work and what couldn't.

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
Roberto De Ioris | 23 May 2012 21:17
Picon

Re: websocket support in WSGI


> On Tue, May 22, 2012 at 3:39 PM, Alex Grönholm
> <alex.gronholm <at> nextday.fi>wrote:
>
>>  22.05.2012 10:38, Sylvain Hellegouarch kirjoitti:
>>
>>
>>> In other words: The responsibility for the connection (and socket) is
>>> passed to the application.
>>>
>>> This works well with traditional threaded servers. The application can
>>> spawn a new worker thread, put the job into a queue or whatever and
>>> then
>>> return from the application callable, allowing the server thread to
>>> continue handling new connections.
>>>
>>>
>>  This is exactly how ws4py was implemented when using CherryPy for the
>> HTTP server performing the handshake [1]. There's also a WSGI middleware
>> [2] but it's heavily geared towards gevent and may not be reusable
>> easily
>> elsewhere I'm afraid.
>>
>> It's also a hack that violates the WSGI spec. It's also not usable
>> through
>> reverse proxying or FCGI/SCGI.
>>
>
>
> Yeap that's very true and it'll stay a hack until WSGI is updated to
> support it or explicitely reject protocols such as WebSocket. In the
> meanwhile, I'm personally fine having projects like ws4py to play with and
> decide what could work and what couldn't.
>

Can't we simply define something like environ['wsgi.raw_socket'] (or
whatever name you want) mapping to the client (or webserver in case of
proxied) socket ?

At the very beginning, uWSGI used to map wsgi.input to the webserver
socket, and implementing WebSocket (and all of the 'HTTP Upgrade' fatures
you can think of, included the ultra-non-standard icecast protocol) was
easy for non-buffering webservers (like Apache or Cherokee)

http://projects.unbit.it/uwsgi/browser/websockets.py

Obviously reading from both wsgi.input and wsgi.raw_socket should be
"discouraged" (or directly forbidden)

My point is in not referring explicitely to WebSockets, but have a way to
simply let the application having access to the communication socket (with
some strict rule, like getting only the http body part and so on, to make
things easier for middleware developers)

I tend to consider mod_wsgi as the "standard de-facto" implementation of
WSGI, and adding support for wsgi.raw_socket in it would be really easy
(Graham i offer myself for a patch ;), as well as in uWSGI.

The problem will rise for nginx (when used as a proxy), but it is
generated by its "buffering" policy, so we cannot (for now) make something
about that.

--

-- 
Roberto De Ioris
http://unbit.it
_______________________________________________
Web-SIG mailing list
Web-SIG <at> python.org
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
PJ Eby | 24 May 2012 02:05
Gravatar

Re: websocket support in WSGI

On Wed, May 23, 2012 at 3:17 PM, Roberto De Ioris <roberto-5KDOxZqKugI@public.gmane.org> wrote:
Can't we simply define something like environ['wsgi.raw_socket'] (or
whatever name you want) mapping to the client (or webserver in case of
proxied) socket ?

Probably not.  What happens if middleware has already sent stuff to that socket, indirectly?  I suppose you could add some sort of status indicators to it.  What happens if the app writes to it, then returns to some middleware that expects to then start its own response?  What happens with program flow control in general?

I don't know if sane Websocket support is even *possible* in WSGI, but if it is, then there's a heck of a lot more to be specified there than just an environ key.

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Gmane