update eventlet websocket example and fix gevent one

This commit is contained in:
benoitc 2010-07-08 18:49:15 +02:00
parent 94df88ca7c
commit b2db9df58f
2 changed files with 52 additions and 12 deletions

View File

@ -8,7 +8,7 @@
import collections
import errno
import re
from md5 import md5
from hashlib import md5
import socket
import struct
@ -44,7 +44,7 @@ class WebSocketWSGI(object):
return []
sock = environ['gunicorn.socket']
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 0)
ws = WebSocket(sock,
environ.get('HTTP_ORIGIN'),
environ.get('HTTP_WEBSOCKET_PROTOCOL'),
@ -167,7 +167,7 @@ def handle(ws):
ws.send("0 %s %s\n" % (i, random.random()))
gevent.sleep(0.1)
wsapp = WebSocketWSGI(handle, 'http://localhost:8000')
wsapp = WebSocketWSGI(handle)
def app(environ, start_response):
""" This resolves to the web page or the websocket depending on
the path."""

View File

@ -8,9 +8,14 @@
import collections
import errno
from hashlib import md5
import re
import socket
import struct
from gunicorn.workers.async import ALREADY_HANDLED
from eventlet import pools
import socket
import eventlet
from eventlet.common import get_errno
@ -20,6 +25,16 @@ class WebSocketWSGI(object):
def verify_client(self, ws):
pass
def _get_key_value(self, key_value):
if not key_value:
return
key_number = int(re.sub("\\D", "", key_value))
spaces = re.subn(" ", "", key_value)[1]
if key_number % spaces != 0:
return
part = key_number / spaces
return part
def __call__(self, environ, start_response):
if not (environ['HTTP_CONNECTION'] == 'Upgrade' and
@ -33,20 +48,45 @@ class WebSocketWSGI(object):
environ.get('HTTP_ORIGIN'),
environ.get('HTTP_WEBSOCKET_PROTOCOL'),
environ.get('PATH_INFO'))
self.verify_client(ws)
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"WebSocket-Origin: %s\r\n"
"WebSocket-Location: ws://%s%s\r\n\r\n" % (
environ.get('HTTP_ORIGIN'),
environ.get('HTTP_HOST'),
ws.path))
"Connection: Upgrade\r\n")
self.verify_client(ws)
key1 = self._get_key_value(environ.get('HTTP_SEC_WEBSOCKET_KEY1'))
key2 = self._get_key_value(environ.get('HTTP_SEC_WEBSOCKET_KEY2'))
if key1 and key2:
challenge = ""
challenge += struct.pack("!I", key1) # network byteorder int
challenge += struct.pack("!I", key2) # network byteorder int
challenge += environ['wsgi.input'].read()
handshake_reply += (
"Sec-WebSocket-Origin: %s\r\n"
"Sec-WebSocket-Location: ws://%s%s\r\n"
"Sec-WebSocket-Protocol: %s\r\n"
"\r\n%s" % (
environ.get('HTTP_ORIGIN'),
environ.get('HTTP_HOST'),
ws.path,
environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL'),
md5(challenge).digest()))
else:
handshake_reply += (
"WebSocket-Origin: %s\r\n"
"WebSocket-Location: ws://%s%s\r\n\r\n" % (
environ.get('HTTP_ORIGIN'),
environ.get('HTTP_HOST'),
ws.path))
sock.sendall(handshake_reply)
try:
self.handler(ws)
except socket.error, e:
if get_errno(e) != errno.EPIPE:
if e[0] != errno.EPIPE:
raise
# use this undocumented feature of grainbows to ensure that it
# doesn't barf on the fact that we didn't call start_response