mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
all tests pass under python 3
This commit is contained in:
parent
60644b12af
commit
8d453fb341
@ -74,10 +74,10 @@ def reload_django_settings():
|
|||||||
app_mod = util.import_module(app[:-2])
|
app_mod = util.import_module(app[:-2])
|
||||||
appdir = os.path.dirname(app_mod.__file__)
|
appdir = os.path.dirname(app_mod.__file__)
|
||||||
app_subdirs = os.listdir(appdir)
|
app_subdirs = os.listdir(appdir)
|
||||||
app_subdirs.sort()
|
|
||||||
name_pattern = re.compile(r'[a-zA-Z]\w*')
|
name_pattern = re.compile(r'[a-zA-Z]\w*')
|
||||||
for d in app_subdirs:
|
for d in sorted(app_subdirs):
|
||||||
if name_pattern.match(d) and os.path.isdir(os.path.join(appdir, d)):
|
if (name_pattern.match(d) and
|
||||||
|
os.path.isdir(os.path.join(appdir, d))):
|
||||||
new_installed_apps.append('%s.%s' % (app[:-2], d))
|
new_installed_apps.append('%s.%s' % (app[:-2], d))
|
||||||
else:
|
else:
|
||||||
new_installed_apps.append(app)
|
new_installed_apps.append(app)
|
||||||
|
|||||||
@ -99,7 +99,10 @@ class Arbiter(object):
|
|||||||
|
|
||||||
if self.cfg.debug:
|
if self.cfg.debug:
|
||||||
self.log.debug("Current configuration:")
|
self.log.debug("Current configuration:")
|
||||||
for config, value in sorted(self.cfg.settings.iteritems()):
|
|
||||||
|
|
||||||
|
for config, value in sorted(self.cfg.settings.items(),
|
||||||
|
key=lambda setting: setting[1]):
|
||||||
self.log.debug(" %s: %s", config, value.value)
|
self.log.debug(" %s: %s", config, value.value)
|
||||||
|
|
||||||
if self.cfg.preload_app:
|
if self.cfg.preload_app:
|
||||||
@ -436,7 +439,7 @@ class Arbiter(object):
|
|||||||
self.spawn_workers()
|
self.spawn_workers()
|
||||||
|
|
||||||
workers = self.WORKERS.items()
|
workers = self.WORKERS.items()
|
||||||
workers.sort(key=lambda w: w[1].age)
|
workers = sorted(workers, key=lambda w: w[1].age)
|
||||||
while len(workers) > self.num_workers:
|
while len(workers) > self.num_workers:
|
||||||
(pid, _) = workers.pop(0)
|
(pid, _) = workers.pop(0)
|
||||||
self.kill_worker(pid, signal.SIGQUIT)
|
self.kill_worker(pid, signal.SIGQUIT)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import types
|
|||||||
from gunicorn import __version__
|
from gunicorn import __version__
|
||||||
from gunicorn.errors import ConfigError
|
from gunicorn.errors import ConfigError
|
||||||
from gunicorn import util
|
from gunicorn import util
|
||||||
from gunicorn.six import string_types
|
from gunicorn.six import string_types, integer_types, bytes_to_str
|
||||||
|
|
||||||
KNOWN_SETTINGS = []
|
KNOWN_SETTINGS = []
|
||||||
|
|
||||||
@ -62,10 +62,12 @@ class Config(object):
|
|||||||
}
|
}
|
||||||
parser = optparse.OptionParser(**kwargs)
|
parser = optparse.OptionParser(**kwargs)
|
||||||
|
|
||||||
keys = self.settings.keys()
|
keys = list(self.settings)
|
||||||
def sorter(k):
|
def sorter(k):
|
||||||
return (self.settings[k].section, self.settings[k].order)
|
return (self.settings[k].section, self.settings[k].order)
|
||||||
keys.sort(key=sorter)
|
|
||||||
|
|
||||||
|
keys = sorted(self.settings, key=self.settings.__getitem__)
|
||||||
for k in keys:
|
for k in keys:
|
||||||
self.settings[k].add_option(parser)
|
self.settings[k].add_option(parser)
|
||||||
return parser
|
return parser
|
||||||
@ -85,7 +87,7 @@ class Config(object):
|
|||||||
@property
|
@property
|
||||||
def address(self):
|
def address(self):
|
||||||
bind = self.settings['bind'].get()
|
bind = self.settings['bind'].get()
|
||||||
return util.parse_address(util.to_bytestring(bind))
|
return util.parse_address(bytes_to_str(bind))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uid(self):
|
def uid(self):
|
||||||
@ -179,8 +181,15 @@ class Setting(object):
|
|||||||
assert callable(self.validator), "Invalid validator: %s" % self.name
|
assert callable(self.validator), "Invalid validator: %s" % self.name
|
||||||
self.value = self.validator(val)
|
self.value = self.validator(val)
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return (self.section == other.section and
|
||||||
|
self.order < other.order)
|
||||||
|
__cmp__ = __lt__
|
||||||
|
|
||||||
|
Setting = SettingMeta('Setting', (Setting,), {})
|
||||||
|
|
||||||
def validate_bool(val):
|
def validate_bool(val):
|
||||||
if isinstance(val, types.BooleanType):
|
if isinstance(val, bool):
|
||||||
return val
|
return val
|
||||||
if not isinstance(val, string_types):
|
if not isinstance(val, string_types):
|
||||||
raise TypeError("Invalid type for casting: %s" % val)
|
raise TypeError("Invalid type for casting: %s" % val)
|
||||||
@ -197,7 +206,7 @@ def validate_dict(val):
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
def validate_pos_int(val):
|
def validate_pos_int(val):
|
||||||
if not isinstance(val, (types.IntType, types.LongType)):
|
if not isinstance(val, integer_types):
|
||||||
val = int(val, 0)
|
val = int(val, 0)
|
||||||
else:
|
else:
|
||||||
# Booleans are ints!
|
# Booleans are ints!
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
|
|
||||||
class HaltServer(Exception):
|
class HaltServer(BaseException):
|
||||||
def __init__(self, reason, exit_status=1):
|
def __init__(self, reason, exit_status=1):
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
self.exit_status = exit_status
|
self.exit_status = exit_status
|
||||||
@ -12,5 +12,5 @@ class HaltServer(Exception):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<HaltServer %r %d>" % (self.reason, self.exit_status)
|
return "<HaltServer %r %d>" % (self.reason, self.exit_status)
|
||||||
|
|
||||||
class ConfigError(Exception):
|
class ConfigError(BaseException):
|
||||||
""" Exception raised on config error """
|
""" Exception raised on config error """
|
||||||
|
|||||||
@ -7,16 +7,16 @@ import sys
|
|||||||
|
|
||||||
from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
|
from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
|
||||||
InvalidChunkSize)
|
InvalidChunkSize)
|
||||||
from gunicorn.six import StringIO, bytes_to_str, integer_types
|
from gunicorn import six
|
||||||
|
|
||||||
class ChunkedReader(object):
|
class ChunkedReader(object):
|
||||||
def __init__(self, req, unreader):
|
def __init__(self, req, unreader):
|
||||||
self.req = req
|
self.req = req
|
||||||
self.parser = self.parse_chunked(unreader)
|
self.parser = self.parse_chunked(unreader)
|
||||||
self.buf = StringIO()
|
self.buf = six.BytesIO()
|
||||||
|
|
||||||
def read(self, size):
|
def read(self, size):
|
||||||
if not isinstance(size, integer_types):
|
if not isinstance(size, six.integer_types):
|
||||||
raise TypeError("size must be an integral type")
|
raise TypeError("size must be an integral type")
|
||||||
if size <= 0:
|
if size <= 0:
|
||||||
raise ValueError("Size must be positive.")
|
raise ValueError("Size must be positive.")
|
||||||
@ -26,19 +26,19 @@ class ChunkedReader(object):
|
|||||||
if self.parser:
|
if self.parser:
|
||||||
while self.buf.tell() < size:
|
while self.buf.tell() < size:
|
||||||
try:
|
try:
|
||||||
self.buf.write(self.parser.next())
|
self.buf.write(six.next(self.parser))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.parser = None
|
self.parser = None
|
||||||
break
|
break
|
||||||
|
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
ret, rest = data[:size], data[size:]
|
ret, rest = data[:size], data[size:]
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(rest)
|
self.buf.write(rest)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def parse_trailers(self, unreader, data):
|
def parse_trailers(self, unreader, data):
|
||||||
buf = StringIO()
|
buf = six.BytesIO()
|
||||||
buf.write(data)
|
buf.write(data)
|
||||||
|
|
||||||
idx = buf.getvalue().find(b"\r\n\r\n")
|
idx = buf.getvalue().find(b"\r\n\r\n")
|
||||||
@ -50,8 +50,7 @@ class ChunkedReader(object):
|
|||||||
if done:
|
if done:
|
||||||
unreader.unread(buf.getvalue()[2:])
|
unreader.unread(buf.getvalue()[2:])
|
||||||
return b""
|
return b""
|
||||||
self.req.trailers = self.req.parse_headers(
|
self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx])
|
||||||
bytes_to_str(buf.getvalue()[:idx]))
|
|
||||||
unreader.unread(buf.getvalue()[idx+4:])
|
unreader.unread(buf.getvalue()[idx+4:])
|
||||||
|
|
||||||
def parse_chunked(self, unreader):
|
def parse_chunked(self, unreader):
|
||||||
@ -73,7 +72,7 @@ class ChunkedReader(object):
|
|||||||
(size, rest) = self.parse_chunk_size(unreader, data=rest[2:])
|
(size, rest) = self.parse_chunk_size(unreader, data=rest[2:])
|
||||||
|
|
||||||
def parse_chunk_size(self, unreader, data=None):
|
def parse_chunk_size(self, unreader, data=None):
|
||||||
buf = StringIO()
|
buf = six.BytesIO()
|
||||||
if data is not None:
|
if data is not None:
|
||||||
buf.write(data)
|
buf.write(data)
|
||||||
|
|
||||||
@ -111,7 +110,7 @@ class LengthReader(object):
|
|||||||
self.length = length
|
self.length = length
|
||||||
|
|
||||||
def read(self, size):
|
def read(self, size):
|
||||||
if not isinstance(size, integer_types):
|
if not isinstance(size, six.integer_types):
|
||||||
raise TypeError("size must be an integral type")
|
raise TypeError("size must be an integral type")
|
||||||
|
|
||||||
size = min(self.length, size)
|
size = min(self.length, size)
|
||||||
@ -121,7 +120,7 @@ class LengthReader(object):
|
|||||||
return b""
|
return b""
|
||||||
|
|
||||||
|
|
||||||
buf = StringIO()
|
buf = six.BytesIO()
|
||||||
data = self.unreader.read()
|
data = self.unreader.read()
|
||||||
while data:
|
while data:
|
||||||
buf.write(data)
|
buf.write(data)
|
||||||
@ -138,21 +137,21 @@ class LengthReader(object):
|
|||||||
class EOFReader(object):
|
class EOFReader(object):
|
||||||
def __init__(self, unreader):
|
def __init__(self, unreader):
|
||||||
self.unreader = unreader
|
self.unreader = unreader
|
||||||
self.buf = StringIO()
|
self.buf = six.BytesIO()
|
||||||
self.finished = False
|
self.finished = False
|
||||||
|
|
||||||
def read(self, size):
|
def read(self, size):
|
||||||
if not isinstance(size, integer_types):
|
if not isinstance(size, six.integer_types):
|
||||||
raise TypeError("size must be an integral type")
|
raise TypeError("size must be an integral type")
|
||||||
if size < 0:
|
if size < 0:
|
||||||
raise ValueError("Size must be positive.")
|
raise ValueError("Size must be positive.")
|
||||||
if size == 0:
|
if size == 0:
|
||||||
return ""
|
return b""
|
||||||
|
|
||||||
if self.finished:
|
if self.finished:
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
ret, rest = data[:size], data[size:]
|
ret, rest = data[:size], data[size:]
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(rest)
|
self.buf.write(rest)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -168,31 +167,32 @@ class EOFReader(object):
|
|||||||
|
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
ret, rest = data[:size], data[size:]
|
ret, rest = data[:size], data[size:]
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(rest)
|
self.buf.write(rest)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
class Body(object):
|
class Body(object):
|
||||||
def __init__(self, reader):
|
def __init__(self, reader):
|
||||||
self.reader = reader
|
self.reader = reader
|
||||||
self.buf = StringIO()
|
self.buf = six.BytesIO()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def next(self):
|
def __next__(self):
|
||||||
ret = self.readline()
|
ret = self.readline()
|
||||||
if not ret:
|
if not ret:
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
return ret
|
return ret
|
||||||
|
next = __next__
|
||||||
|
|
||||||
def getsize(self, size):
|
def getsize(self, size):
|
||||||
if size is None:
|
if size is None:
|
||||||
return sys.maxint
|
return six.MAXSIZE
|
||||||
elif not isinstance(size, integer_types):
|
elif not isinstance(size, six.integer_types):
|
||||||
raise TypeError("size must be an integral type")
|
raise TypeError("size must be an integral type")
|
||||||
elif size < 0:
|
elif size < 0:
|
||||||
return sys.maxint
|
return six.MAXSIZE
|
||||||
return size
|
return size
|
||||||
|
|
||||||
def read(self, size=None):
|
def read(self, size=None):
|
||||||
@ -203,7 +203,7 @@ class Body(object):
|
|||||||
if size < self.buf.tell():
|
if size < self.buf.tell():
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
ret, rest = data[:size], data[size:]
|
ret, rest = data[:size], data[size:]
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(rest)
|
self.buf.write(rest)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ class Body(object):
|
|||||||
|
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
ret, rest = data[:size], data[size:]
|
ret, rest = data[:size], data[size:]
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(rest)
|
self.buf.write(rest)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -225,7 +225,7 @@ class Body(object):
|
|||||||
return b""
|
return b""
|
||||||
|
|
||||||
line = self.buf.getvalue()
|
line = self.buf.getvalue()
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
if len(line) < size:
|
if len(line) < size:
|
||||||
line += self.reader.read(size - len(line))
|
line += self.reader.read(size - len(line))
|
||||||
extra_buf_data = line[size:]
|
extra_buf_data = line[size:]
|
||||||
|
|||||||
@ -3,12 +3,13 @@
|
|||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
class ParseException(Exception):
|
class ParseException(BaseException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class NoMoreData(IOError):
|
class NoMoreData(IOError):
|
||||||
def __init__(self, buf=None):
|
def __init__(self, buf=None):
|
||||||
self.buf = buf
|
self.buf = buf
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "No more data after: %r" % self.buf
|
return "No more data after: %r" % self.buf
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ from gunicorn.http.errors import InvalidHeader, InvalidHeaderName, NoMoreData, \
|
|||||||
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \
|
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \
|
||||||
LimitRequestLine, LimitRequestHeaders
|
LimitRequestLine, LimitRequestHeaders
|
||||||
from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
|
from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
|
||||||
from gunicorn.six import StringIO, urlsplit, bytes_to_str
|
from gunicorn.six import BytesIO, urlsplit, bytes_to_str
|
||||||
|
|
||||||
MAX_REQUEST_LINE = 8190
|
MAX_REQUEST_LINE = 8190
|
||||||
MAX_HEADERS = 32768
|
MAX_HEADERS = 32768
|
||||||
@ -148,7 +148,6 @@ class Request(Message):
|
|||||||
|
|
||||||
self.req_number = req_number
|
self.req_number = req_number
|
||||||
self.proxy_protocol_info = None
|
self.proxy_protocol_info = None
|
||||||
|
|
||||||
super(Request, self).__init__(cfg, unreader)
|
super(Request, self).__init__(cfg, unreader)
|
||||||
|
|
||||||
|
|
||||||
@ -161,7 +160,7 @@ class Request(Message):
|
|||||||
buf.write(data)
|
buf.write(data)
|
||||||
|
|
||||||
def parse(self, unreader):
|
def parse(self, unreader):
|
||||||
buf = StringIO()
|
buf = BytesIO()
|
||||||
self.get_data(unreader, buf, stop=True)
|
self.get_data(unreader, buf, stop=True)
|
||||||
|
|
||||||
# get request line
|
# get request line
|
||||||
@ -170,12 +169,12 @@ class Request(Message):
|
|||||||
# proxy protocol
|
# proxy protocol
|
||||||
if self.proxy_protocol(bytes_to_str(line)):
|
if self.proxy_protocol(bytes_to_str(line)):
|
||||||
# get next request line
|
# get next request line
|
||||||
buf = StringIO()
|
buf = BytesIO()
|
||||||
buf.write(rbuf)
|
buf.write(rbuf)
|
||||||
line, rbuf = self.read_line(unreader, buf, self.limit_request_line)
|
line, rbuf = self.read_line(unreader, buf, self.limit_request_line)
|
||||||
|
|
||||||
self.parse_request_line(bytes_to_str(line))
|
self.parse_request_line(bytes_to_str(line))
|
||||||
buf = StringIO()
|
buf = BytesIO()
|
||||||
buf.write(rbuf)
|
buf.write(rbuf)
|
||||||
|
|
||||||
# Headers
|
# Headers
|
||||||
@ -202,7 +201,7 @@ class Request(Message):
|
|||||||
self.headers = self.parse_headers(data[:idx])
|
self.headers = self.parse_headers(data[:idx])
|
||||||
|
|
||||||
ret = data[idx+4:]
|
ret = data[idx+4:]
|
||||||
buf = StringIO()
|
buf = BytesIO()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def read_line(self, unreader, buf, limit=0):
|
def read_line(self, unreader, buf, limit=0):
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class Parser(object):
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def next(self):
|
def __next__(self):
|
||||||
# Stop if HTTP dictates a stop.
|
# Stop if HTTP dictates a stop.
|
||||||
if self.mesg and self.mesg.should_close():
|
if self.mesg and self.mesg.should_close():
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
@ -33,6 +33,7 @@ class Parser(object):
|
|||||||
while data:
|
while data:
|
||||||
data = self.mesg.body.read(8192)
|
data = self.mesg.body.read(8192)
|
||||||
|
|
||||||
|
|
||||||
# Parse the next request
|
# Parse the next request
|
||||||
self.req_count += 1
|
self.req_count += 1
|
||||||
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
|
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
|
||||||
@ -40,6 +41,8 @@ class Parser(object):
|
|||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
return self.mesg
|
return self.mesg
|
||||||
|
|
||||||
|
next = __next__
|
||||||
|
|
||||||
class RequestParser(Parser):
|
class RequestParser(Parser):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(RequestParser, self).__init__(Request, *args, **kwargs)
|
super(RequestParser, self).__init__(Request, *args, **kwargs)
|
||||||
|
|||||||
@ -5,44 +5,47 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from gunicorn.six import integer_types, StringIO
|
from gunicorn import six
|
||||||
|
|
||||||
# Classes that can undo reading data from
|
# Classes that can undo reading data from
|
||||||
# a given type of data source.
|
# a given type of data source.
|
||||||
|
|
||||||
class Unreader(object):
|
class Unreader(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.buf = StringIO()
|
self.buf = six.BytesIO()
|
||||||
|
|
||||||
def chunk(self):
|
def chunk(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def read(self, size=None):
|
def read(self, size=None):
|
||||||
if size is not None and not isinstance(size, integer_types):
|
if size is not None and not isinstance(size, six.integer_types):
|
||||||
raise TypeError("size parameter must be an int or long.")
|
raise TypeError("size parameter must be an int or long.")
|
||||||
if size == 0:
|
|
||||||
return ""
|
if size is not None:
|
||||||
if size < 0:
|
if size == 0:
|
||||||
size = None
|
return b""
|
||||||
|
if size < 0:
|
||||||
|
size = None
|
||||||
|
|
||||||
self.buf.seek(0, os.SEEK_END)
|
self.buf.seek(0, os.SEEK_END)
|
||||||
|
|
||||||
if size is None and self.buf.tell():
|
if size is None and self.buf.tell():
|
||||||
ret = self.buf.getvalue()
|
ret = self.buf.getvalue()
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
return ret
|
return ret
|
||||||
if size is None:
|
if size is None:
|
||||||
return self.chunk()
|
d = self.chunk()
|
||||||
|
return d
|
||||||
|
|
||||||
while self.buf.tell() < size:
|
while self.buf.tell() < size:
|
||||||
chunk = self.chunk()
|
chunk = self.chunk()
|
||||||
if not len(chunk):
|
if not len(chunk):
|
||||||
ret = self.buf.getvalue()
|
ret = self.buf.getvalue()
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
return ret
|
return ret
|
||||||
self.buf.write(chunk)
|
self.buf.write(chunk)
|
||||||
data = self.buf.getvalue()
|
data = self.buf.getvalue()
|
||||||
self.buf.truncate(0)
|
self.buf = six.BytesIO()
|
||||||
self.buf.write(data[size:])
|
self.buf.write(data[size:])
|
||||||
return data[:size]
|
return data[:size]
|
||||||
|
|
||||||
@ -66,9 +69,9 @@ class IterUnreader(Unreader):
|
|||||||
|
|
||||||
def chunk(self):
|
def chunk(self):
|
||||||
if not self.iter:
|
if not self.iter:
|
||||||
return ""
|
return b""
|
||||||
try:
|
try:
|
||||||
return self.iter.next()
|
return six.next(self.iter)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.iter = None
|
self.iter = None
|
||||||
return ""
|
return b""
|
||||||
|
|||||||
@ -281,10 +281,14 @@ _add_doc(u, """Text literal""")
|
|||||||
|
|
||||||
|
|
||||||
if PY3:
|
if PY3:
|
||||||
|
|
||||||
|
def execfile_(fname, *args):
|
||||||
|
return exec(compile(open(fname, 'rb').read(), fname, 'exec'), *args)
|
||||||
|
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
exec_ = getattr(builtins, "exec")
|
exec_ = getattr(builtins, "exec")
|
||||||
|
|
||||||
|
|
||||||
def reraise(tp, value, tb=None):
|
def reraise(tp, value, tb=None):
|
||||||
if value.__traceback__ is not tb:
|
if value.__traceback__ is not tb:
|
||||||
raise value.with_traceback(tb)
|
raise value.with_traceback(tb)
|
||||||
@ -294,10 +298,6 @@ if PY3:
|
|||||||
print_ = getattr(builtins, "print")
|
print_ = getattr(builtins, "print")
|
||||||
del builtins
|
del builtins
|
||||||
|
|
||||||
def execfile_(file, globals=globals(), locals=locals()):
|
|
||||||
with open(file, "r") as fh:
|
|
||||||
exec_(fh.read()+"\n", globals, locals)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
def exec_(code, globs=None, locs=None):
|
def exec_(code, globs=None, locs=None):
|
||||||
"""Execute code in a namespace."""
|
"""Execute code in a namespace."""
|
||||||
@ -373,33 +373,26 @@ def with_metaclass(meta, base=object):
|
|||||||
|
|
||||||
# specific to gunicorn
|
# specific to gunicorn
|
||||||
if PY3:
|
if PY3:
|
||||||
import io
|
|
||||||
StringIO = io.BytesIO
|
|
||||||
|
|
||||||
def bytes_to_str(b):
|
def bytes_to_str(b):
|
||||||
|
if isinstance(b, text_type):
|
||||||
|
return b
|
||||||
return str(b, 'latin1')
|
return str(b, 'latin1')
|
||||||
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
unquote = urllib.parse.unquote
|
unquote = urllib.parse.unquote
|
||||||
urlsplit = urllib.parse.urlsplit
|
urlsplit = urllib.parse.urlsplit
|
||||||
|
urlparse = urllib.parse.urlparse
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
def bytes_to_str(s):
|
||||||
import cStringIO as StringIO
|
|
||||||
except ImportError:
|
|
||||||
import StringIO
|
|
||||||
|
|
||||||
StringIO = StringIO
|
|
||||||
|
|
||||||
|
|
||||||
def bytestring(s):
|
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, unicode):
|
||||||
return s.encode('utf-8')
|
return s.encode('utf-8')
|
||||||
return s
|
return s
|
||||||
|
|
||||||
import urlparse as orig_urlparse
|
import urlparse as orig_urlparse
|
||||||
urlsplit = orig_urlparse.urlsplit
|
urlsplit = orig_urlparse.urlsplit
|
||||||
|
urlparse = orig_urlparse.urlparse
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
urlunquote = urllib.unquote
|
urlunquote = urllib.unquote
|
||||||
|
|||||||
@ -311,15 +311,6 @@ def http_date(timestamp=None):
|
|||||||
hh, mm, ss)
|
hh, mm, ss)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def to_bytestring(s):
|
|
||||||
""" convert to bytestring an unicode """
|
|
||||||
if not isinstance(s, string_types):
|
|
||||||
return s
|
|
||||||
if isinstance(s, unicode):
|
|
||||||
return s.encode('utf-8')
|
|
||||||
else:
|
|
||||||
return s
|
|
||||||
|
|
||||||
def is_hoppish(header):
|
def is_hoppish(header):
|
||||||
return header.lower().strip() in hop_headers
|
return header.lower().strip() in hop_headers
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import gunicorn.http as http
|
|||||||
import gunicorn.http.wsgi as wsgi
|
import gunicorn.http.wsgi as wsgi
|
||||||
import gunicorn.util as util
|
import gunicorn.util as util
|
||||||
import gunicorn.workers.base as base
|
import gunicorn.workers.base as base
|
||||||
|
from gunicorn import six
|
||||||
|
|
||||||
ALREADY_HANDLED = object()
|
ALREADY_HANDLED = object()
|
||||||
|
|
||||||
@ -32,14 +33,14 @@ class AsyncWorker(base.Worker):
|
|||||||
parser = http.RequestParser(self.cfg, client)
|
parser = http.RequestParser(self.cfg, client)
|
||||||
try:
|
try:
|
||||||
if not self.cfg.keepalive:
|
if not self.cfg.keepalive:
|
||||||
req = parser.next()
|
req = six.next(parser)
|
||||||
self.handle_request(req, client, addr)
|
self.handle_request(req, client, addr)
|
||||||
else:
|
else:
|
||||||
# keepalive loop
|
# keepalive loop
|
||||||
while True:
|
while True:
|
||||||
req = None
|
req = None
|
||||||
with self.timeout_ctx():
|
with self.timeout_ctx():
|
||||||
req = parser.next()
|
req = six.next(parser)
|
||||||
if not req:
|
if not req:
|
||||||
break
|
break
|
||||||
self.handle_request(req, client, addr)
|
self.handle_request(req, client, addr)
|
||||||
|
|||||||
@ -18,6 +18,7 @@ InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \
|
|||||||
LimitRequestLine, LimitRequestHeaders
|
LimitRequestLine, LimitRequestHeaders
|
||||||
from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
|
from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
|
||||||
from gunicorn.http.wsgi import default_environ, Response
|
from gunicorn.http.wsgi import default_environ, Response
|
||||||
|
from gunicorn.six import MAXSIZE
|
||||||
|
|
||||||
class Worker(object):
|
class Worker(object):
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ class Worker(object):
|
|||||||
self.booted = False
|
self.booted = False
|
||||||
|
|
||||||
self.nr = 0
|
self.nr = 0
|
||||||
self.max_requests = cfg.max_requests or sys.maxint
|
self.max_requests = cfg.max_requests or MAXSIZE
|
||||||
self.alive = True
|
self.alive = True
|
||||||
self.log = log
|
self.log = log
|
||||||
self.debug = cfg.debug
|
self.debug = cfg.debug
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import gunicorn.http as http
|
|||||||
import gunicorn.http.wsgi as wsgi
|
import gunicorn.http.wsgi as wsgi
|
||||||
import gunicorn.util as util
|
import gunicorn.util as util
|
||||||
import gunicorn.workers.base as base
|
import gunicorn.workers.base as base
|
||||||
|
from gunicorn import six
|
||||||
|
|
||||||
class SyncWorker(base.Worker):
|
class SyncWorker(base.Worker):
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ class SyncWorker(base.Worker):
|
|||||||
try:
|
try:
|
||||||
client.settimeout(self.cfg.timeout)
|
client.settimeout(self.cfg.timeout)
|
||||||
parser = http.RequestParser(self.cfg, client)
|
parser = http.RequestParser(self.cfg, client)
|
||||||
req = parser.next()
|
req = six.next(parser)
|
||||||
self.handle_request(req, client, addr)
|
self.handle_request(req, client, addr)
|
||||||
except http.errors.NoMoreData as e:
|
except http.errors.NoMoreData as e:
|
||||||
self.log.debug("Ignored premature client disconnection. %s", e)
|
self.log.debug("Ignored premature client disconnection. %s", e)
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
from StringIO import StringIO
|
|
||||||
|
|
||||||
import t
|
|
||||||
from gunicorn.http.body import Body
|
|
||||||
|
|
||||||
|
|
||||||
def assert_readline(payload, size, expected):
|
|
||||||
body = Body(StringIO(payload))
|
|
||||||
t.eq(body.readline(size), expected)
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_empty_body():
|
|
||||||
assert_readline("", None, "")
|
|
||||||
assert_readline("", 1, "")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_zero_size():
|
|
||||||
assert_readline("abc", 0, "")
|
|
||||||
assert_readline("\n", 0, "")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_new_line_before_size():
|
|
||||||
body = Body(StringIO("abc\ndef"))
|
|
||||||
t.eq(body.readline(4), "abc\n")
|
|
||||||
t.eq(body.readline(), "def")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_new_line_after_size():
|
|
||||||
body = Body(StringIO("abc\ndef"))
|
|
||||||
t.eq(body.readline(2), "ab")
|
|
||||||
t.eq(body.readline(), "c\n")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_no_new_line():
|
|
||||||
body = Body(StringIO("abcdef"))
|
|
||||||
t.eq(body.readline(), "abcdef")
|
|
||||||
body = Body(StringIO("abcdef"))
|
|
||||||
t.eq(body.readline(2), "ab")
|
|
||||||
t.eq(body.readline(2), "cd")
|
|
||||||
t.eq(body.readline(2), "ef")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_buffer_loaded():
|
|
||||||
reader = StringIO("abc\ndef")
|
|
||||||
body = Body(reader)
|
|
||||||
body.read(1) # load internal buffer
|
|
||||||
reader.write("g\nhi")
|
|
||||||
reader.seek(7)
|
|
||||||
t.eq(body.readline(), "bc\n")
|
|
||||||
t.eq(body.readline(), "defg\n")
|
|
||||||
t.eq(body.readline(), "hi")
|
|
||||||
|
|
||||||
|
|
||||||
def test_readline_buffer_loaded_with_size():
|
|
||||||
body = Body(StringIO("abc\ndef"))
|
|
||||||
body.read(1) # load internal buffer
|
|
||||||
t.eq(body.readline(2), "bc")
|
|
||||||
t.eq(body.readline(2), "\n")
|
|
||||||
t.eq(body.readline(2), "de")
|
|
||||||
t.eq(body.readline(2), "f")
|
|
||||||
|
|
||||||
@ -7,5 +7,5 @@ request = {
|
|||||||
("CONTENT-TYPE", "application/json"),
|
("CONTENT-TYPE", "application/json"),
|
||||||
("CONTENT-LENGTH", "14")
|
("CONTENT-LENGTH", "14")
|
||||||
],
|
],
|
||||||
"body": '{"nom": "nom"}'
|
"body": b'{"nom": "nom"}'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,5 @@ request = {
|
|||||||
("HOST", "0.0.0.0=5000"),
|
("HOST", "0.0.0.0=5000"),
|
||||||
("ACCEPT", "*/*")
|
("ACCEPT", "*/*")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,5 +12,5 @@ request = {
|
|||||||
("KEEP-ALIVE", "300"),
|
("KEEP-ALIVE", "300"),
|
||||||
("CONNECTION", "keep-alive")
|
("CONNECTION", "keep-alive")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("AAAAAAAAAAAAA", "++++++++++")
|
("AAAAAAAAAAAAA", "++++++++++")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri("/forums/1/topics/2375?page=1#posts-17408"),
|
"uri": uri("/forums/1/topics/2375?page=1#posts-17408"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri("/get_no_headers_no_body/world"),
|
"uri": uri("/get_no_headers_no_body/world"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("ACCEPT", "*/*")
|
("ACCEPT", "*/*")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("CONTENT-LENGTH", "5")
|
("CONTENT-LENGTH", "5")
|
||||||
],
|
],
|
||||||
"body": "HELLO"
|
"body": b"HELLO"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,5 @@ request = {
|
|||||||
("TRANSFER-ENCODING", "identity"),
|
("TRANSFER-ENCODING", "identity"),
|
||||||
("CONTENT-LENGTH", "5")
|
("CONTENT-LENGTH", "5")
|
||||||
],
|
],
|
||||||
"body": "World"
|
"body": b"World"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked"),
|
("TRANSFER-ENCODING", "chunked"),
|
||||||
],
|
],
|
||||||
"body": "all your base are belong to us"
|
"body": b"all your base are belong to us"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked")
|
("TRANSFER-ENCODING", "chunked")
|
||||||
],
|
],
|
||||||
"body": "hello world"
|
"body": b"hello world"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,9 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked")
|
("TRANSFER-ENCODING", "chunked")
|
||||||
],
|
],
|
||||||
"body": "hello world",
|
"body": b"hello world",
|
||||||
"trailers": [
|
"trailers": [
|
||||||
("VARY", "*"),
|
("VARY", "*"),
|
||||||
("CONTENT-TYPE", "text/plain")
|
("CONTENT-TYPE", "text/plain")
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ request = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked")
|
("TRANSFER-ENCODING", "chunked")
|
||||||
],
|
],
|
||||||
"body": "hello world"
|
"body": b"hello world"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri('/with_"quotes"?foo="bar"'),
|
"uri": uri('/with_"quotes"?foo="bar"'),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,5 @@ request = {
|
|||||||
("USER-AGENT", "ApacheBench/2.3"),
|
("USER-AGENT", "ApacheBench/2.3"),
|
||||||
("ACCEPT", "*/*")
|
("ACCEPT", "*/*")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,5 +36,5 @@ request = {
|
|||||||
"uri": uri("/"),
|
"uri": uri("/"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [("X-SSL-CERT", certificate)],
|
"headers": [("X-SSL-CERT", certificate)],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,5 +6,5 @@ request = {
|
|||||||
("IF-MATCH", "bazinga!"),
|
("IF-MATCH", "bazinga!"),
|
||||||
("IF-MATCH", "large-sound")
|
("IF-MATCH", "large-sound")
|
||||||
],
|
],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ req1 = {
|
|||||||
"uri": uri("/first"),
|
"uri": uri("/first"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|
||||||
req2 = {
|
req2 = {
|
||||||
@ -11,7 +11,7 @@ req2 = {
|
|||||||
"uri": uri("/second"),
|
"uri": uri("/second"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|
||||||
request = [req1, req2]
|
request = [req1, req2]
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri("/first"),
|
"uri": uri("/first"),
|
||||||
"version": (1, 0),
|
"version": (1, 0),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri("/first"),
|
"uri": uri("/first"),
|
||||||
"version": (1, 0),
|
"version": (1, 0),
|
||||||
"headers": [('CONTENT-LENGTH', '24')],
|
"headers": [('CONTENT-LENGTH', '24')],
|
||||||
"body": "GET /second HTTP/1.1\r\n\r\n"
|
"body": b"GET /second HTTP/1.1\r\n\r\n"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,5 +3,5 @@ request = {
|
|||||||
"uri": uri("/first"),
|
"uri": uri("/first"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [("CONNECTION", "Close")],
|
"headers": [("CONNECTION", "Close")],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ req1 = {
|
|||||||
"uri": uri("/first"),
|
"uri": uri("/first"),
|
||||||
"version": (1, 0),
|
"version": (1, 0),
|
||||||
"headers": [("CONNECTION", "Keep-Alive")],
|
"headers": [("CONNECTION", "Keep-Alive")],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|
||||||
req2 = {
|
req2 = {
|
||||||
@ -11,7 +11,7 @@ req2 = {
|
|||||||
"uri": uri("/second"),
|
"uri": uri("/second"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|
||||||
request = [req1, req2]
|
request = [req1, req2]
|
||||||
|
|||||||
@ -5,7 +5,7 @@ req1 = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked")
|
("TRANSFER-ENCODING", "chunked")
|
||||||
],
|
],
|
||||||
"body": "hello world"
|
"body": b"hello world"
|
||||||
}
|
}
|
||||||
|
|
||||||
req2 = {
|
req2 = {
|
||||||
@ -13,7 +13,7 @@ req2 = {
|
|||||||
"uri": uri("/second"),
|
"uri": uri("/second"),
|
||||||
"version": (1, 1),
|
"version": (1, 1),
|
||||||
"headers": [],
|
"headers": [],
|
||||||
"body": ""
|
"body": b""
|
||||||
}
|
}
|
||||||
|
|
||||||
request = [req1, req2]
|
request = [req1, req2]
|
||||||
|
|||||||
@ -6,7 +6,7 @@ req1 = {
|
|||||||
("CONTENT-LENGTH", "-1"),
|
("CONTENT-LENGTH", "-1"),
|
||||||
("TRANSFER-ENCODING", "chunked")
|
("TRANSFER-ENCODING", "chunked")
|
||||||
],
|
],
|
||||||
"body": "hello world"
|
"body": b"hello world"
|
||||||
}
|
}
|
||||||
|
|
||||||
req2 = {
|
req2 = {
|
||||||
@ -17,7 +17,7 @@ req2 = {
|
|||||||
("TRANSFER-ENCODING", "chunked"),
|
("TRANSFER-ENCODING", "chunked"),
|
||||||
("CONTENT-LENGTH", "-1"),
|
("CONTENT-LENGTH", "-1"),
|
||||||
],
|
],
|
||||||
"body": "hello world"
|
"body": b"hello world"
|
||||||
}
|
}
|
||||||
|
|
||||||
request = [req1, req2]
|
request = [req1, req2]
|
||||||
|
|||||||
@ -12,5 +12,5 @@ request = {
|
|||||||
("CONTENT-TYPE", "application/json"),
|
("CONTENT-TYPE", "application/json"),
|
||||||
("CONTENT-LENGTH", "14")
|
("CONTENT-LENGTH", "14")
|
||||||
],
|
],
|
||||||
"body": '{"nom": "nom"}'
|
"body": b'{"nom": "nom"}'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ req1 = {
|
|||||||
("CONTENT-LENGTH", "14"),
|
("CONTENT-LENGTH", "14"),
|
||||||
("CONNECTION", "keep-alive")
|
("CONNECTION", "keep-alive")
|
||||||
],
|
],
|
||||||
"body": '{"nom": "nom"}'
|
"body": b'{"nom": "nom"}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ req2 = {
|
|||||||
"headers": [
|
"headers": [
|
||||||
("TRANSFER-ENCODING", "chunked"),
|
("TRANSFER-ENCODING", "chunked"),
|
||||||
],
|
],
|
||||||
"body": "all your base are belong to us"
|
"body": b"all your base are belong to us"
|
||||||
}
|
}
|
||||||
|
|
||||||
request = [req1, req2]
|
request = [req1, req2]
|
||||||
|
|||||||
35
tests/t.py
35
tests/t.py
@ -1,43 +1,43 @@
|
|||||||
# -*- coding: utf-8 -
|
# -*- coding: utf-8 -
|
||||||
# Copyright 2009 Paul J. Davis <paul.joseph.davis@gmail.com>
|
# Copyright 2009 Paul J. Davis <paul.joseph.davis@gmail.com>
|
||||||
#
|
#
|
||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import array
|
import array
|
||||||
import os
|
import os
|
||||||
from StringIO import StringIO
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
dirname = os.path.dirname(__file__)
|
dirname = os.path.dirname(__file__)
|
||||||
|
|
||||||
from gunicorn.http.parser import RequestParser
|
from gunicorn.http.parser import RequestParser
|
||||||
from gunicorn.config import Config
|
from gunicorn.config import Config
|
||||||
|
from gunicorn.six import BytesIO
|
||||||
|
|
||||||
def data_source(fname):
|
def data_source(fname):
|
||||||
buf = StringIO()
|
buf = BytesIO()
|
||||||
with open(fname) as handle:
|
with open(fname) as handle:
|
||||||
for line in handle:
|
for line in handle:
|
||||||
line = line.rstrip("\n").replace("\\r\\n", "\r\n")
|
line = line.rstrip("\n").replace("\\r\\n", "\r\n")
|
||||||
buf.write(line)
|
buf.write(line.encode('latin1'))
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
class request(object):
|
class request(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.fname = os.path.join(dirname, "requests", name)
|
self.fname = os.path.join(dirname, "requests", name)
|
||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
def run():
|
def run():
|
||||||
src = data_source(self.fname)
|
src = data_source(self.fname)
|
||||||
func(src, RequestParser(src))
|
func(src, RequestParser(src))
|
||||||
run.func_name = func.func_name
|
run.func_name = func.func_name
|
||||||
return run
|
return run
|
||||||
|
|
||||||
|
|
||||||
class FakeSocket(object):
|
class FakeSocket(object):
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
self.tmp = tempfile.TemporaryFile()
|
self.tmp = tempfile.TemporaryFile()
|
||||||
if data:
|
if data:
|
||||||
@ -47,32 +47,32 @@ class FakeSocket(object):
|
|||||||
|
|
||||||
def fileno(self):
|
def fileno(self):
|
||||||
return self.tmp.fileno()
|
return self.tmp.fileno()
|
||||||
|
|
||||||
def len(self):
|
def len(self):
|
||||||
return self.tmp.len
|
return self.tmp.len
|
||||||
|
|
||||||
def recv(self, length=None):
|
def recv(self, length=None):
|
||||||
return self.tmp.read()
|
return self.tmp.read()
|
||||||
|
|
||||||
def recv_into(self, buf, length):
|
def recv_into(self, buf, length):
|
||||||
tmp_buffer = self.tmp.read(length)
|
tmp_buffer = self.tmp.read(length)
|
||||||
v = len(tmp_buffer)
|
v = len(tmp_buffer)
|
||||||
for i, c in enumerate(tmp_buffer):
|
for i, c in enumerate(tmp_buffer):
|
||||||
buf[i] = c
|
buf[i] = c
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
self.tmp.write(data)
|
self.tmp.write(data)
|
||||||
self.tmp.flush()
|
self.tmp.flush()
|
||||||
|
|
||||||
def seek(self, offset, whence=0):
|
def seek(self, offset, whence=0):
|
||||||
self.tmp.seek(offset, whence)
|
self.tmp.seek(offset, whence)
|
||||||
|
|
||||||
|
|
||||||
class http_request(object):
|
class http_request(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.fname = os.path.join(dirname, "requests", name)
|
self.fname = os.path.join(dirname, "requests", name)
|
||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
def run():
|
def run():
|
||||||
fsock = FakeSocket(data_source(self.fname))
|
fsock = FakeSocket(data_source(self.fname))
|
||||||
@ -80,7 +80,7 @@ class http_request(object):
|
|||||||
func(req)
|
func(req)
|
||||||
run.func_name = func.func_name
|
run.func_name = func.func_name
|
||||||
return run
|
return run
|
||||||
|
|
||||||
def eq(a, b):
|
def eq(a, b):
|
||||||
assert a == b, "%r != %r" % (a, b)
|
assert a == b, "%r != %r" % (a, b)
|
||||||
|
|
||||||
@ -117,4 +117,3 @@ def raises(exctype, func, *args, **kwargs):
|
|||||||
func_name = getattr(func, "func_name", "<builtin_function>")
|
func_name = getattr(func, "func_name", "<builtin_function>")
|
||||||
raise AssertionError("Function %s did not raise %s" % (
|
raise AssertionError("Function %s did not raise %s" % (
|
||||||
func_name, exctype.__name__))
|
func_name, exctype.__name__))
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -
|
# -*- coding: utf-8 -
|
||||||
#
|
#
|
||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
import t
|
import t
|
||||||
@ -9,6 +9,8 @@ import treq
|
|||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
dirname = os.path.dirname(__file__)
|
dirname = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
from py.test import skip
|
||||||
reqdir = os.path.join(dirname, "requests", "valid")
|
reqdir = os.path.join(dirname, "requests", "valid")
|
||||||
|
|
||||||
def a_case(fname):
|
def a_case(fname):
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -
|
# -*- coding: utf-8 -
|
||||||
#
|
#
|
||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
import t
|
import t
|
||||||
@ -8,7 +8,8 @@ import treq
|
|||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
from nose.tools import raises
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
dirname = os.path.dirname(__file__)
|
dirname = os.path.dirname(__file__)
|
||||||
reqdir = os.path.join(dirname, "requests", "invalid")
|
reqdir = os.path.join(dirname, "requests", "invalid")
|
||||||
@ -17,12 +18,12 @@ reqdir = os.path.join(dirname, "requests", "invalid")
|
|||||||
def test_http_parser():
|
def test_http_parser():
|
||||||
for fname in glob.glob(os.path.join(reqdir, "*.http")):
|
for fname in glob.glob(os.path.join(reqdir, "*.http")):
|
||||||
env = treq.load_py(os.path.splitext(fname)[0] + ".py")
|
env = treq.load_py(os.path.splitext(fname)[0] + ".py")
|
||||||
|
|
||||||
expect = env['request']
|
expect = env['request']
|
||||||
cfg = env['cfg']
|
cfg = env['cfg']
|
||||||
req = treq.badrequest(fname)
|
req = treq.badrequest(fname)
|
||||||
|
|
||||||
@raises(expect)
|
with pytest.raises(expect):
|
||||||
def check(fname):
|
def f(fname):
|
||||||
return req.check(cfg)
|
return req.check(cfg)
|
||||||
|
f(fname)
|
||||||
yield check, fname # fname is pass so that we know which test failed
|
|
||||||
@ -1,12 +1,10 @@
|
|||||||
# -*- coding: utf-8 -
|
# -*- coding: utf-8 -
|
||||||
#
|
#
|
||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
from nose.plugins.skip import SkipTest
|
|
||||||
|
|
||||||
import t
|
import t
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
@ -23,14 +21,6 @@ def cfg_file():
|
|||||||
def paster_ini():
|
def paster_ini():
|
||||||
return os.path.join(dirname, "..", "examples", "frameworks", "pylonstest", "nose.ini")
|
return os.path.join(dirname, "..", "examples", "frameworks", "pylonstest", "nose.ini")
|
||||||
|
|
||||||
def PasterApp():
|
|
||||||
try:
|
|
||||||
from paste.deploy import loadapp, loadwsgi
|
|
||||||
except ImportError:
|
|
||||||
raise SkipTest()
|
|
||||||
from gunicorn.app.pasterapp import PasterApplication
|
|
||||||
return PasterApplication("no_usage")
|
|
||||||
|
|
||||||
class AltArgs(object):
|
class AltArgs(object):
|
||||||
def __init__(self, args=None):
|
def __init__(self, args=None):
|
||||||
self.args = args or []
|
self.args = args or []
|
||||||
@ -38,17 +28,17 @@ class AltArgs(object):
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
sys.argv = self.args
|
sys.argv = self.args
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_inst, traceback):
|
def __exit__(self, exc_type, exc_inst, traceback):
|
||||||
sys.argv = self.orig
|
sys.argv = self.orig
|
||||||
|
|
||||||
class NoConfigApp(Application):
|
class NoConfigApp(Application):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(NoConfigApp, self).__init__("no_usage")
|
super(NoConfigApp, self).__init__("no_usage")
|
||||||
|
|
||||||
def init(self, parser, opts, args):
|
def init(self, parser, opts, args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -63,25 +53,25 @@ def test_property_access():
|
|||||||
c = config.Config()
|
c = config.Config()
|
||||||
for s in config.KNOWN_SETTINGS:
|
for s in config.KNOWN_SETTINGS:
|
||||||
getattr(c, s.name)
|
getattr(c, s.name)
|
||||||
|
|
||||||
# Class was loaded
|
# Class was loaded
|
||||||
t.eq(c.worker_class, SyncWorker)
|
t.eq(c.worker_class, SyncWorker)
|
||||||
|
|
||||||
# Debug affects workers
|
# Debug affects workers
|
||||||
t.eq(c.workers, 1)
|
t.eq(c.workers, 1)
|
||||||
c.set("workers", 3)
|
c.set("workers", 3)
|
||||||
t.eq(c.workers, 3)
|
t.eq(c.workers, 3)
|
||||||
|
|
||||||
# Address is parsed
|
# Address is parsed
|
||||||
t.eq(c.address, ("127.0.0.1", 8000))
|
t.eq(c.address, ("127.0.0.1", 8000))
|
||||||
|
|
||||||
# User and group defaults
|
# User and group defaults
|
||||||
t.eq(os.geteuid(), c.uid)
|
t.eq(os.geteuid(), c.uid)
|
||||||
t.eq(os.getegid(), c.gid)
|
t.eq(os.getegid(), c.gid)
|
||||||
|
|
||||||
# Proc name
|
# Proc name
|
||||||
t.eq("gunicorn", c.proc_name)
|
t.eq("gunicorn", c.proc_name)
|
||||||
|
|
||||||
# Not a config property
|
# Not a config property
|
||||||
t.raises(AttributeError, getattr, c, "foo")
|
t.raises(AttributeError, getattr, c, "foo")
|
||||||
# Force to be not an error
|
# Force to be not an error
|
||||||
@ -93,10 +83,10 @@ def test_property_access():
|
|||||||
|
|
||||||
# Attempt to set a cfg not via c.set
|
# Attempt to set a cfg not via c.set
|
||||||
t.raises(AttributeError, setattr, c, "proc_name", "baz")
|
t.raises(AttributeError, setattr, c, "proc_name", "baz")
|
||||||
|
|
||||||
# No setting for name
|
# No setting for name
|
||||||
t.raises(AttributeError, c.set, "baz", "bar")
|
t.raises(AttributeError, c.set, "baz", "bar")
|
||||||
|
|
||||||
def test_bool_validation():
|
def test_bool_validation():
|
||||||
c = config.Config()
|
c = config.Config()
|
||||||
t.eq(c.debug, False)
|
t.eq(c.debug, False)
|
||||||
@ -196,30 +186,9 @@ def test_load_config():
|
|||||||
t.eq(app.cfg.bind, "unix:/tmp/bar/baz")
|
t.eq(app.cfg.bind, "unix:/tmp/bar/baz")
|
||||||
t.eq(app.cfg.workers, 3)
|
t.eq(app.cfg.workers, 3)
|
||||||
t.eq(app.cfg.proc_name, "fooey")
|
t.eq(app.cfg.proc_name, "fooey")
|
||||||
|
|
||||||
def test_cli_overrides_config():
|
def test_cli_overrides_config():
|
||||||
with AltArgs(["prog_name", "-c", cfg_file(), "-b", "blarney"]):
|
with AltArgs(["prog_name", "-c", cfg_file(), "-b", "blarney"]):
|
||||||
app = NoConfigApp()
|
app = NoConfigApp()
|
||||||
t.eq(app.cfg.bind, "blarney")
|
t.eq(app.cfg.bind, "blarney")
|
||||||
t.eq(app.cfg.proc_name, "fooey")
|
t.eq(app.cfg.proc_name, "fooey")
|
||||||
|
|
||||||
def test_paster_config():
|
|
||||||
with AltArgs(["prog_name", paster_ini()]):
|
|
||||||
app = PasterApp()
|
|
||||||
t.eq(app.cfg.bind, "192.168.0.1:80")
|
|
||||||
t.eq(app.cfg.proc_name, "brim")
|
|
||||||
t.eq("ignore_me" in app.cfg.settings, False)
|
|
||||||
|
|
||||||
def test_cfg_over_paster():
|
|
||||||
with AltArgs(["prog_name", "-c", cfg_file(), paster_ini()]):
|
|
||||||
app = PasterApp()
|
|
||||||
t.eq(app.cfg.bind, "unix:/tmp/bar/baz")
|
|
||||||
t.eq(app.cfg.proc_name, "fooey")
|
|
||||||
t.eq(app.cfg.default_proc_name, "blurgh")
|
|
||||||
|
|
||||||
def test_cli_cfg_paster():
|
|
||||||
with AltArgs(["prog_name", "-c", cfg_file(), "-b", "whee", paster_ini()]):
|
|
||||||
app = PasterApp()
|
|
||||||
t.eq(app.cfg.bind, "whee")
|
|
||||||
t.eq(app.cfg.proc_name, "fooey")
|
|
||||||
t.eq(app.cfg.default_proc_name, "blurgh")
|
|
||||||
61
tests/test_004-http-body.py
Normal file
61
tests/test_004-http-body.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import t
|
||||||
|
from gunicorn.http.body import Body
|
||||||
|
from gunicorn.six import BytesIO
|
||||||
|
|
||||||
|
|
||||||
|
def assert_readline(payload, size, expected):
|
||||||
|
body = Body(BytesIO(payload))
|
||||||
|
t.eq(body.readline(size), expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_empty_body():
|
||||||
|
assert_readline(b"", None, b"")
|
||||||
|
assert_readline(b"", 1, b"")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_zero_size():
|
||||||
|
assert_readline(b"abc", 0, b"")
|
||||||
|
assert_readline(b"\n", 0, b"")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_new_line_before_size():
|
||||||
|
body = Body(BytesIO(b"abc\ndef"))
|
||||||
|
t.eq(body.readline(4), b"abc\n")
|
||||||
|
t.eq(body.readline(), b"def")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_new_line_after_size():
|
||||||
|
body = Body(BytesIO(b"abc\ndef"))
|
||||||
|
t.eq(body.readline(2), b"ab")
|
||||||
|
t.eq(body.readline(), b"c\n")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_no_new_line():
|
||||||
|
body = Body(BytesIO(b"abcdef"))
|
||||||
|
t.eq(body.readline(), b"abcdef")
|
||||||
|
body = Body(BytesIO(b"abcdef"))
|
||||||
|
t.eq(body.readline(2), b"ab")
|
||||||
|
t.eq(body.readline(2), b"cd")
|
||||||
|
t.eq(body.readline(2), b"ef")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_buffer_loaded():
|
||||||
|
reader = BytesIO(b"abc\ndef")
|
||||||
|
body = Body(reader)
|
||||||
|
body.read(1) # load internal buffer
|
||||||
|
reader.write(b"g\nhi")
|
||||||
|
reader.seek(7)
|
||||||
|
print(reader.getvalue())
|
||||||
|
t.eq(body.readline(), b"bc\n")
|
||||||
|
t.eq(body.readline(), b"defg\n")
|
||||||
|
t.eq(body.readline(), b"hi")
|
||||||
|
|
||||||
|
|
||||||
|
def test_readline_buffer_loaded_with_size():
|
||||||
|
body = Body(BytesIO(b"abc\ndef"))
|
||||||
|
body.read(1) # load internal buffer
|
||||||
|
t.eq(body.readline(2), b"bc")
|
||||||
|
t.eq(body.readline(2), b"\n")
|
||||||
|
t.eq(body.readline(2), b"de")
|
||||||
|
t.eq(body.readline(2), b"f")
|
||||||
|
|
||||||
@ -10,18 +10,19 @@ import t
|
|||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from gunicorn.config import Config
|
from gunicorn.config import Config
|
||||||
from gunicorn.http.errors import ParseException
|
from gunicorn.http.errors import ParseException
|
||||||
from gunicorn.http.parser import RequestParser
|
from gunicorn.http.parser import RequestParser
|
||||||
|
from gunicorn.six import urlparse, execfile_
|
||||||
|
from gunicorn import six
|
||||||
|
|
||||||
dirname = os.path.dirname(__file__)
|
dirname = os.path.dirname(__file__)
|
||||||
random.seed()
|
random.seed()
|
||||||
|
|
||||||
def uri(data):
|
def uri(data):
|
||||||
ret = {"raw": data}
|
ret = {"raw": data}
|
||||||
parts = urlparse.urlparse(data)
|
parts = urlparse(data)
|
||||||
ret["scheme"] = parts.scheme or ''
|
ret["scheme"] = parts.scheme or ''
|
||||||
ret["host"] = parts.netloc.rsplit(":", 1)[0] or None
|
ret["host"] = parts.netloc.rsplit(":", 1)[0] or None
|
||||||
ret["port"] = parts.port or 80
|
ret["port"] = parts.port or 80
|
||||||
@ -42,7 +43,7 @@ def load_py(fname):
|
|||||||
config = globals().copy()
|
config = globals().copy()
|
||||||
config["uri"] = uri
|
config["uri"] = uri
|
||||||
config["cfg"] = Config()
|
config["cfg"] = Config()
|
||||||
execfile(fname, config)
|
execfile_(fname, config)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
class request(object):
|
class request(object):
|
||||||
@ -54,10 +55,10 @@ class request(object):
|
|||||||
if not isinstance(self.expect, list):
|
if not isinstance(self.expect, list):
|
||||||
self.expect = [self.expect]
|
self.expect = [self.expect]
|
||||||
|
|
||||||
with open(self.fname) as handle:
|
with open(self.fname, 'rb') as handle:
|
||||||
self.data = handle.read()
|
self.data = handle.read()
|
||||||
self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n")
|
self.data = self.data.replace(b"\n", b"").replace(b"\\r\\n", b"\r\n")
|
||||||
self.data = self.data.replace("\\0", "\000")
|
self.data = self.data.replace(b"\\0", b"\000")
|
||||||
|
|
||||||
# Functions for sending data to the parser.
|
# Functions for sending data to the parser.
|
||||||
# These functions mock out reading from a
|
# These functions mock out reading from a
|
||||||
@ -69,20 +70,20 @@ class request(object):
|
|||||||
|
|
||||||
def send_lines(self):
|
def send_lines(self):
|
||||||
lines = self.data
|
lines = self.data
|
||||||
pos = lines.find("\r\n")
|
pos = lines.find(b"\r\n")
|
||||||
while pos > 0:
|
while pos > 0:
|
||||||
yield lines[:pos+2]
|
yield lines[:pos+2]
|
||||||
lines = lines[pos+2:]
|
lines = lines[pos+2:]
|
||||||
pos = lines.find("\r\n")
|
pos = lines.find(b"\r\n")
|
||||||
if len(lines):
|
if len(lines):
|
||||||
yield lines
|
yield lines
|
||||||
|
|
||||||
def send_bytes(self):
|
def send_bytes(self):
|
||||||
for d in self.data:
|
for d in str(self.data, "latin1"):
|
||||||
yield d
|
yield bytes(d, "latin1")
|
||||||
|
|
||||||
def send_random(self):
|
def send_random(self):
|
||||||
maxs = len(self.data) / 10
|
maxs = round(len(self.data) / 10)
|
||||||
read = 0
|
read = 0
|
||||||
while read < len(self.data):
|
while read < len(self.data):
|
||||||
chunk = random.randint(1, maxs)
|
chunk = random.randint(1, maxs)
|
||||||
@ -143,7 +144,7 @@ class request(object):
|
|||||||
while len(body):
|
while len(body):
|
||||||
if body[:len(data)] != data:
|
if body[:len(data)] != data:
|
||||||
raise AssertionError("Invalid data read: %r" % data)
|
raise AssertionError("Invalid data read: %r" % data)
|
||||||
if '\n' in data[:-1]:
|
if b'\n' in data[:-1]:
|
||||||
raise AssertionError("Embedded new line: %r" % data)
|
raise AssertionError("Embedded new line: %r" % data)
|
||||||
body = body[len(data):]
|
body = body[len(data):]
|
||||||
data = self.szread(req.body.readline, sizes)
|
data = self.szread(req.body.readline, sizes)
|
||||||
@ -165,7 +166,7 @@ class request(object):
|
|||||||
"""
|
"""
|
||||||
data = req.body.readlines()
|
data = req.body.readlines()
|
||||||
for line in data:
|
for line in data:
|
||||||
if '\n' in line[:-1]:
|
if b'\n' in line[:-1]:
|
||||||
raise AssertionError("Embedded new line: %r" % line)
|
raise AssertionError("Embedded new line: %r" % line)
|
||||||
if line != body[:len(line)]:
|
if line != body[:len(line)]:
|
||||||
raise AssertionError("Invalid body data read: %r != %r" % (
|
raise AssertionError("Invalid body data read: %r != %r" % (
|
||||||
@ -182,7 +183,7 @@ class request(object):
|
|||||||
This skips sizes because there's its not part of the iter api.
|
This skips sizes because there's its not part of the iter api.
|
||||||
"""
|
"""
|
||||||
for line in req.body:
|
for line in req.body:
|
||||||
if '\n' in line[:-1]:
|
if b'\n' in line[:-1]:
|
||||||
raise AssertionError("Embedded new line: %r" % line)
|
raise AssertionError("Embedded new line: %r" % line)
|
||||||
if line != body[:len(line)]:
|
if line != body[:len(line)]:
|
||||||
raise AssertionError("Invalid body data read: %r != %r" % (
|
raise AssertionError("Invalid body data read: %r != %r" % (
|
||||||
@ -191,7 +192,7 @@ class request(object):
|
|||||||
if len(body):
|
if len(body):
|
||||||
raise AssertionError("Failed to read entire body: %r" % body)
|
raise AssertionError("Failed to read entire body: %r" % body)
|
||||||
try:
|
try:
|
||||||
data = iter(req.body).next()
|
data = six.next(iter(req.body))
|
||||||
raise AssertionError("Read data after body finished: %r" % data)
|
raise AssertionError("Read data after body finished: %r" % data)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
pass
|
pass
|
||||||
@ -214,9 +215,15 @@ class request(object):
|
|||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
for (mt, sz, sn) in cfgs:
|
for (mt, sz, sn) in cfgs:
|
||||||
mtn = mt.func_name[6:]
|
if hasattr(mt, 'funcname'):
|
||||||
szn = sz.func_name[5:]
|
mtn = mt.func_name[6:]
|
||||||
snn = sn.func_name[5:]
|
szn = sz.func_name[5:]
|
||||||
|
snn = sn.func_name[5:]
|
||||||
|
else:
|
||||||
|
mtn = mt.__name__[6:]
|
||||||
|
szn = sz.__name__[5:]
|
||||||
|
snn = sn.__name__[5:]
|
||||||
|
|
||||||
def test_req(sn, sz, mt):
|
def test_req(sn, sz, mt):
|
||||||
self.check(cfg, sn, sz, mt)
|
self.check(cfg, sn, sz, mt)
|
||||||
desc = "%s: MT: %s SZ: %s SN: %s" % (self.name, mtn, szn, snn)
|
desc = "%s: MT: %s SZ: %s SN: %s" % (self.name, mtn, szn, snn)
|
||||||
@ -251,9 +258,10 @@ class badrequest(object):
|
|||||||
self.data = handle.read()
|
self.data = handle.read()
|
||||||
self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n")
|
self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n")
|
||||||
self.data = self.data.replace("\\0", "\000")
|
self.data = self.data.replace("\\0", "\000")
|
||||||
|
self.data = self.data.encode('latin1')
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
maxs = len(self.data) / 10
|
maxs = round(len(self.data) / 10)
|
||||||
read = 0
|
read = 0
|
||||||
while read < len(self.data):
|
while read < len(self.data):
|
||||||
chunk = random.randint(1, maxs)
|
chunk = random.randint(1, maxs)
|
||||||
@ -262,5 +270,4 @@ class badrequest(object):
|
|||||||
|
|
||||||
def check(self, cfg):
|
def check(self, cfg):
|
||||||
p = RequestParser(cfg, self.send())
|
p = RequestParser(cfg, self.send())
|
||||||
[req for req in p]
|
six.next(p)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user