fixes gevent websocket example . close #343

This commit is contained in:
benoitc 2012-05-15 00:13:48 +02:00
parent 90e698aa3c
commit 7a32616407

View File

@ -10,6 +10,7 @@ import struct
import logging import logging
from socket import error as SocketError from socket import error as SocketError
import gevent
from gunicorn.workers.async import ALREADY_HANDLED from gunicorn.workers.async import ALREADY_HANDLED
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -85,8 +86,8 @@ class WebSocketWSGI(object):
"Sec-WebSocket-Version: %s\r\n" "Sec-WebSocket-Version: %s\r\n"
"Sec-WebSocket-Accept: %s\r\n\r\n" "Sec-WebSocket-Accept: %s\r\n\r\n"
% ( % (
environ.get('HTTP_ORIGIN'), environ.get('HTTP_ORIGIN'),
environ.get('HTTP_HOST'), environ.get('HTTP_HOST'),
ws.path, ws.path,
version, version,
base64.b64encode(sha1(key + WS_KEY).digest()) base64.b64encode(sha1(key + WS_KEY).digest())
@ -97,8 +98,8 @@ class WebSocketWSGI(object):
handshake_reply += ( handshake_reply += (
"WebSocket-Origin: %s\r\n" "WebSocket-Origin: %s\r\n"
"WebSocket-Location: ws://%s%s\r\n\r\n" % ( "WebSocket-Location: ws://%s%s\r\n\r\n" % (
environ.get('HTTP_ORIGIN'), environ.get('HTTP_ORIGIN'),
environ.get('HTTP_HOST'), environ.get('HTTP_HOST'),
ws.path)) ws.path))
sock.sendall(handshake_reply) sock.sendall(handshake_reply)
@ -192,7 +193,7 @@ class WebSocket(object):
""" """
f = {'fin' : 0, f = {'fin' : 0,
'opcode' : 0, 'opcode' : 0,
'mask' : 0, 'mask' : 0,
'hlen' : 2, 'hlen' : 2,
'length' : 0, 'length' : 0,
@ -341,10 +342,10 @@ class WebSocket(object):
raise ValueError("Don't understand how to parse this type of message: %r" % buf) raise ValueError("Don't understand how to parse this type of message: %r" % buf)
self._buf = buf self._buf = buf
return msgs return msgs
def send(self, message): def send(self, message):
"""Send a message to the browser. """Send a message to the browser.
*message* should be convertable to a string; unicode objects should be *message* should be convertable to a string; unicode objects should be
encodable as utf-8. Raises socket.error with errno of 32 encodable as utf-8. Raises socket.error with errno of 32
(broken pipe) if the socket has already been closed by the client.""" (broken pipe) if the socket has already been closed by the client."""
@ -362,8 +363,8 @@ class WebSocket(object):
#self._sendlock.release() #self._sendlock.release()
def wait(self): def wait(self):
"""Waits for and deserializes messages. """Waits for and deserializes messages.
Returns a single message; the oldest not yet processed. If the client Returns a single message; the oldest not yet processed. If the client
has already closed the connection, returns None. This is different has already closed the connection, returns None. This is different
from normal socket behavior because the empty string is a valid from normal socket behavior because the empty string is a valid
@ -408,3 +409,37 @@ class WebSocket(object):
self._send_closing_frame() self._send_closing_frame()
self.socket.shutdown(True) self.socket.shutdown(True)
self.socket.close() self.socket.close()
# demo app
import os
import random
def handle(ws):
""" This is the websocket handler function. Note that we
can dispatch based on path in here, too."""
if ws.path == '/echo':
while True:
m = ws.wait()
if m is None:
break
ws.send(m)
elif ws.path == '/data':
for i in xrange(10000):
ws.send("0 %s %s\n" % (i, random.random()))
gevent.sleep(0.1)
wsapp = WebSocketWSGI(handle)
def app(environ, start_response):
""" This resolves to the web page or the websocket depending on
the path."""
if environ['PATH_INFO'] == '/' or environ['PATH_INFO'] == "":
data = open(os.path.join(
os.path.dirname(__file__),
'websocket.html')).read()
data = data % environ
start_response('200 OK', [('Content-Type', 'text/html'),
('Content-Length', len(data))])
return [data]
else:
return wsapp(environ, start_response)