mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
send appropriate error status on http parsing. Fix issue #132.
This commit is contained in:
parent
b62055d529
commit
a8e34ac16c
@ -45,7 +45,7 @@ hop_headers = set("""
|
||||
te trailers transfer-encoding upgrade
|
||||
server date
|
||||
""".split())
|
||||
|
||||
|
||||
try:
|
||||
from setproctitle import setproctitle
|
||||
def _setproctitle(title):
|
||||
@ -178,27 +178,28 @@ def writelines(sock, lines, chunked=False):
|
||||
for line in list(lines):
|
||||
write(sock, line, chunked)
|
||||
|
||||
def write_error(sock, msg):
|
||||
def write_error(sock, msg, status_int=500,
|
||||
reason="Internal Server Error"):
|
||||
html = textwrap.dedent("""\
|
||||
<html>
|
||||
<head>
|
||||
<title>Internal Server Error</title>
|
||||
<title>%(reason)s</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Internal Server Error</h1>
|
||||
<h2>WSGI Error Report:</h2>
|
||||
<pre>%s</pre>
|
||||
<h1>%(reason)s</h1>
|
||||
%(msg)s
|
||||
</body>
|
||||
</html>
|
||||
""") % msg
|
||||
""") % {"reason": reason, "msg": msg}
|
||||
|
||||
http = textwrap.dedent("""\
|
||||
HTTP/1.1 500 Internal Server Error\r
|
||||
HTTP/1.1 %s %s\r
|
||||
Connection: close\r
|
||||
Content-Type: text/html\r
|
||||
Content-Length: %d\r
|
||||
\r
|
||||
%s
|
||||
""") % (len(html), html)
|
||||
""") % (str(status_int), reason, len(html), html)
|
||||
write_nonblock(sock, http)
|
||||
|
||||
def normalize_name(name):
|
||||
|
||||
@ -48,13 +48,7 @@ class AsyncWorker(base.Worker):
|
||||
self.log.debug("Ignoring EPIPE")
|
||||
except Exception, e:
|
||||
self.log.exception("General error processing request.")
|
||||
try:
|
||||
# Last ditch attempt to notify the client of an error.
|
||||
mesg = "HTTP/1.0 500 Internal Server Error\r\n\r\n"
|
||||
util.write_nonblock(client, mesg)
|
||||
except:
|
||||
pass
|
||||
return
|
||||
self.handle_error(client, e)
|
||||
finally:
|
||||
util.close(client)
|
||||
|
||||
@ -82,9 +76,7 @@ class AsyncWorker(base.Worker):
|
||||
raise
|
||||
except Exception, e:
|
||||
#Only send back traceback in HTTP in debug mode.
|
||||
if not self.debug:
|
||||
raise
|
||||
util.write_error(sock, traceback.format_exc())
|
||||
self.handle_error(sock, e)
|
||||
return False
|
||||
finally:
|
||||
try:
|
||||
|
||||
@ -10,10 +10,16 @@ import random
|
||||
import signal
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
|
||||
from gunicorn import util
|
||||
from gunicorn.workers.workertmp import WorkerTmp
|
||||
|
||||
from gunicorn.http.errors import InvalidHeader, InvalidHeaderName, \
|
||||
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion
|
||||
|
||||
|
||||
class Worker(object):
|
||||
|
||||
SIGNALS = map(
|
||||
@ -110,6 +116,37 @@ class Worker(object):
|
||||
self.alive = False
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def handle_error(self, client, exc):
|
||||
|
||||
if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
|
||||
InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,)):
|
||||
|
||||
if isinstance(exc, InvalidRequestLine):
|
||||
mesg = "<p>Invalid Request Line '%s'</p>" % str(exc)
|
||||
elif isinstance(exc, InvalidRequestMethod):
|
||||
mesg = "<p>Invalid Method'%s'</p>" % str(exc)
|
||||
elif isinstance(exc, InvalidHTTPVersion):
|
||||
mesg = "<p>Invalid HTTP Version '%s'</p>" % str(exc)
|
||||
elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
|
||||
mesg = "<p>Invalid Header'%s'</p>" % str(exc)
|
||||
reason = "Bad Request"
|
||||
status_int = 400
|
||||
else:
|
||||
mesg = reason = "Internal Server reason"
|
||||
status_int = 500
|
||||
|
||||
if self.debug:
|
||||
tb = traceback.format_exc()
|
||||
mesg += "<h2>Traceback:</23><pre>%s</pre>" % tb
|
||||
|
||||
try:
|
||||
util.write_error(client, mesg, status_int=status_int,
|
||||
reason=reason)
|
||||
except:
|
||||
self.log.warning("Unexpected error" % traceback.format_exc())
|
||||
pass
|
||||
|
||||
def handle_winch(self, sig, fname):
|
||||
# Ignore SIGWINCH in worker. Fixes a crash on OpenBSD.
|
||||
return
|
||||
|
||||
@ -72,7 +72,6 @@ class GeventWorker(AsyncWorker):
|
||||
worker=self)
|
||||
|
||||
server.start()
|
||||
|
||||
try:
|
||||
while self.alive:
|
||||
self.notify()
|
||||
|
||||
@ -8,7 +8,6 @@ import errno
|
||||
import os
|
||||
import select
|
||||
import socket
|
||||
import traceback
|
||||
|
||||
import gunicorn.http as http
|
||||
import gunicorn.http.wsgi as wsgi
|
||||
@ -63,7 +62,7 @@ class SyncWorker(base.Worker):
|
||||
else:
|
||||
return
|
||||
raise
|
||||
|
||||
|
||||
def handle(self, client, addr):
|
||||
try:
|
||||
parser = http.RequestParser(client)
|
||||
@ -78,12 +77,7 @@ class SyncWorker(base.Worker):
|
||||
self.log.debug("Ignoring EPIPE")
|
||||
except Exception, e:
|
||||
self.log.exception("Error processing request.")
|
||||
try:
|
||||
# Last ditch attempt to notify the client of an error.
|
||||
mesg = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
||||
util.write_nonblock(client, mesg)
|
||||
except:
|
||||
pass
|
||||
self.handle_error(client, e)
|
||||
finally:
|
||||
util.close(client)
|
||||
|
||||
@ -111,9 +105,7 @@ class SyncWorker(base.Worker):
|
||||
raise
|
||||
except Exception, e:
|
||||
# Only send back traceback in HTTP in debug mode.
|
||||
if not self.debug:
|
||||
raise
|
||||
util.write_error(client, traceback.format_exc())
|
||||
self.handle_error(client, e)
|
||||
return
|
||||
finally:
|
||||
try:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user