mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
naive working integration of simplehttp parser. async worker is slower
than the non async actually for unkown reason and slower than with old parser.
This commit is contained in:
parent
eb0d54e111
commit
d9a2579613
@ -17,6 +17,8 @@ except ImportError:
|
|||||||
import sys
|
import sys
|
||||||
from urllib import unquote
|
from urllib import unquote
|
||||||
|
|
||||||
|
from simplehttp import RequestParser
|
||||||
|
|
||||||
from gunicorn import __version__
|
from gunicorn import __version__
|
||||||
from gunicorn.http.parser import Parser
|
from gunicorn.http.parser import Parser
|
||||||
from gunicorn.http.response import Response, KeepAliveResponse
|
from gunicorn.http.response import Response, KeepAliveResponse
|
||||||
@ -54,41 +56,54 @@ class Request(object):
|
|||||||
self.response_status = None
|
self.response_status = None
|
||||||
self.response_headers = []
|
self.response_headers = []
|
||||||
self._version = 11
|
self._version = 11
|
||||||
self.parser = Parser.parse_request()
|
self.parser = RequestParser(self.socket)
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
self.response = None
|
self.response = None
|
||||||
self.response_chunked = False
|
self.response_chunked = False
|
||||||
self.headers_sent = False
|
self.headers_sent = False
|
||||||
|
self.req = None
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
environ = {}
|
environ = {}
|
||||||
headers = []
|
headers = []
|
||||||
buf = StringIO()
|
|
||||||
data = self.socket.recv(CHUNK_SIZE)
|
|
||||||
buf.write(data)
|
|
||||||
buf2 = self.parser.filter_headers(headers, buf)
|
|
||||||
if not buf2:
|
|
||||||
while True:
|
|
||||||
data = self.socket.recv(CHUNK_SIZE)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buf.write(data)
|
|
||||||
buf2 = self.parser.filter_headers(headers, buf)
|
|
||||||
if buf2:
|
|
||||||
break
|
|
||||||
|
|
||||||
self.log.debug("%s", self.parser.status)
|
|
||||||
self.log.debug("Headers:\n%s" % headers)
|
|
||||||
|
|
||||||
if self.parser.headers_dict.get('Expect','').lower() == "100-continue":
|
ended = False
|
||||||
self.socket.send("HTTP/1.1 100 Continue\r\n\r\n")
|
req = None
|
||||||
|
|
||||||
if not self.parser.content_len and not self.parser.is_chunked:
|
self.req = req = self.parser.next()
|
||||||
wsgi_input = TeeInput(self.cfg, self.socket, self.parser, StringIO())
|
|
||||||
content_length = "0"
|
##self.log.debug("%s", self.parser.status)
|
||||||
|
self.log.debug("Headers:\n%s" % req.headers)
|
||||||
|
|
||||||
|
# authors should be aware that REMOTE_HOST and REMOTE_ADDR
|
||||||
|
# may not qualify the remote addr:
|
||||||
|
# http://www.ietf.org/rfc/rfc3875
|
||||||
|
client_address = self.client_address or "127.0.0.1"
|
||||||
|
forward_address = client_address
|
||||||
|
server_address = self.server_address
|
||||||
|
script_name = os.environ.get("SCRIPT_NAME", "")
|
||||||
|
content_type = ""
|
||||||
|
for hdr_name, hdr_value in req.headers:
|
||||||
|
name = hdr_name.lower()
|
||||||
|
if name == "expect":
|
||||||
|
# handle expect
|
||||||
|
if hdr_value.lower() == "100-continue":
|
||||||
|
self.socket.send("HTTP/1.1 100 Continue\r\n\r\n")
|
||||||
|
elif name == "x-forwarded-for":
|
||||||
|
forward_address = hdr_value
|
||||||
|
elif name == "host":
|
||||||
|
host = hdr_value
|
||||||
|
elif name == "script_name":
|
||||||
|
script_name = hdr_value
|
||||||
|
elif name == "content-type":
|
||||||
|
content_type = hdr_value
|
||||||
|
|
||||||
|
|
||||||
|
wsgi_input = req.body
|
||||||
|
if hasattr(req.body, "length"):
|
||||||
|
content_length = str(req.body.length)
|
||||||
else:
|
else:
|
||||||
wsgi_input = TeeInput(self.cfg, self.socket, self.parser, buf2)
|
content_length = None
|
||||||
content_length = str(wsgi_input.len)
|
|
||||||
|
|
||||||
# This value should evaluate true if an equivalent application
|
# This value should evaluate true if an equivalent application
|
||||||
# object may be simultaneously invoked by another process, and
|
# object may be simultaneously invoked by another process, and
|
||||||
@ -96,44 +111,27 @@ class Request(object):
|
|||||||
# worker so we comply to pylons and other paster app.
|
# worker so we comply to pylons and other paster app.
|
||||||
wsgi_multiprocess = self.cfg.workers > 1
|
wsgi_multiprocess = self.cfg.workers > 1
|
||||||
|
|
||||||
# authors should be aware that REMOTE_HOST and REMOTE_ADDR
|
if isinstance(forward_address, basestring):
|
||||||
# may not qualify the remote addr:
|
|
||||||
# http://www.ietf.org/rfc/rfc3875
|
|
||||||
client_address = self.client_address or "127.0.0.1"
|
|
||||||
forward_adress = self.parser.headers_dict.get('X-Forwarded-For',
|
|
||||||
client_address)
|
|
||||||
|
|
||||||
if self.parser.headers_dict.get("X-Forwarded-Protocol") == "https" or \
|
|
||||||
self.parser.headers_dict.get("X-Forwarded-Ssl") == "on":
|
|
||||||
url_scheme = "https"
|
|
||||||
else:
|
|
||||||
url_scheme = "http"
|
|
||||||
|
|
||||||
if isinstance(forward_adress, basestring):
|
|
||||||
# we only took the last one
|
# we only took the last one
|
||||||
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||||
if "," in forward_adress:
|
if "," in forward_address:
|
||||||
forward_adress = forward_adress.split(",")[-1].strip()
|
forward_adress = forward_address.split(",")[-1].strip()
|
||||||
remote_addr = forward_adress.split(":")
|
remote_addr = forward_address.split(":")
|
||||||
if len(remote_addr) == 1:
|
if len(remote_addr) == 1:
|
||||||
remote_addr.append('')
|
remote_addr.append('')
|
||||||
else:
|
else:
|
||||||
remote_addr = forward_adress
|
remote_addr = forward_address
|
||||||
|
|
||||||
# Try to server address from headers
|
|
||||||
server_address = self.parser.headers_dict.get('Host',
|
|
||||||
self.server_address)
|
|
||||||
if isinstance(server_address, basestring):
|
if isinstance(server_address, basestring):
|
||||||
server_address = server_address.split(":")
|
server_address = server_address.split(":")
|
||||||
if len(server_address) == 1:
|
if len(server_address) == 1:
|
||||||
server_address.append('')
|
server_address.append('')
|
||||||
|
|
||||||
script_name = self.parser.headers_dict.get("SCRIPT_NAME",
|
path_info = req.path
|
||||||
os.environ.get("SCRIPT_NAME", ""))
|
|
||||||
path_info = self.parser.path
|
|
||||||
if script_name:
|
if script_name:
|
||||||
path_info = path_info.split(script_name, 1)[-1]
|
path_info = path_info.split(script_name, 1)[-1]
|
||||||
|
|
||||||
|
|
||||||
environ = {
|
environ = {
|
||||||
"wsgi.url_scheme": url_scheme,
|
"wsgi.url_scheme": url_scheme,
|
||||||
"wsgi.input": wsgi_input,
|
"wsgi.input": wsgi_input,
|
||||||
@ -144,23 +142,24 @@ class Request(object):
|
|||||||
"wsgi.run_once": False,
|
"wsgi.run_once": False,
|
||||||
"SCRIPT_NAME": script_name,
|
"SCRIPT_NAME": script_name,
|
||||||
"SERVER_SOFTWARE": self.SERVER_VERSION,
|
"SERVER_SOFTWARE": self.SERVER_VERSION,
|
||||||
"REQUEST_METHOD": self.parser.method,
|
"REQUEST_METHOD": req.method,
|
||||||
"PATH_INFO": unquote(path_info),
|
"PATH_INFO": unquote(path_info),
|
||||||
"QUERY_STRING": self.parser.query_string,
|
"QUERY_STRING": req.query,
|
||||||
"RAW_URI": self.parser.raw_path,
|
"RAW_URI": req.path,
|
||||||
"CONTENT_TYPE": self.parser.headers_dict.get('Content-Type', ''),
|
"CONTENT_TYPE": content_type,
|
||||||
"CONTENT_LENGTH": content_length,
|
"CONTENT_LENGTH": content_length,
|
||||||
"REMOTE_ADDR": remote_addr[0],
|
"REMOTE_ADDR": remote_addr[0],
|
||||||
"REMOTE_PORT": str(remote_addr[1]),
|
"REMOTE_PORT": str(remote_addr[1]),
|
||||||
"SERVER_NAME": server_address[0],
|
"SERVER_NAME": server_address[0],
|
||||||
"SERVER_PORT": str(server_address[1]),
|
"SERVER_PORT": str(server_address[1]),
|
||||||
"SERVER_PROTOCOL": self.parser.raw_version
|
"SERVER_PROTOCOL": req.version
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value in self.parser.headers:
|
for key, value in req.headers:
|
||||||
key = 'HTTP_' + key.upper().replace('-', '_')
|
key = 'HTTP_' + key.upper().replace('-', '_')
|
||||||
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
|
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
|
||||||
environ[key] = value
|
environ[key] = value
|
||||||
|
|
||||||
return environ
|
return environ
|
||||||
|
|
||||||
def start_response(self, status, headers, exc_info=None):
|
def start_response(self, status, headers, exc_info=None):
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class KeepAliveResponse(Response):
|
|||||||
|
|
||||||
def default_headers(self):
|
def default_headers(self):
|
||||||
connection = "keep-alive"
|
connection = "keep-alive"
|
||||||
if self.req.parser.should_close:
|
if self.req.req.should_close():
|
||||||
connection = "close"
|
connection = "close"
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class AsyncWorker(Worker):
|
|||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
environ = req.read()
|
environ = req.read()
|
||||||
if not environ or not req.parser.headers:
|
if not environ:
|
||||||
return False
|
return False
|
||||||
respiter = self.wsgi(environ, req.start_response)
|
respiter = self.wsgi(environ, req.start_response)
|
||||||
if respiter == ALREADY_HANDLED:
|
if respiter == ALREADY_HANDLED:
|
||||||
@ -65,7 +65,7 @@ class AsyncWorker(Worker):
|
|||||||
req.response.close()
|
req.response.close()
|
||||||
if hasattr(respiter, "close"):
|
if hasattr(respiter, "close"):
|
||||||
respiter.close()
|
respiter.close()
|
||||||
if req.parser.should_close:
|
if req.req.should_close():
|
||||||
return False
|
return False
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
#Only send back traceback in HTTP in debug mode.
|
#Only send back traceback in HTTP in debug mode.
|
||||||
|
|||||||
@ -92,7 +92,7 @@ class SyncWorker(Worker):
|
|||||||
req = http.Request(self.cfg, client, addr, self.address)
|
req = http.Request(self.cfg, client, addr, self.address)
|
||||||
try:
|
try:
|
||||||
environ = req.read()
|
environ = req.read()
|
||||||
if not environ or not req.parser.status_line:
|
if not environ:
|
||||||
return
|
return
|
||||||
respiter = self.wsgi(environ, req.start_response)
|
respiter = self.wsgi(environ, req.start_response)
|
||||||
for item in respiter:
|
for item in respiter:
|
||||||
|
|||||||
5
setup.py
5
setup.py
@ -41,9 +41,8 @@ setup(
|
|||||||
packages = find_packages(exclude=['examples', 'tests']),
|
packages = find_packages(exclude=['examples', 'tests']),
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
||||||
install_requires=['setuptools'],
|
install_requires=['setuptools', 'simplehttp'],
|
||||||
|
|
||||||
|
|
||||||
entry_points="""
|
entry_points="""
|
||||||
|
|
||||||
[console_scripts]
|
[console_scripts]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user