Skip to content

Commit

Permalink
Merge pull request #1 from xeross/HEAD
Browse files Browse the repository at this point in the history
Update to use gevent-websocket instead of ws4py
  • Loading branch information
zeekay committed Apr 16, 2012
2 parents 4833e57 + 729ae1b commit 303d141
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 98 deletions.
2 changes: 1 addition & 1 deletion README.md
@@ -1,4 +1,4 @@
This project adds websocket capabilities to [bottle](http://bottlepy.org), leveraging [Websocket-for-Python](https://github.com/Lawouach/WebSocket-for-Python) and [gevent](http://www.gevent.org/). This project adds websocket capabilities to [bottle](http://bottlepy.org), leveraging [gevent-websocket](http://www.gelens.org/code/gevent-websocket/) and [gevent](http://www.gevent.org/).


Usage is pretty straight-forward, just import the server and plugin: Usage is pretty straight-forward, just import the server and plugin:


Expand Down
93 changes: 2 additions & 91 deletions bottle_websocket/plugin.py
@@ -1,96 +1,7 @@
import base64 from bottle import request
try:
import ujson as json
except ImportError:
try:
import simplejson as json
except ImportError:
try:
import json
except ImportError:
json = None

from hashlib import sha1

from bottle import request, HTTPError

from ws4py.exc import HandshakeError
from ws4py import WS_KEY
from ws4py.server.wsgi.middleware import WebSocketHandler

WS_VERSION = 8

CLOSE_SOCKET = True


def websocket(callback): def websocket(callback):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
try: callback(request.environ.get('wsgi.websocket'), *args, **kwargs)
if 'websocket' not in request.environ.get('upgrade.protocol', ''):
raise HandshakeError("Upgrade protocol is not websocket")

if request.environ.get('REQUEST_METHOD') != 'GET':
raise HandshakeError('Method is not GET')

key = request.environ.get('HTTP_SEC_WEBSOCKET_KEY')
if key:
ws_key = base64.b64decode(key)
if len(ws_key) != 16:
raise HandshakeError("WebSocket key's length is invalid")
else:
raise HandshakeError("Not a valid HyBi WebSocket request")

version = request.environ.get('HTTP_SEC_WEBSOCKET_VERSION')
if version:
if version != str(WS_VERSION):
raise HandshakeError('Unsupported WebSocket version')
request.environ['websocket.version'] = str(WS_VERSION)
else:
raise HandshakeError('WebSocket version required')
except HandshakeError, e:
raise HTTPError(code=400, output=e)

# Collect supported subprotocols
protocols = []
subprotocols = request.environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL')
ws_protocols = []
if subprotocols:
for s in subprotocols.split(','):
s = s.strip()
if s in protocols:
ws_protocols.append(s)

# Collect supported extensions
exts = []
ws_extensions = []
extensions = request.environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS')
if extensions:
for ext in extensions.split(','):
ext = ext.strip()
if ext in exts:
ws_extensions.append(ext)

# Build and start the HTTP response
headers = [
('Upgrade', 'websocket'),
('Connection', 'Upgrade'),
('Sec-WebSocket-Version', request.environ['websocket.version']),
('Sec-WebSocket-Accept', base64.b64encode(sha1(key + WS_KEY).digest())),
]
if ws_protocols:
headers.append(('Sec-WebSocket-Protocol', ', '.join(ws_protocols)))
if ws_extensions:
headers.append(('Sec-WebSocket-Extensions', ','.join(ws_extensions)))
socket = request.environ.get('upgrade.socket')
socket.send("HTTP/1.1 101 Switching Protocols\r\n")
for k,v in headers:
socket.send(': '.join([k,v]) + '\r\n')
socket.send('\r\n')


websocket = WebSocketHandler(socket, ws_protocols, ws_extensions, request.environ)
if json:
websocket.send_json = lambda msg: websocket.send(json.dumps(msg))
websocket.receive_json = lambda: json.loads(websocket.receive())
callback(websocket, *args, **kwargs)
if CLOSE_SOCKET:
websocket.close()
return wrapper return wrapper
8 changes: 3 additions & 5 deletions bottle_websocket/server.py
@@ -1,9 +1,7 @@
from bottle import ServerAdapter from bottle import ServerAdapter
from gevent import pywsgi, monkey, local from gevent import pywsgi
from ws4py.server.geventserver import UpgradableWSGIHandler from geventwebsocket.handler import WebSocketHandler
import threading


class GeventWebSocketServer(ServerAdapter): class GeventWebSocketServer(ServerAdapter):
def run(self, handler): def run(self, handler):
if not threading.local is local.local: monkey.patch_all() pywsgi.WSGIServer((self.host, self.port), handler, handler_class=WebSocketHandler).serve_forever()
pywsgi.WSGIServer((self.host, self.port), handler, handler_class=UpgradableWSGIHandler).serve_forever()
2 changes: 1 addition & 1 deletion requirements.txt
@@ -1,2 +1,2 @@
gevent gevent
git+https://github.com/progrium/WebSocket-for-Python.git gevent-websocket

0 comments on commit 303d141

Please sign in to comment.