Fixing empty-query-string compatibility that mcarter reported, added unit tests for it, too.

This commit is contained in:
Ryan Williams
2010-10-24 21:01:12 -07:00
parent d10ed20586
commit e374a8d741
4 changed files with 69 additions and 13 deletions

View File

@@ -2,7 +2,7 @@
=====================================
This module provides a simple way to create a `websocket
<http://dev.w3.org/html5/websockets/>` server. It works with a few
<http://dev.w3.org/html5/websockets/>`_ server. It works with a few
tweaks in the :mod:`~eventlet.wsgi` module that allow websockets to
coexist with other WSGI applications.

View File

@@ -81,7 +81,7 @@ class WebSocketWSGI(object):
environ.get('PATH_INFO')
)
qs = environ.get('QUERY_STRING')
if qs:
if qs is not None:
location += '?' + qs
if self.protocol_version == 75:
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
@@ -212,9 +212,11 @@ class WebSocket(object):
return msgs
def send(self, message):
"""Send a message to the browser. *message* should be
convertable to a string; unicode objects should be encodable
as utf-8."""
"""Send a message to the browser.
*message* should be convertable to a string; unicode objects should be
encodable as utf-8. Raises socket.error with errno of 32
(broken pipe) if the socket has already been closed by the client."""
packed = self._pack_message(message)
# if two greenthreads are trying to send at the same time
# on the same socket, sendlock prevents interleaving and corruption
@@ -225,8 +227,12 @@ class WebSocket(object):
self._sendlock.release()
def wait(self):
"""Waits for and deserializes messages. Returns a single
message; the oldest not yet processed."""
"""Waits for and deserializes messages.
Returns a single message; the oldest not yet processed. If the client
has already closed the connection, returns None. This is different
from normal socket behavior because the empty string is a valid
websocket message."""
while not self._msgs:
# Websocket might be closed already.
if self.websocket_closed:

View File

@@ -402,12 +402,10 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
env['REQUEST_METHOD'] = self.command
env['SCRIPT_NAME'] = ''
if '?' in self.path:
path, query = self.path.split('?', 1)
else:
path, query = self.path, ''
env['PATH_INFO'] = urllib.unquote(path)
env['QUERY_STRING'] = query
pq = self.path.split('?', 1)
env['PATH_INFO'] = urllib.unquote(pq[0])
if len(pq) > 1:
env['QUERY_STRING'] = pq[1]
if self.headers.typeheader is None:
env['CONTENT_TYPE'] = self.headers.type

View File

@@ -145,6 +145,58 @@ class TestWebSocket(_TestBase):
'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
'Sec-WebSocket-Protocol: ws',
'Sec-WebSocket-Location: ws://localhost:%s/echo\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port]))
def test_query_string(self):
# verify that the query string comes out the other side unscathed
connect = [
"GET /echo?query_string HTTP/1.1",
"Upgrade: WebSocket",
"Connection: Upgrade",
"Host: localhost:%s" % self.port,
"Origin: http://localhost:%s" % self.port,
"Sec-WebSocket-Protocol: ws",
"Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5",
"Sec-WebSocket-Key2: 12998 5 Y3 1 .P00",
]
sock = eventlet.connect(
('localhost', self.port))
sock.sendall('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')
result = sock.recv(1024)
self.assertEqual(result,
'\r\n'.join(['HTTP/1.1 101 WebSocket Protocol Handshake',
'Upgrade: WebSocket',
'Connection: Upgrade',
'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
'Sec-WebSocket-Protocol: ws',
'Sec-WebSocket-Location: ws://localhost:%s/echo?query_string\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port]))
def test_empty_query_string(self):
# verify that a single trailing ? doesn't get nuked
connect = [
"GET /echo? HTTP/1.1",
"Upgrade: WebSocket",
"Connection: Upgrade",
"Host: localhost:%s" % self.port,
"Origin: http://localhost:%s" % self.port,
"Sec-WebSocket-Protocol: ws",
"Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5",
"Sec-WebSocket-Key2: 12998 5 Y3 1 .P00",
]
sock = eventlet.connect(
('localhost', self.port))
sock.sendall('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')
result = sock.recv(1024)
self.assertEqual(result,
'\r\n'.join(['HTTP/1.1 101 WebSocket Protocol Handshake',
'Upgrade: WebSocket',
'Connection: Upgrade',
'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
'Sec-WebSocket-Protocol: ws',
'Sec-WebSocket-Location: ws://localhost:%s/echo?\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port]))
def test_sending_messages_to_websocket_75(self):
connect = [