Python 3 compat: Improve various bits
This includes changes to WSGI, websocket, bytes/str/unicode handling, SSL, backdoor, greenio and tests. Some comments and conditionals (PY2/PY3) were added for clarity GH issues: Closes #106 Closes #111 Closes #118 Closes #141 Incidentally should also close #135 (reopen if didn't) cc #6
This commit is contained in:
1
NEWS
1
NEWS
@@ -2,6 +2,7 @@
|
||||
=========================
|
||||
|
||||
* removed deprecated modules: api, most of coros, pool, proc, processes and util
|
||||
* improved Python 3 compatibility
|
||||
|
||||
0.15.2
|
||||
======
|
||||
|
@@ -7,7 +7,7 @@ import sys
|
||||
|
||||
import eventlet
|
||||
from eventlet import hubs
|
||||
from eventlet.support import greenlets, get_errno, six
|
||||
from eventlet.support import greenlets, get_errno
|
||||
|
||||
try:
|
||||
sys.ps1
|
||||
@@ -30,13 +30,11 @@ class FileProxy(object):
|
||||
pass
|
||||
|
||||
def write(self, data, *a, **kw):
|
||||
data = six.b(data)
|
||||
self.f.write(data, *a, **kw)
|
||||
self.f.flush()
|
||||
|
||||
def readline(self, *a):
|
||||
line = self.f.readline(*a).replace(b'\r\n', b'\n')
|
||||
return six.u(line)
|
||||
return self.f.readline(*a).replace('\r\n', '\n')
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.f, attr)
|
||||
|
@@ -7,7 +7,7 @@ import sys
|
||||
import errno
|
||||
time = __import__('time')
|
||||
|
||||
from eventlet.support import get_errno
|
||||
from eventlet.support import get_errno, six
|
||||
from eventlet.hubs import trampoline, IOClosed
|
||||
from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS
|
||||
orig_socket = __import__('socket')
|
||||
@@ -21,9 +21,10 @@ else:
|
||||
|
||||
__patched__ = ['SSLSocket', 'wrap_socket', 'sslwrap_simple']
|
||||
|
||||
_original_sslsocket = __ssl.SSLSocket
|
||||
|
||||
class GreenSSLSocket(__ssl.SSLSocket):
|
||||
|
||||
class GreenSSLSocket(_original_sslsocket):
|
||||
""" This is a green version of the SSLSocket class from the ssl module added
|
||||
in 2.6. For documentation on it, please see the Python standard
|
||||
documentation.
|
||||
@@ -40,23 +41,49 @@ class GreenSSLSocket(__ssl.SSLSocket):
|
||||
# we are inheriting from SSLSocket because its constructor calls
|
||||
# do_handshake whose behavior we wish to override
|
||||
|
||||
def __init__(self, sock, *args, **kw):
|
||||
def __init__(self, sock, keyfile=None, certfile=None,
|
||||
server_side=False, cert_reqs=CERT_NONE,
|
||||
ssl_version=PROTOCOL_SSLv23, ca_certs=None,
|
||||
do_handshake_on_connect=True, *args, **kw):
|
||||
if not isinstance(sock, GreenSocket):
|
||||
sock = GreenSocket(sock)
|
||||
|
||||
self.act_non_blocking = sock.act_non_blocking
|
||||
self._timeout = sock.gettimeout()
|
||||
super(GreenSSLSocket, self).__init__(sock.fd, *args, **kw)
|
||||
|
||||
if six.PY2:
|
||||
# On Python 2 SSLSocket constructor queries the timeout, it'd break without
|
||||
# this assignment
|
||||
self._timeout = sock.gettimeout()
|
||||
|
||||
# nonblocking socket handshaking on connect got disabled so let's pretend it's disabled
|
||||
# even when it's on
|
||||
super(GreenSSLSocket, self).__init__(
|
||||
sock.fd, keyfile, certfile, server_side,cert_reqs, ssl_version,
|
||||
ca_certs, do_handshake_on_connect and six.PY2, *args, **kw)
|
||||
|
||||
# the superclass initializer trashes the methods so we remove
|
||||
# the local-object versions of them and let the actual class
|
||||
# methods shine through
|
||||
# Note: This for Python 2
|
||||
try:
|
||||
for fn in orig_socket._delegate_methods:
|
||||
delattr(self, fn)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if six.PY3:
|
||||
# Python 3 SSLSocket construction process overwrites the timeout so restore it
|
||||
self._timeout = sock.gettimeout()
|
||||
|
||||
# it also sets timeout to None internally apparently (tested with 3.4.2)
|
||||
_original_sslsocket.settimeout(self, 0.0)
|
||||
assert _original_sslsocket.gettimeout(self) == 0.0
|
||||
|
||||
# see note above about handshaking
|
||||
self.do_handshake_on_connect = do_handshake_on_connect
|
||||
if do_handshake_on_connect and self._connected:
|
||||
self.do_handshake()
|
||||
|
||||
def settimeout(self, timeout):
|
||||
self._timeout = timeout
|
||||
|
||||
@@ -98,14 +125,14 @@ class GreenSSLSocket(__ssl.SSLSocket):
|
||||
return self._call_trampolining(
|
||||
super(GreenSSLSocket, self).write, data)
|
||||
|
||||
def read(self, len=1024):
|
||||
def read(self, *args, **kwargs):
|
||||
"""Read up to LEN bytes and return them.
|
||||
Return zero-length string on EOF."""
|
||||
try:
|
||||
return self._call_trampolining(
|
||||
super(GreenSSLSocket, self).read, len)
|
||||
super(GreenSSLSocket, self).read, *args, **kwargs)
|
||||
except IOClosed:
|
||||
return ''
|
||||
return b''
|
||||
|
||||
def send(self, data, flags=0):
|
||||
if self._sslobj:
|
||||
@@ -174,9 +201,9 @@ class GreenSSLSocket(__ssl.SSLSocket):
|
||||
trampoline(self, read=True,
|
||||
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
|
||||
except IOClosed:
|
||||
return ''
|
||||
return b''
|
||||
if get_errno(e) in SOCKET_CLOSED:
|
||||
return ''
|
||||
return b''
|
||||
raise
|
||||
|
||||
def recv_into(self, buffer, nbytes=None, flags=0):
|
||||
@@ -245,14 +272,16 @@ class GreenSSLSocket(__ssl.SSLSocket):
|
||||
if self._sslobj:
|
||||
raise ValueError("attempt to connect already-connected SSLSocket!")
|
||||
self._socket_connect(addr)
|
||||
if has_ciphers:
|
||||
self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
|
||||
self.cert_reqs, self.ssl_version,
|
||||
self.ca_certs, self.ciphers)
|
||||
server_side = False
|
||||
try:
|
||||
sslwrap = _ssl.sslwrap
|
||||
except AttributeError:
|
||||
# sslwrap was removed in 2.7.9
|
||||
self._sslobj = self._context._wrap_socket(self, server_side)
|
||||
else:
|
||||
self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
|
||||
self.cert_reqs, self.ssl_version,
|
||||
self.ca_certs)
|
||||
self._sslobj = sslwrap(self._sock, server_side, self.keyfile, self.certfile,
|
||||
self.cert_reqs, self.ssl_version,
|
||||
self.ca_certs, *([self.ciphers] if has_ciphers else []))
|
||||
if self.do_handshake_on_connect:
|
||||
self.do_handshake()
|
||||
|
||||
|
@@ -160,6 +160,15 @@ class GreenSocket(object):
|
||||
def _sock(self):
|
||||
return self
|
||||
|
||||
if six.PY3:
|
||||
def _get_io_refs(self):
|
||||
return self.fd._io_refs
|
||||
|
||||
def _set_io_refs(self, value):
|
||||
self.fd._io_refs = value
|
||||
|
||||
_io_refs = property(_get_io_refs, _set_io_refs)
|
||||
|
||||
# Forward unknown attributes to fd, cache the value for future use.
|
||||
# I do not see any simple attribute which could be changed
|
||||
# so caching everything in self is fine.
|
||||
@@ -275,12 +284,16 @@ class GreenSocket(object):
|
||||
newsock.settimeout(self.gettimeout())
|
||||
return newsock
|
||||
|
||||
def makefile(self, *args, **kw):
|
||||
dupped = self.dup()
|
||||
res = _fileobject(dupped, *args, **kw)
|
||||
if hasattr(dupped, "_drop"):
|
||||
dupped._drop()
|
||||
return res
|
||||
if six.PY3:
|
||||
def makefile(self, *args, **kwargs):
|
||||
return _original_socket.makefile(self, *args, **kwargs)
|
||||
else:
|
||||
def makefile(self, *args, **kwargs):
|
||||
dupped = self.dup()
|
||||
res = _fileobject(dupped, *args, **kwargs)
|
||||
if hasattr(dupped, "_drop"):
|
||||
dupped._drop()
|
||||
return res
|
||||
|
||||
def makeGreenFile(self, *args, **kw):
|
||||
warnings.warn("makeGreenFile has been deprecated, please use "
|
||||
@@ -457,11 +470,12 @@ class _SocketDuckForFd(object):
|
||||
def send(self, data):
|
||||
while True:
|
||||
try:
|
||||
os.write(self._fileno, data)
|
||||
return os.write(self._fileno, data)
|
||||
except OSError as e:
|
||||
if get_errno(e) not in SOCKET_BLOCKING:
|
||||
raise IOError(*e.args)
|
||||
trampoline(self, write=True)
|
||||
else:
|
||||
trampoline(self, write=True)
|
||||
|
||||
def sendall(self, data):
|
||||
len_data = len(data)
|
||||
|
@@ -37,15 +37,17 @@ for _mod in ('wsaccel.utf8validator', 'autobahn.utf8validator'):
|
||||
ACCEPTABLE_CLIENT_ERRORS = set((errno.ECONNRESET, errno.EPIPE))
|
||||
|
||||
__all__ = ["WebSocketWSGI", "WebSocket"]
|
||||
PROTOCOL_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
||||
VALID_CLOSE_STATUS = (range(1000, 1004)
|
||||
+ range(1007, 1012)
|
||||
# 3000-3999: reserved for use by libraries, frameworks,
|
||||
# and applications
|
||||
+ range(3000, 4000)
|
||||
# 4000-4999: reserved for private use and thus can't
|
||||
# be registered
|
||||
+ range(4000, 5000))
|
||||
PROTOCOL_GUID = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
||||
VALID_CLOSE_STATUS = set(
|
||||
list(range(1000, 1004)) +
|
||||
list(range(1007, 1012)) +
|
||||
# 3000-3999: reserved for use by libraries, frameworks,
|
||||
# and applications
|
||||
list(range(3000, 4000)) +
|
||||
# 4000-4999: reserved for private use and thus can't
|
||||
# be registered
|
||||
list(range(4000, 5000))
|
||||
)
|
||||
|
||||
|
||||
class BadRequest(Exception):
|
||||
@@ -115,7 +117,7 @@ class WebSocketWSGI(object):
|
||||
raise BadRequest()
|
||||
except BadRequest as e:
|
||||
status = e.status
|
||||
body = e.body or ''
|
||||
body = e.body or b''
|
||||
headers = e.headers or []
|
||||
start_response(status,
|
||||
[('Connection', 'close'), ] + headers)
|
||||
@@ -219,15 +221,14 @@ class WebSocketWSGI(object):
|
||||
# extensions = [i.strip() for i in extensions.split(',')]
|
||||
|
||||
key = environ['HTTP_SEC_WEBSOCKET_KEY']
|
||||
response = base64.b64encode(sha1(key + PROTOCOL_GUID).digest())
|
||||
handshake_reply = ["HTTP/1.1 101 Switching Protocols",
|
||||
"Upgrade: websocket",
|
||||
"Connection: Upgrade",
|
||||
"Sec-WebSocket-Accept: %s" % (response, )]
|
||||
response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest())
|
||||
handshake_reply = [b"HTTP/1.1 101 Switching Protocols",
|
||||
b"Upgrade: websocket",
|
||||
b"Connection: Upgrade",
|
||||
b"Sec-WebSocket-Accept: " + response]
|
||||
if negotiated_protocol:
|
||||
handshake_reply.append("Sec-WebSocket-Protocol: %s"
|
||||
% (negotiated_protocol, ))
|
||||
sock.sendall('\r\n'.join(handshake_reply) + '\r\n\r\n')
|
||||
handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol))
|
||||
sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n')
|
||||
return RFC6455WebSocket(sock, environ, self.protocol_version,
|
||||
protocol=negotiated_protocol)
|
||||
|
||||
@@ -425,7 +426,7 @@ class RFC6455WebSocket(WebSocket):
|
||||
return self.decoder.decode(data, final)
|
||||
|
||||
def _get_bytes(self, numbytes):
|
||||
data = ''
|
||||
data = b''
|
||||
while len(data) < numbytes:
|
||||
d = self.socket.recv(numbytes - len(data))
|
||||
if not d:
|
||||
@@ -447,14 +448,14 @@ class RFC6455WebSocket(WebSocket):
|
||||
self.data.append(data)
|
||||
|
||||
def getvalue(self):
|
||||
return ''.join(self.data)
|
||||
return ('' if self.decoder else b'').join(self.data)
|
||||
|
||||
@staticmethod
|
||||
def _apply_mask(data, mask, length=None, offset=0):
|
||||
if length is None:
|
||||
length = len(data)
|
||||
cnt = range(length)
|
||||
return ''.join(chr(ord(data[i]) ^ mask[(offset + i) % 4]) for i in cnt)
|
||||
return b''.join(six.int2byte(six.indexbytes(data, i) ^ mask[(offset + i) % 4]) for i in cnt)
|
||||
|
||||
def _handle_control_frame(self, opcode, data):
|
||||
if opcode == 8: # connection close
|
||||
@@ -609,12 +610,13 @@ class RFC6455WebSocket(WebSocket):
|
||||
# NOTE: RFC6455 states:
|
||||
# A server MUST NOT mask any frames that it sends to the client
|
||||
rand = Random(time.time())
|
||||
mask = map(rand.getrandbits, (8, ) * 4)
|
||||
mask = [rand.getrandbits(8) for _ in six.moves.xrange(4)]
|
||||
message = RFC6455WebSocket._apply_mask(message, mask, length)
|
||||
maskdata = struct.pack('!BBBB', *mask)
|
||||
else:
|
||||
maskdata = ''
|
||||
return ''.join((header, lengthdata, maskdata, message))
|
||||
maskdata = b''
|
||||
|
||||
return b''.join((header, lengthdata, maskdata, message))
|
||||
|
||||
def wait(self):
|
||||
for i in self.iterator:
|
||||
|
@@ -116,11 +116,11 @@ class Input(object):
|
||||
if length and length > self.content_length - self.position:
|
||||
length = self.content_length - self.position
|
||||
if not length:
|
||||
return ''
|
||||
return b''
|
||||
try:
|
||||
read = reader(length)
|
||||
except greenio.SSL.ZeroReturnError:
|
||||
read = ''
|
||||
read = b''
|
||||
self.position += len(read)
|
||||
return read
|
||||
|
||||
@@ -189,7 +189,7 @@ class Input(object):
|
||||
return self._do_read(self.rfile.readlines, hint)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.read, '')
|
||||
return iter(self.read, b'')
|
||||
|
||||
def get_socket(self):
|
||||
return self.rfile._sock
|
||||
@@ -226,7 +226,7 @@ class FileObjectForHeaders(object):
|
||||
if size < 0:
|
||||
sz = MAX_HEADER_LINE
|
||||
rv = self.fp.readline(sz)
|
||||
if size < 0 and len(rv) >= MAX_HEADER_LINE:
|
||||
if len(rv) >= MAX_HEADER_LINE:
|
||||
raise HeaderLineTooLong()
|
||||
self.total_header_size += len(rv)
|
||||
if self.total_header_size > MAX_TOTAL_HEADER_SIZE:
|
||||
@@ -267,8 +267,8 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
self.raw_requestline = self.rfile.readline(self.server.url_length_limit)
|
||||
if len(self.raw_requestline) == self.server.url_length_limit:
|
||||
self.wfile.write(
|
||||
"HTTP/1.0 414 Request URI Too Long\r\n"
|
||||
"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
b"HTTP/1.0 414 Request URI Too Long\r\n"
|
||||
b"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
self.close_connection = 1
|
||||
return
|
||||
except greenio.SSL.ZeroReturnError:
|
||||
@@ -289,14 +289,14 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
return
|
||||
except HeaderLineTooLong:
|
||||
self.wfile.write(
|
||||
"HTTP/1.0 400 Header Line Too Long\r\n"
|
||||
"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
b"HTTP/1.0 400 Header Line Too Long\r\n"
|
||||
b"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
self.close_connection = 1
|
||||
return
|
||||
except HeadersTooLarge:
|
||||
self.wfile.write(
|
||||
"HTTP/1.0 400 Headers Too Large\r\n"
|
||||
"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
b"HTTP/1.0 400 Headers Too Large\r\n"
|
||||
b"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
self.close_connection = 1
|
||||
return
|
||||
finally:
|
||||
@@ -308,8 +308,8 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
int(content_length)
|
||||
except ValueError:
|
||||
self.wfile.write(
|
||||
"HTTP/1.0 400 Bad Request\r\n"
|
||||
"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
b"HTTP/1.0 400 Bad Request\r\n"
|
||||
b"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||
self.close_connection = 1
|
||||
return
|
||||
|
||||
@@ -345,13 +345,13 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
status, response_headers = headers_set
|
||||
headers_sent.append(1)
|
||||
header_list = [header[0].lower() for header in response_headers]
|
||||
towrite.append('%s %s\r\n' % (self.protocol_version, status))
|
||||
towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status)))
|
||||
for header in response_headers:
|
||||
towrite.append('%s: %s\r\n' % header)
|
||||
towrite.append(six.b('%s: %s\r\n' % header))
|
||||
|
||||
# send Date header?
|
||||
if 'date' not in header_list:
|
||||
towrite.append('Date: %s\r\n' % (format_date_time(time.time()),))
|
||||
towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),)))
|
||||
|
||||
client_conn = self.headers.get('Connection', '').lower()
|
||||
send_keep_alive = False
|
||||
@@ -369,21 +369,21 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
if 'content-length' not in header_list:
|
||||
if self.request_version == 'HTTP/1.1':
|
||||
use_chunked[0] = True
|
||||
towrite.append('Transfer-Encoding: chunked\r\n')
|
||||
towrite.append(b'Transfer-Encoding: chunked\r\n')
|
||||
elif 'content-length' not in header_list:
|
||||
# client is 1.0 and therefore must read to EOF
|
||||
self.close_connection = 1
|
||||
|
||||
if self.close_connection:
|
||||
towrite.append('Connection: close\r\n')
|
||||
towrite.append(b'Connection: close\r\n')
|
||||
elif send_keep_alive:
|
||||
towrite.append('Connection: keep-alive\r\n')
|
||||
towrite.append('\r\n')
|
||||
towrite.append(b'Connection: keep-alive\r\n')
|
||||
towrite.append(b'\r\n')
|
||||
# end of header writing
|
||||
|
||||
if use_chunked[0]:
|
||||
# Write the chunked encoding
|
||||
towrite.append("%x\r\n%s\r\n" % (len(data), data))
|
||||
towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n")
|
||||
else:
|
||||
towrite.append(data)
|
||||
try:
|
||||
@@ -450,15 +450,15 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
towrite.append(data)
|
||||
towrite_size += len(data)
|
||||
if towrite_size >= minimum_write_chunk_size:
|
||||
write(''.join(towrite))
|
||||
write(b''.join(towrite))
|
||||
towrite = []
|
||||
just_written_size = towrite_size
|
||||
towrite_size = 0
|
||||
if towrite:
|
||||
just_written_size = towrite_size
|
||||
write(''.join(towrite))
|
||||
write(b''.join(towrite))
|
||||
if not headers_sent or (use_chunked[0] and just_written_size):
|
||||
write('')
|
||||
write(b'')
|
||||
except Exception:
|
||||
self.close_connection = 1
|
||||
tb = traceback.format_exc()
|
||||
@@ -476,7 +476,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
result.close()
|
||||
if (self.environ['eventlet.input'].chunked_input or
|
||||
self.environ['eventlet.input'].position
|
||||
< self.environ['eventlet.input'].content_length):
|
||||
< self.environ['eventlet.input'].content_length or 0):
|
||||
# Read and discard body if there was no pending 100-continue
|
||||
if not self.environ['eventlet.input'].wfile:
|
||||
# NOTE: MINIMUM_CHUNK_SIZE is used here for purpose different than chunking.
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import os
|
||||
import socket
|
||||
from unittest import TestCase, main
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
import eventlet
|
||||
from eventlet import greenio, hubs, greenthread, spawn
|
||||
from eventlet.green import ssl
|
||||
@@ -51,9 +52,8 @@ class TestApi(TestCase):
|
||||
client = eventlet.connect(('127.0.0.1', server.getsockname()[1]))
|
||||
fd = client.makefile('rb')
|
||||
client.close()
|
||||
assert fd.readline() == b'hello\n'
|
||||
|
||||
assert fd.read() == b''
|
||||
eq_(fd.readline(), b'hello\n')
|
||||
eq_(fd.read(), b'')
|
||||
fd.close()
|
||||
|
||||
check_hub()
|
||||
@@ -80,7 +80,7 @@ class TestApi(TestCase):
|
||||
|
||||
raw_client = eventlet.connect(('127.0.0.1', server.getsockname()[1]))
|
||||
client = ssl.wrap_socket(raw_client)
|
||||
fd = socket._fileobject(client, 'rb', 8192)
|
||||
fd = client.makefile('rb', 8192)
|
||||
|
||||
assert fd.readline() == b'hello\r\n'
|
||||
try:
|
||||
|
@@ -14,15 +14,15 @@ class BackdoorTest(LimitedTestCase):
|
||||
client = socket.socket()
|
||||
client.connect(('localhost', listener.getsockname()[1]))
|
||||
f = client.makefile('rw')
|
||||
assert b'Python' in f.readline()
|
||||
assert 'Python' in f.readline()
|
||||
f.readline() # build info
|
||||
f.readline() # help info
|
||||
assert b'InteractiveConsole' in f.readline()
|
||||
self.assertEqual(b'>>> ', f.read(4))
|
||||
f.write(b'print("hi")\n')
|
||||
assert 'InteractiveConsole' in f.readline()
|
||||
self.assertEqual('>>> ', f.read(4))
|
||||
f.write('print("hi")\n')
|
||||
f.flush()
|
||||
self.assertEqual(b'hi\n', f.readline())
|
||||
self.assertEqual(b'>>> ', f.read(4))
|
||||
self.assertEqual('hi\n', f.readline())
|
||||
self.assertEqual('>>> ', f.read(4))
|
||||
f.close()
|
||||
client.close()
|
||||
serv.kill()
|
||||
|
@@ -125,8 +125,8 @@ class TestServe(LimitedTestCase):
|
||||
|
||||
eventlet.spawn(eventlet.serve, server, handle)
|
||||
client = eventlet.wrap_ssl(eventlet.connect(('localhost', port)))
|
||||
client.sendall("echo")
|
||||
self.assertEqual("echo", client.recv(1024))
|
||||
client.sendall(b"echo")
|
||||
self.assertEqual(b"echo", client.recv(1024))
|
||||
|
||||
def test_socket_reuse(self):
|
||||
lsock1 = eventlet.listen(('localhost', 0))
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from eventlet.support import six
|
||||
from tests.patcher_test import ProcessBase
|
||||
from tests import skip_with_pyevent
|
||||
|
||||
|
@@ -450,7 +450,7 @@ class TestGreenSocket(LimitedTestCase):
|
||||
|
||||
def sender(evt):
|
||||
s2, addr = server.accept()
|
||||
wrap_wfile = s2.makefile('w')
|
||||
wrap_wfile = s2.makefile('wb')
|
||||
|
||||
eventlet.sleep(0.02)
|
||||
wrap_wfile.write(b'hi')
|
||||
@@ -627,7 +627,7 @@ class TestGreenPipe(LimitedTestCase):
|
||||
wf = greenio.GreenPipe(w, 'w', 0)
|
||||
|
||||
def sender(f, content):
|
||||
for ch in content:
|
||||
for ch in map(six.int2byte, six.iterbytes(content)):
|
||||
eventlet.sleep(0.0001)
|
||||
f.write(ch)
|
||||
f.close()
|
||||
@@ -638,7 +638,7 @@ class TestGreenPipe(LimitedTestCase):
|
||||
line = rf.readline()
|
||||
eventlet.sleep(0.01)
|
||||
self.assertEqual(line, one_line)
|
||||
self.assertEqual(rf.readline(), '')
|
||||
self.assertEqual(rf.readline(), b'')
|
||||
|
||||
def test_pipe_read(self):
|
||||
# ensure that 'readline' works properly on GreenPipes when data is not
|
||||
@@ -663,10 +663,10 @@ class TestGreenPipe(LimitedTestCase):
|
||||
eventlet.sleep(0)
|
||||
|
||||
line = r.readline()
|
||||
self.assertEqual(line, 'line\n')
|
||||
self.assertEqual(line, b'line\n')
|
||||
|
||||
line = r.readline()
|
||||
self.assertEqual(line, 'line\r\n')
|
||||
self.assertEqual(line, b'line\r\n')
|
||||
|
||||
gt.wait()
|
||||
|
||||
@@ -676,7 +676,7 @@ class TestGreenPipe(LimitedTestCase):
|
||||
r = greenio.GreenPipe(r)
|
||||
w = greenio.GreenPipe(w, 'w')
|
||||
|
||||
large_message = b"".join([1024 * chr(i) for i in range(65)])
|
||||
large_message = b"".join([1024 * six.int2byte(i) for i in range(65)])
|
||||
|
||||
def writer():
|
||||
w.write(large_message)
|
||||
|
@@ -1,12 +1,12 @@
|
||||
from __future__ import print_function
|
||||
import MySQLdb as m
|
||||
from eventlet import patcher
|
||||
from eventlet.green import MySQLdb as gm
|
||||
|
||||
# no standard tests in this file, ignore
|
||||
__test__ = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
import MySQLdb as m
|
||||
from eventlet.green import MySQLdb as gm
|
||||
patcher.monkey_patch(all=True, MySQLdb=True)
|
||||
print("mysqltest {0}".format(",".join(sorted(patcher.already_patched.keys()))))
|
||||
print("connect {0}".format(m.connect == gm.connect))
|
||||
|
@@ -3,12 +3,16 @@ import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from eventlet.support import six
|
||||
from tests import LimitedTestCase, main, run_python, skip_with_pyevent
|
||||
|
||||
|
||||
base_module_contents = """
|
||||
import socket
|
||||
import urllib
|
||||
try:
|
||||
import urllib.request as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
print("base {0} {1}".format(socket, urllib))
|
||||
"""
|
||||
|
||||
@@ -45,14 +49,18 @@ class ProcessBase(LimitedTestCase):
|
||||
filename = os.path.join(self.tempdir, name)
|
||||
if not filename.endswith('.py'):
|
||||
filename = filename + '.py'
|
||||
fd = open(filename, "wb")
|
||||
fd.write(contents)
|
||||
fd.close()
|
||||
with open(filename, "w") as fd:
|
||||
fd.write(contents)
|
||||
|
||||
def launch_subprocess(self, filename):
|
||||
path = os.path.join(self.tempdir, filename)
|
||||
output = run_python(path)
|
||||
lines = output.split("\n")
|
||||
if six.PY3:
|
||||
output = output.decode('utf-8')
|
||||
separator = '\n'
|
||||
else:
|
||||
separator = b'\n'
|
||||
lines = output.split(separator)
|
||||
return output, lines
|
||||
|
||||
def run_script(self, contents, modname=None):
|
||||
@@ -98,7 +106,10 @@ class MonkeyPatch(ProcessBase):
|
||||
from eventlet import patcher
|
||||
patcher.monkey_patch()
|
||||
import socket
|
||||
import urllib
|
||||
try:
|
||||
import urllib.request as urllib
|
||||
except ImportError:
|
||||
import urllib
|
||||
print("newmod {0} {1}".format(socket.socket, urllib.socket.socket))
|
||||
"""
|
||||
self.write_to_tempfile("newmod", new_mod)
|
||||
|
@@ -1,11 +1,15 @@
|
||||
import errno
|
||||
import struct
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
import eventlet
|
||||
from eventlet import event
|
||||
from eventlet import websocket
|
||||
from eventlet.green import httplib
|
||||
from eventlet.green import socket
|
||||
from eventlet import websocket
|
||||
from eventlet.support import six
|
||||
|
||||
from tests.wsgi_test import _TestBase
|
||||
|
||||
@@ -51,7 +55,7 @@ class TestWebSocket(_TestBase):
|
||||
|
||||
self.assertEqual(resp.status, 400)
|
||||
self.assertEqual(resp.getheader('connection'), 'close')
|
||||
self.assertEqual(resp.read(), '')
|
||||
self.assertEqual(resp.read(), b'')
|
||||
|
||||
# Now, miss off key
|
||||
headers = dict(kv.split(': ') for kv in [
|
||||
@@ -67,7 +71,7 @@ class TestWebSocket(_TestBase):
|
||||
|
||||
self.assertEqual(resp.status, 400)
|
||||
self.assertEqual(resp.getheader('connection'), 'close')
|
||||
self.assertEqual(resp.read(), '')
|
||||
self.assertEqual(resp.read(), b'')
|
||||
|
||||
# No Upgrade now
|
||||
headers = dict(kv.split(': ') for kv in [
|
||||
@@ -82,7 +86,7 @@ class TestWebSocket(_TestBase):
|
||||
|
||||
self.assertEqual(resp.status, 400)
|
||||
self.assertEqual(resp.getheader('connection'), 'close')
|
||||
self.assertEqual(resp.read(), '')
|
||||
self.assertEqual(resp.read(), b'')
|
||||
|
||||
def test_correct_upgrade_request_13(self):
|
||||
for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
|
||||
@@ -97,16 +101,16 @@ class TestWebSocket(_TestBase):
|
||||
]
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
|
||||
sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
|
||||
sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
|
||||
result = sock.recv(1024)
|
||||
# The server responds the correct Websocket handshake
|
||||
print('Connection string: %r' % http_connection)
|
||||
self.assertEqual(result, '\r\n'.join([
|
||||
self.assertEqual(result, six.b('\r\n'.join([
|
||||
'HTTP/1.1 101 Switching Protocols',
|
||||
'Upgrade: websocket',
|
||||
'Connection: Upgrade',
|
||||
'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
|
||||
]))
|
||||
])))
|
||||
|
||||
def test_send_recv_13(self):
|
||||
connect = [
|
||||
@@ -121,15 +125,15 @@ class TestWebSocket(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
|
||||
sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
|
||||
sock.recv(1024)
|
||||
ws = websocket.RFC6455WebSocket(sock, {}, client=True)
|
||||
ws.send('hello')
|
||||
assert ws.wait() == 'hello'
|
||||
ws.send('hello world!\x01')
|
||||
ws.send(b'hello')
|
||||
eq_(ws.wait(), b'hello')
|
||||
ws.send(b'hello world!\x01')
|
||||
ws.send(u'hello world again!')
|
||||
assert ws.wait() == 'hello world!\x01'
|
||||
assert ws.wait() == u'hello world again!'
|
||||
eq_(ws.wait(), b'hello world!\x01')
|
||||
eq_(ws.wait(), u'hello world again!')
|
||||
ws.close()
|
||||
eventlet.sleep(0.01)
|
||||
|
||||
@@ -160,7 +164,7 @@ class TestWebSocket(_TestBase):
|
||||
]
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
|
||||
sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
|
||||
sock.recv(1024) # get the headers
|
||||
sock.close() # close while the app is running
|
||||
done_with_request.wait()
|
||||
@@ -193,7 +197,7 @@ class TestWebSocket(_TestBase):
|
||||
]
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
|
||||
sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
|
||||
sock.recv(1024) # get the headers
|
||||
closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
|
||||
sock.sendall(closeframe) # "Close the connection" packet.
|
||||
@@ -227,8 +231,8 @@ class TestWebSocket(_TestBase):
|
||||
]
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
|
||||
sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
|
||||
sock.recv(1024) # get the headers
|
||||
sock.sendall('\x07\xff') # Weird packet.
|
||||
sock.sendall(b'\x07\xff') # Weird packet.
|
||||
done_with_request.wait()
|
||||
assert not error_detected[0]
|
||||
|
@@ -27,6 +27,13 @@ import tests
|
||||
certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
|
||||
private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
|
||||
|
||||
if six.PY3:
|
||||
def bytes_to_str(b):
|
||||
return b.decode()
|
||||
else:
|
||||
def bytes_to_str(b):
|
||||
return b
|
||||
|
||||
|
||||
HttpReadResult = collections.namedtuple(
|
||||
'HttpReadResult',
|
||||
@@ -36,17 +43,17 @@ HttpReadResult = collections.namedtuple(
|
||||
def hello_world(env, start_response):
|
||||
if env['PATH_INFO'] == 'notexist':
|
||||
start_response('404 Not Found', [('Content-type', 'text/plain')])
|
||||
return ["not found"]
|
||||
return [b"not found"]
|
||||
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
return ["hello world"]
|
||||
return [b"hello world"]
|
||||
|
||||
|
||||
def chunked_app(env, start_response):
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
yield "this"
|
||||
yield "is"
|
||||
yield "chunked"
|
||||
yield b"this"
|
||||
yield b"is"
|
||||
yield b"chunked"
|
||||
|
||||
|
||||
def chunked_fail_app(environ, start_response):
|
||||
@@ -56,8 +63,8 @@ def chunked_fail_app(environ, start_response):
|
||||
start_response('200 OK', headers)
|
||||
|
||||
# We start streaming data just fine.
|
||||
yield "The dwarves of yore made mighty spells,"
|
||||
yield "While hammers fell like ringing bells"
|
||||
yield b"The dwarves of yore made mighty spells,"
|
||||
yield b"While hammers fell like ringing bells"
|
||||
|
||||
# Then the back-end fails!
|
||||
try:
|
||||
@@ -67,13 +74,13 @@ def chunked_fail_app(environ, start_response):
|
||||
return
|
||||
|
||||
# So rest of the response data is not available.
|
||||
yield "In places deep, where dark things sleep,"
|
||||
yield "In hollow halls beneath the fells."
|
||||
yield b"In places deep, where dark things sleep,"
|
||||
yield b"In hollow halls beneath the fells."
|
||||
|
||||
|
||||
def big_chunks(env, start_response):
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
line = 'a' * 8192
|
||||
line = b'a' * 8192
|
||||
for x in range(10):
|
||||
yield line
|
||||
|
||||
@@ -150,11 +157,13 @@ class ConnectionClosed(Exception):
|
||||
|
||||
|
||||
def read_http(sock):
|
||||
fd = sock.makefile()
|
||||
fd = sock.makefile('rb')
|
||||
try:
|
||||
response_line = fd.readline().rstrip('\r\n')
|
||||
response_line = bytes_to_str(fd.readline().rstrip(b'\r\n'))
|
||||
except socket.error as exc:
|
||||
if support.get_errno(exc) == 10053:
|
||||
# TODO find out whether 54 is ok here or not, I see it when running tests
|
||||
# on Python 3
|
||||
if support.get_errno(exc) in (10053, 54):
|
||||
raise ConnectionClosed
|
||||
raise
|
||||
if not response_line:
|
||||
@@ -163,7 +172,7 @@ def read_http(sock):
|
||||
header_lines = []
|
||||
while True:
|
||||
line = fd.readline()
|
||||
if line == '\r\n':
|
||||
if line == b'\r\n':
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
@@ -174,7 +183,7 @@ def read_http(sock):
|
||||
x = x.strip()
|
||||
if not x:
|
||||
continue
|
||||
key, value = x.split(':', 1)
|
||||
key, value = bytes_to_str(x).split(':', 1)
|
||||
key = key.rstrip()
|
||||
value = value.lstrip()
|
||||
key_lower = key.lower()
|
||||
@@ -256,20 +265,20 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result = fd.read()
|
||||
fd.close()
|
||||
# The server responds with the maximum version it supports
|
||||
assert result.startswith('HTTP'), result
|
||||
assert result.endswith('hello world'), result
|
||||
assert result.startswith(b'HTTP'), result
|
||||
assert result.endswith(b'hello world'), result
|
||||
|
||||
def test_002_keepalive(self):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
read_http(sock)
|
||||
@@ -284,7 +293,7 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
cancel = eventlet.Timeout(1, RuntimeError)
|
||||
@@ -296,7 +305,7 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
read_http(sock)
|
||||
@@ -323,8 +332,8 @@ class TestHttpd(_TestBase):
|
||||
for ii in range(3000):
|
||||
path_parts.append('path')
|
||||
path = '/'.join(path_parts)
|
||||
request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
|
||||
fd = sock.makefile('rw')
|
||||
request = ('GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path).encode()
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(request)
|
||||
fd.flush()
|
||||
result = fd.readline()
|
||||
@@ -352,8 +361,8 @@ class TestHttpd(_TestBase):
|
||||
'Content-Length: 3',
|
||||
'',
|
||||
'a=a'))
|
||||
fd = sock.makefile('w')
|
||||
fd.write(request)
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(request.encode())
|
||||
fd.flush()
|
||||
|
||||
# send some junk after the actual request
|
||||
@@ -365,7 +374,7 @@ class TestHttpd(_TestBase):
|
||||
def test_008_correctresponse(self):
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result_200 = read_http(sock)
|
||||
@@ -384,37 +393,37 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
assert 'Transfer-Encoding: chunked' in fd.read()
|
||||
assert b'Transfer-Encoding: chunked' in fd.read()
|
||||
|
||||
def test_010_no_chunked_http_1_0(self):
|
||||
self.site.application = chunked_app
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
assert 'Transfer-Encoding: chunked' not in fd.read()
|
||||
assert b'Transfer-Encoding: chunked' not in fd.read()
|
||||
|
||||
def test_011_multiple_chunks(self):
|
||||
self.site.application = big_chunks
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
headers = ''
|
||||
headers = b''
|
||||
while True:
|
||||
line = fd.readline()
|
||||
if line == '\r\n':
|
||||
if line == b'\r\n':
|
||||
break
|
||||
else:
|
||||
headers += line
|
||||
assert 'Transfer-Encoding: chunked' in headers
|
||||
assert b'Transfer-Encoding: chunked' in headers
|
||||
chunks = 0
|
||||
chunklen = int(fd.readline(), 16)
|
||||
while chunklen:
|
||||
@@ -473,52 +482,52 @@ class TestHttpd(_TestBase):
|
||||
def test_014_chunked_post(self):
|
||||
self.site.application = chunked_post
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write('PUT /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
|
||||
'Transfer-Encoding: chunked\r\n\r\n'
|
||||
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
|
||||
fd.flush()
|
||||
while True:
|
||||
if fd.readline() == '\r\n':
|
||||
if fd.readline() == b'\r\n':
|
||||
break
|
||||
response = fd.read()
|
||||
assert response == 'oh hai', 'invalid response %s' % response
|
||||
assert response == b'oh hai', 'invalid response %s' % response
|
||||
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write('PUT /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
|
||||
'Transfer-Encoding: chunked\r\n\r\n'
|
||||
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
|
||||
fd.flush()
|
||||
while True:
|
||||
if fd.readline() == '\r\n':
|
||||
if fd.readline() == b'\r\n':
|
||||
break
|
||||
response = fd.read()
|
||||
assert response == 'oh hai', 'invalid response %s' % response
|
||||
assert response == b'oh hai', 'invalid response %s' % response
|
||||
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write('PUT /c HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
|
||||
'Transfer-Encoding: chunked\r\n\r\n'
|
||||
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
|
||||
fd.flush()
|
||||
while True:
|
||||
if fd.readline() == '\r\n':
|
||||
if fd.readline() == b'\r\n':
|
||||
break
|
||||
response = fd.read(8192)
|
||||
assert response == 'oh hai', 'invalid response %s' % response
|
||||
assert response == b'oh hai', 'invalid response %s' % response
|
||||
|
||||
def test_015_write(self):
|
||||
self.site.application = use_write
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
result1 = read_http(sock)
|
||||
assert 'content-length' in result1.headers_lower
|
||||
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
result2 = read_http(sock)
|
||||
@@ -531,21 +540,21 @@ class TestHttpd(_TestBase):
|
||||
"""
|
||||
def wsgi_app(environ, start_response):
|
||||
start_response('200 OK', [('Content-Length', '7')])
|
||||
return ['testing']
|
||||
return [b'testing']
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
header_lines = []
|
||||
while True:
|
||||
line = fd.readline()
|
||||
if line == '\r\n':
|
||||
if line == b'\r\n':
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
self.assertEqual(1, len(
|
||||
[l for l in header_lines if l.lower().startswith('content-length')]))
|
||||
[l for l in header_lines if l.lower().startswith(b'content-length')]))
|
||||
|
||||
@tests.skip_if_no_ssl
|
||||
def test_017_ssl_zeroreturnerror(self):
|
||||
@@ -588,7 +597,7 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
|
||||
fd.flush()
|
||||
|
||||
@@ -607,13 +616,13 @@ class TestHttpd(_TestBase):
|
||||
def use_fieldstorage(environ, start_response):
|
||||
cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
return ['hello!']
|
||||
return [b'hello!']
|
||||
|
||||
self.site.application = use_fieldstorage
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write('POST / HTTP/1.1\r\n'
|
||||
'Host: localhost\r\n'
|
||||
'Connection: close\r\n'
|
||||
@@ -621,7 +630,7 @@ class TestHttpd(_TestBase):
|
||||
'2\r\noh\r\n'
|
||||
'4\r\n hai\r\n0\r\n\r\n'.encode())
|
||||
fd.flush()
|
||||
assert 'hello!' in fd.read()
|
||||
assert b'hello!' in fd.read()
|
||||
|
||||
def test_020_x_forwarded_for(self):
|
||||
request_bytes = (
|
||||
@@ -654,13 +663,13 @@ class TestHttpd(_TestBase):
|
||||
self.spawn_server(sock=server_sock_2)
|
||||
# do a single req/response to verify it's up
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result = fd.read(1024)
|
||||
fd.close()
|
||||
assert result.startswith('HTTP'), result
|
||||
assert result.endswith('hello world')
|
||||
assert result.startswith(b'HTTP'), result
|
||||
assert result.endswith(b'hello world'), result
|
||||
|
||||
# shut down the server and verify the server_socket fd is still open,
|
||||
# but the actual socketobject passed in to wsgi.server is closed
|
||||
@@ -673,13 +682,13 @@ class TestHttpd(_TestBase):
|
||||
self.assertEqual(support.get_errno(exc), errno.EBADF)
|
||||
self.spawn_server(sock=server_sock)
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result = fd.read(1024)
|
||||
fd.close()
|
||||
assert result.startswith('HTTP'), result
|
||||
assert result.endswith('hello world')
|
||||
assert result.startswith(b'HTTP'), result
|
||||
assert result.endswith(b'hello world'), result
|
||||
|
||||
def test_021_environ_clobbering(self):
|
||||
def clobberin_time(environ, start_response):
|
||||
@@ -695,13 +704,13 @@ class TestHttpd(_TestBase):
|
||||
return []
|
||||
self.site.application = clobberin_time
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write('GET / HTTP/1.1\r\n'
|
||||
'Host: localhost\r\n'
|
||||
'Connection: close\r\n'
|
||||
'\r\n\r\n'.encode())
|
||||
fd.flush()
|
||||
assert '200 OK' in fd.read()
|
||||
assert b'200 OK' in fd.read()
|
||||
|
||||
def test_022_custom_pool(self):
|
||||
# just test that it accepts the parameter for now
|
||||
@@ -713,44 +722,44 @@ class TestHttpd(_TestBase):
|
||||
# this stuff is copied from test_001_server, could be better factored
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result = fd.read()
|
||||
fd.close()
|
||||
assert result.startswith('HTTP'), result
|
||||
assert result.endswith('hello world')
|
||||
assert result.startswith(b'HTTP'), result
|
||||
assert result.endswith(b'hello world'), result
|
||||
|
||||
def test_023_bad_content_length(self):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nContent-length: argh\r\n\r\n')
|
||||
fd.flush()
|
||||
result = fd.read()
|
||||
fd.close()
|
||||
assert result.startswith('HTTP'), result
|
||||
assert '400 Bad Request' in result
|
||||
assert '500' not in result
|
||||
assert result.startswith(b'HTTP'), result
|
||||
assert b'400 Bad Request' in result, result
|
||||
assert b'500' not in result, result
|
||||
|
||||
def test_024_expect_100_continue(self):
|
||||
def wsgi_app(environ, start_response):
|
||||
if int(environ['CONTENT_LENGTH']) > 1024:
|
||||
start_response('417 Expectation Failed', [('Content-Length', '7')])
|
||||
return ['failure']
|
||||
return [b'failure']
|
||||
else:
|
||||
text = environ['wsgi.input'].read()
|
||||
start_response('200 OK', [('Content-Length', str(len(text)))])
|
||||
return [text]
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\n'
|
||||
b'Expect: 100-continue\r\n\r\n')
|
||||
fd.flush()
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.status, 'HTTP/1.1 417 Expectation Failed')
|
||||
self.assertEqual(result.body, 'failure')
|
||||
self.assertEqual(result.body, b'failure')
|
||||
fd.write(
|
||||
b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\n'
|
||||
b'Expect: 100-continue\r\n\r\ntesting')
|
||||
@@ -758,7 +767,7 @@ class TestHttpd(_TestBase):
|
||||
header_lines = []
|
||||
while True:
|
||||
line = fd.readline()
|
||||
if line == '\r\n':
|
||||
if line == b'\r\n':
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
@@ -766,12 +775,12 @@ class TestHttpd(_TestBase):
|
||||
header_lines = []
|
||||
while True:
|
||||
line = fd.readline()
|
||||
if line == '\r\n':
|
||||
if line == b'\r\n':
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
assert header_lines[0].startswith('HTTP/1.1 200 OK')
|
||||
self.assertEqual(fd.read(7), 'testing')
|
||||
assert fd.read(7) == b'testing'
|
||||
fd.close()
|
||||
sock.close()
|
||||
|
||||
@@ -871,7 +880,7 @@ class TestHttpd(_TestBase):
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.headers_lower['connection'], 'close')
|
||||
self.assertNotEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
|
||||
self.assertEqual(result.body, "thisischunked")
|
||||
self.assertEqual(result.body, b"thisischunked")
|
||||
|
||||
def test_minimum_chunk_size_parameter_leaves_httpprotocol_class_member_intact(self):
|
||||
start_size = wsgi.HttpProtocol.minimum_chunk_size
|
||||
@@ -902,7 +911,7 @@ class TestHttpd(_TestBase):
|
||||
self.assertEqual(result.body, expected_body)
|
||||
|
||||
# verify that socket is closed by server
|
||||
self.assertEqual(sock.recv(1), '')
|
||||
self.assertEqual(sock.recv(1), b'')
|
||||
|
||||
def test_026_http_10_nokeepalive(self):
|
||||
# verify that if an http/1.0 client sends connection: keep-alive
|
||||
@@ -918,7 +927,7 @@ class TestHttpd(_TestBase):
|
||||
def test_027_keepalive_chunked(self):
|
||||
self.site.application = chunked_post
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
common_suffix = (
|
||||
b'Host: localhost\r\nTransfer-Encoding: chunked\r\n\r\n' +
|
||||
b'10\r\n0123456789abcdef\r\n0\r\n\r\n')
|
||||
@@ -995,13 +1004,13 @@ class TestHttpd(_TestBase):
|
||||
env['eventlet.posthooks'].append(
|
||||
(posthook1, (2,), {'multiplier': 3}))
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
yield ''
|
||||
yield b''
|
||||
self.site.application = one_posthook_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fp = sock.makefile('rw')
|
||||
fp = sock.makefile('rwb')
|
||||
fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fp.flush()
|
||||
self.assertEqual(fp.readline(), 'HTTP/1.1 200 OK\r\n')
|
||||
self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
|
||||
fp.close()
|
||||
sock.close()
|
||||
self.assertEqual(posthook1_count[0], 6)
|
||||
@@ -1018,13 +1027,13 @@ class TestHttpd(_TestBase):
|
||||
env['eventlet.posthooks'].append(
|
||||
(posthook2, (100,), {'divisor': 4}))
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
yield ''
|
||||
yield b''
|
||||
self.site.application = two_posthook_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fp = sock.makefile('rw')
|
||||
fp = sock.makefile('rwb')
|
||||
fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fp.flush()
|
||||
self.assertEqual(fp.readline(), 'HTTP/1.1 200 OK\r\n')
|
||||
self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
|
||||
fp.close()
|
||||
sock.close()
|
||||
self.assertEqual(posthook1_count[0], 26)
|
||||
@@ -1034,7 +1043,7 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
request = 'GET / HTTP/1.0\r\nHost: localhost\r\nLong: %s\r\n\r\n' % \
|
||||
('a' * 10000)
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(request.encode())
|
||||
fd.flush()
|
||||
result = read_http(sock)
|
||||
@@ -1065,7 +1074,7 @@ class TestHttpd(_TestBase):
|
||||
yield chunk
|
||||
|
||||
self.site.application = echo_by_iterating
|
||||
upload_data = '123456789abcdef' * 100
|
||||
upload_data = b'123456789abcdef' * 100
|
||||
request = (
|
||||
'POST / HTTP/1.0\r\n'
|
||||
'Host: localhost\r\n'
|
||||
@@ -1089,20 +1098,20 @@ class TestHttpd(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
response = fd.read().split('\r\n')
|
||||
response = fd.read().split(b'\r\n')
|
||||
headers = []
|
||||
while True:
|
||||
h = response.pop(0)
|
||||
headers.append(h)
|
||||
if h == '':
|
||||
break
|
||||
assert 'Transfer-Encoding: chunked' in ''.join(headers)
|
||||
assert b'Transfer-Encoding: chunked' in ''.join(headers)
|
||||
# should only be one chunk of zero size with two blank lines
|
||||
# (one terminates the chunk, one terminates the body)
|
||||
self.assertEqual(response, ['0', '', ''])
|
||||
self.assertEqual(response, [b'0', b'', b''])
|
||||
|
||||
def test_configurable_url_length_limit(self):
|
||||
self.spawn_server(url_length_limit=20000)
|
||||
@@ -1110,15 +1119,15 @@ class TestHttpd(_TestBase):
|
||||
('localhost', self.port))
|
||||
path = 'x' * 15000
|
||||
request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
|
||||
fd = sock.makefile('rw')
|
||||
fd.write(request)
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(request.encode())
|
||||
fd.flush()
|
||||
result = fd.readline()
|
||||
if result:
|
||||
# windows closes the socket before the data is flushed,
|
||||
# so we never get anything back
|
||||
status = result.split(' ')[1]
|
||||
self.assertEqual(status, '200')
|
||||
status = result.split(b' ')[1]
|
||||
self.assertEqual(status, b'200')
|
||||
fd.close()
|
||||
|
||||
def test_aborted_chunked_post(self):
|
||||
@@ -1130,7 +1139,7 @@ class TestHttpd(_TestBase):
|
||||
content = env['wsgi.input'].read(1024)
|
||||
except IOError:
|
||||
blew_up[0] = True
|
||||
content = 'ok'
|
||||
content = b'ok'
|
||||
read_content.send(content)
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
return [content]
|
||||
@@ -1147,7 +1156,7 @@ class TestHttpd(_TestBase):
|
||||
sock.close()
|
||||
# the test passes if we successfully get here, and read all the data
|
||||
# in spite of the early close
|
||||
self.assertEqual(read_content.wait(), 'ok')
|
||||
self.assertEqual(read_content.wait(), b'ok')
|
||||
assert blew_up[0]
|
||||
|
||||
def test_exceptions_close_connection(self):
|
||||
@@ -1155,7 +1164,7 @@ class TestHttpd(_TestBase):
|
||||
raise RuntimeError("intentional error")
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result = read_http(sock)
|
||||
@@ -1170,13 +1179,13 @@ class TestHttpd(_TestBase):
|
||||
yield u"non-encodable unicode: \u0230"
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.status, 'HTTP/1.1 500 Internal Server Error')
|
||||
self.assertEqual(result.headers_lower['connection'], 'close')
|
||||
assert 'unicode' in result.body
|
||||
assert b'unicode' in result.body
|
||||
|
||||
def test_path_info_decoding(self):
|
||||
def wsgi_app(environ, start_response):
|
||||
@@ -1185,13 +1194,13 @@ class TestHttpd(_TestBase):
|
||||
yield "raw: %s" % environ['RAW_PATH_INFO']
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET /a*b@%40%233 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
|
||||
fd.flush()
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.status, 'HTTP/1.1 200 OK')
|
||||
assert 'decoded: /a*b@@#3' in result.body
|
||||
assert 'raw: /a*b@%40%233' in result.body
|
||||
assert b'decoded: /a*b@@#3' in result.body
|
||||
assert b'raw: /a*b@%40%233' in result.body
|
||||
|
||||
def test_ipv6(self):
|
||||
try:
|
||||
@@ -1224,12 +1233,12 @@ class TestHttpd(_TestBase):
|
||||
self.site.application = crasher
|
||||
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result1 = read_http(sock)
|
||||
self.assertEqual(result1.status, 'HTTP/1.1 500 Internal Server Error')
|
||||
self.assertEqual(result1.body, '')
|
||||
self.assertEqual(result1.body, b'')
|
||||
self.assertEqual(result1.headers_lower['connection'], 'close')
|
||||
assert 'transfer-encoding' not in result1.headers_lower
|
||||
|
||||
@@ -1237,14 +1246,14 @@ class TestHttpd(_TestBase):
|
||||
self.spawn_server(debug=True)
|
||||
self.site.application = crasher
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('w')
|
||||
fd = sock.makefile('wb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd.flush()
|
||||
result2 = read_http(sock)
|
||||
self.assertEqual(result2.status, 'HTTP/1.1 500 Internal Server Error')
|
||||
assert 'intentional crash' in result2.body
|
||||
assert 'RuntimeError' in result2.body
|
||||
assert 'Traceback' in result2.body
|
||||
assert b'intentional crash' in result2.body, result2.body
|
||||
assert b'RuntimeError' in result2.body, result2.body
|
||||
assert b'Traceback' in result2.body, result2.body
|
||||
self.assertEqual(result2.headers_lower['connection'], 'close')
|
||||
assert 'transfer-encoding' not in result2.headers_lower
|
||||
|
||||
@@ -1253,7 +1262,7 @@ class TestHttpd(_TestBase):
|
||||
"""
|
||||
def long_response(environ, start_response):
|
||||
start_response('200 OK', [('Content-Length', '9876')])
|
||||
yield 'a' * 9876
|
||||
yield b'a' * 9876
|
||||
|
||||
server_sock = eventlet.listen(('localhost', 0))
|
||||
self.port = server_sock.getsockname()[1]
|
||||
@@ -1366,7 +1375,7 @@ class IterableAlreadyHandledTest(_TestBase):
|
||||
sock = eventlet.connect(
|
||||
('localhost', self.port))
|
||||
|
||||
fd = sock.makefile('rw')
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
|
||||
fd.flush()
|
||||
@@ -1378,7 +1387,7 @@ class IterableAlreadyHandledTest(_TestBase):
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.status, 'HTTP/1.1 200 OK')
|
||||
self.assertEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
|
||||
self.assertEqual(result.body, '0\r\n\r\n') # Still coming back chunked
|
||||
self.assertEqual(result.body, b'0\r\n\r\n') # Still coming back chunked
|
||||
|
||||
|
||||
class ProxiedIterableAlreadyHandledTest(IterableAlreadyHandledTest):
|
||||
@@ -1418,13 +1427,13 @@ class TestChunkedInput(_TestBase):
|
||||
self.yield_next_space = False
|
||||
|
||||
def response_iter():
|
||||
yield ' '
|
||||
yield b' '
|
||||
num_sleeps = 0
|
||||
while not self.yield_next_space and num_sleeps < 200:
|
||||
eventlet.sleep(.01)
|
||||
num_sleeps += 1
|
||||
|
||||
yield ' '
|
||||
yield b' '
|
||||
|
||||
start_response('200 OK',
|
||||
[('Content-Type', 'text/plain'),
|
||||
@@ -1467,7 +1476,7 @@ class TestChunkedInput(_TestBase):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall(req.encode())
|
||||
self.assertEqual(read_http(fd).body, "this is ch")
|
||||
self.assertEqual(read_http(fd).body, b"this is ch")
|
||||
|
||||
self.ping(fd)
|
||||
fd.close()
|
||||
@@ -1478,7 +1487,7 @@ class TestChunkedInput(_TestBase):
|
||||
"Content-Length:0\r\n\r\n" + body
|
||||
fd = self.connect()
|
||||
fd.sendall(req.encode())
|
||||
self.assertEqual(read_http(fd).body, "this is ch")
|
||||
self.assertEqual(read_http(fd).body, b"this is ch")
|
||||
|
||||
self.ping(fd)
|
||||
fd.close()
|
||||
@@ -1489,7 +1498,7 @@ class TestChunkedInput(_TestBase):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall(req.encode())
|
||||
self.assertEqual(read_http(fd).body, "this is ch")
|
||||
self.assertEqual(read_http(fd).body, b"this is ch")
|
||||
|
||||
self.ping(fd)
|
||||
fd.close()
|
||||
@@ -1500,7 +1509,7 @@ class TestChunkedInput(_TestBase):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall(req.encode())
|
||||
self.assertEqual(read_http(fd).body, "pong")
|
||||
self.assertEqual(read_http(fd).body, b"pong")
|
||||
|
||||
self.ping(fd)
|
||||
fd.close()
|
||||
@@ -1512,7 +1521,7 @@ class TestChunkedInput(_TestBase):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall(req.encode())
|
||||
self.assertEqual(read_http(fd).body, 'this is chunked\nline 2\nline3')
|
||||
self.assertEqual(read_http(fd).body, b'this is chunked\nline 2\nline3')
|
||||
fd.close()
|
||||
|
||||
def test_chunked_readline_wsgi_override_minimum_chunk_size(self):
|
||||
@@ -1527,7 +1536,7 @@ class TestChunkedInput(_TestBase):
|
||||
resp_so_far += one_byte
|
||||
if resp_so_far.endswith('\r\n\r\n'):
|
||||
break
|
||||
self.assertEqual(fd.recv(1), ' ')
|
||||
self.assertEqual(fd.recv(1), b' ')
|
||||
try:
|
||||
with eventlet.Timeout(.1):
|
||||
fd.recv(1)
|
||||
@@ -1538,22 +1547,22 @@ class TestChunkedInput(_TestBase):
|
||||
self.yield_next_space = True
|
||||
|
||||
with eventlet.Timeout(.1):
|
||||
self.assertEqual(fd.recv(1), ' ')
|
||||
self.assertEqual(fd.recv(1), b' ')
|
||||
|
||||
def test_chunked_readline_wsgi_not_override_minimum_chunk_size(self):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall(b"POST /yield_spaces HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
|
||||
|
||||
resp_so_far = ''
|
||||
resp_so_far = b''
|
||||
try:
|
||||
with eventlet.Timeout(.1):
|
||||
while True:
|
||||
one_byte = fd.recv(1)
|
||||
resp_so_far += one_byte
|
||||
if resp_so_far.endswith('\r\n\r\n'):
|
||||
if resp_so_far.endswith(b'\r\n\r\n'):
|
||||
break
|
||||
self.assertEqual(fd.recv(1), ' ')
|
||||
self.assertEqual(fd.recv(1), b' ')
|
||||
except eventlet.Timeout:
|
||||
pass
|
||||
else:
|
||||
|
@@ -136,7 +136,7 @@ if __name__ == '__main__':
|
||||
# req #1 - normal
|
||||
sock1 = eventlet.connect(server_addr)
|
||||
sock1.settimeout(0.1)
|
||||
fd1 = sock1.makefile('rw')
|
||||
fd1 = sock1.makefile('rwb')
|
||||
fd1.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
fd1.flush()
|
||||
tests.wsgi_test.read_http(sock1)
|
||||
|
Reference in New Issue
Block a user