Fixing empty-query-string compatibility that mcarter reported, added unit tests for it, too.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
This module provides a simple way to create a `websocket
|
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
|
tweaks in the :mod:`~eventlet.wsgi` module that allow websockets to
|
||||||
coexist with other WSGI applications.
|
coexist with other WSGI applications.
|
||||||
|
|
||||||
|
@@ -81,7 +81,7 @@ class WebSocketWSGI(object):
|
|||||||
environ.get('PATH_INFO')
|
environ.get('PATH_INFO')
|
||||||
)
|
)
|
||||||
qs = environ.get('QUERY_STRING')
|
qs = environ.get('QUERY_STRING')
|
||||||
if qs:
|
if qs is not None:
|
||||||
location += '?' + qs
|
location += '?' + qs
|
||||||
if self.protocol_version == 75:
|
if self.protocol_version == 75:
|
||||||
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
||||||
@@ -212,9 +212,11 @@ class WebSocket(object):
|
|||||||
return msgs
|
return msgs
|
||||||
|
|
||||||
def send(self, message):
|
def send(self, message):
|
||||||
"""Send a message to the browser. *message* should be
|
"""Send a message to the browser.
|
||||||
convertable to a string; unicode objects should be encodable
|
|
||||||
as utf-8."""
|
*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)
|
packed = self._pack_message(message)
|
||||||
# if two greenthreads are trying to send at the same time
|
# if two greenthreads are trying to send at the same time
|
||||||
# on the same socket, sendlock prevents interleaving and corruption
|
# on the same socket, sendlock prevents interleaving and corruption
|
||||||
@@ -225,8 +227,12 @@ class WebSocket(object):
|
|||||||
self._sendlock.release()
|
self._sendlock.release()
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
"""Waits for and deserializes messages. Returns a single
|
"""Waits for and deserializes messages.
|
||||||
message; the oldest not yet processed."""
|
|
||||||
|
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:
|
while not self._msgs:
|
||||||
# Websocket might be closed already.
|
# Websocket might be closed already.
|
||||||
if self.websocket_closed:
|
if self.websocket_closed:
|
||||||
|
@@ -402,12 +402,10 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
env['REQUEST_METHOD'] = self.command
|
env['REQUEST_METHOD'] = self.command
|
||||||
env['SCRIPT_NAME'] = ''
|
env['SCRIPT_NAME'] = ''
|
||||||
|
|
||||||
if '?' in self.path:
|
pq = self.path.split('?', 1)
|
||||||
path, query = self.path.split('?', 1)
|
env['PATH_INFO'] = urllib.unquote(pq[0])
|
||||||
else:
|
if len(pq) > 1:
|
||||||
path, query = self.path, ''
|
env['QUERY_STRING'] = pq[1]
|
||||||
env['PATH_INFO'] = urllib.unquote(path)
|
|
||||||
env['QUERY_STRING'] = query
|
|
||||||
|
|
||||||
if self.headers.typeheader is None:
|
if self.headers.typeheader is None:
|
||||||
env['CONTENT_TYPE'] = self.headers.type
|
env['CONTENT_TYPE'] = self.headers.type
|
||||||
|
@@ -145,6 +145,58 @@ class TestWebSocket(_TestBase):
|
|||||||
'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
|
'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
|
||||||
'Sec-WebSocket-Protocol: ws',
|
'Sec-WebSocket-Protocol: ws',
|
||||||
'Sec-WebSocket-Location: ws://localhost:%s/echo\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port]))
|
'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):
|
def test_sending_messages_to_websocket_75(self):
|
||||||
connect = [
|
connect = [
|
||||||
|
Reference in New Issue
Block a user