mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
PEP8 fixes
This commit is contained in:
parent
1c9b8460b1
commit
20cd49595a
@ -1,4 +1,4 @@
|
||||
# -*- 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.
|
||||
|
||||
@ -13,6 +13,7 @@ from gunicorn.config import Config
|
||||
from gunicorn import debug
|
||||
from gunicorn.six import execfile_
|
||||
|
||||
|
||||
class Application(object):
|
||||
"""\
|
||||
An application interface for configuring and loading
|
||||
@ -129,4 +130,3 @@ class Application(object):
|
||||
sys.stderr.write("\nError: %s\n\n" % e)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ def make_wsgi_application():
|
||||
return get_internal_wsgi_application()
|
||||
return WSGIHandler()
|
||||
|
||||
|
||||
def reload_django_settings():
|
||||
mod = util.import_module(os.environ['DJANGO_SETTINGS_MODULE'])
|
||||
|
||||
@ -63,7 +64,7 @@ def reload_django_settings():
|
||||
if setting == setting.upper():
|
||||
setting_value = getattr(mod, setting)
|
||||
if setting in tuple_settings and type(setting_value) == str:
|
||||
setting_value = (setting_value,) # In case the user forgot the comma.
|
||||
setting_value = (setting_value,) # In case the user forgot the comma.
|
||||
setattr(settings, setting, setting_value)
|
||||
|
||||
# Expand entries in INSTALLED_APPS like "django.contrib.*" to a list
|
||||
|
||||
@ -9,6 +9,7 @@ import sys
|
||||
from gunicorn.app.base import Application
|
||||
from gunicorn import util
|
||||
|
||||
|
||||
def is_setting_mod(path):
|
||||
return (os.path.isfile(os.path.join(path, "settings.py")) or
|
||||
os.path.isfile(os.path.join(path, "settings.pyc")))
|
||||
@ -34,7 +35,7 @@ def find_settings_module(path):
|
||||
project_path = path
|
||||
elif os.path.isfile(path):
|
||||
project_path = os.path.dirname(path)
|
||||
settings_name, _ = os.path.splitext(os.path.basename(path))
|
||||
settings_name, _ = os.path.splitext(os.path.basename(path))
|
||||
|
||||
return project_path, settings_name
|
||||
|
||||
@ -91,7 +92,6 @@ class DjangoApplication(Application):
|
||||
settings_name))
|
||||
self.cfg.set("pythonpath", pythonpath)
|
||||
|
||||
|
||||
def load(self):
|
||||
# set settings
|
||||
make_default_env(self.cfg)
|
||||
@ -114,7 +114,6 @@ class DjangoApplicationCommand(Application):
|
||||
|
||||
self.do_load_config()
|
||||
|
||||
|
||||
def init(self, *args):
|
||||
if 'settings' in self.options:
|
||||
self.options['django_settings'] = self.options.pop('settings')
|
||||
@ -133,6 +132,7 @@ class DjangoApplicationCommand(Application):
|
||||
mod = util.import_module("gunicorn.app.django_wsgi")
|
||||
return mod.make_command_wsgi_application(self.admin_media_path)
|
||||
|
||||
|
||||
def run():
|
||||
"""\
|
||||
The ``gunicorn_django`` command line runner for launching Django
|
||||
|
||||
@ -18,6 +18,7 @@ SERVER = loadwsgi.SERVER
|
||||
from gunicorn.app.base import Application
|
||||
from gunicorn.config import Config
|
||||
|
||||
|
||||
class PasterBaseApplication(Application):
|
||||
|
||||
def app_config(self):
|
||||
@ -60,6 +61,7 @@ class PasterBaseApplication(Application):
|
||||
fileConfig(config_file, dict(__file__=config_file,
|
||||
here=os.path.dirname(config_file)))
|
||||
|
||||
|
||||
class PasterApplication(PasterBaseApplication):
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
@ -83,6 +85,7 @@ class PasterApplication(PasterBaseApplication):
|
||||
def load(self):
|
||||
return loadapp(self.cfgurl, relative_to=self.relpath)
|
||||
|
||||
|
||||
class PasterServerApplication(PasterBaseApplication):
|
||||
|
||||
def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
@ -119,13 +122,12 @@ class PasterServerApplication(PasterBaseApplication):
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def load_config(self):
|
||||
if not hasattr(self, "cfgfname"):
|
||||
return
|
||||
|
||||
cfg = self.app_config()
|
||||
for k,v in cfg.items():
|
||||
for k, v in cfg.items():
|
||||
try:
|
||||
self.cfg.set(k.lower(), v)
|
||||
except:
|
||||
@ -147,6 +149,7 @@ def run():
|
||||
from gunicorn.app.pasterapp import PasterApplication
|
||||
PasterApplication("%prog [OPTIONS] pasteconfig.ini").run()
|
||||
|
||||
|
||||
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
"""\
|
||||
A paster server.
|
||||
|
||||
@ -9,6 +9,7 @@ import sys
|
||||
from gunicorn import util
|
||||
from gunicorn.app.base import Application
|
||||
|
||||
|
||||
class WSGIApplication(Application):
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
@ -23,6 +24,7 @@ class WSGIApplication(Application):
|
||||
def load(self):
|
||||
return util.import_app(self.app_uri)
|
||||
|
||||
|
||||
def run():
|
||||
"""\
|
||||
The ``gunicorn`` command line runner for launcing Gunicorn with
|
||||
|
||||
@ -13,7 +13,6 @@ import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
|
||||
from gunicorn.errors import HaltServer
|
||||
from gunicorn.pidfile import Pidfile
|
||||
from gunicorn.sock import create_sockets
|
||||
@ -21,6 +20,7 @@ from gunicorn import util
|
||||
|
||||
from gunicorn import __version__, SERVER_SOFTWARE
|
||||
|
||||
|
||||
class Arbiter(object):
|
||||
"""
|
||||
Arbiter maintain the workers processes alive. It launches or
|
||||
@ -82,6 +82,7 @@ class Arbiter(object):
|
||||
|
||||
def _get_num_workers(self):
|
||||
return self._num_workers
|
||||
|
||||
def _set_num_workers(self, value):
|
||||
old_value = self._num_workers
|
||||
self._num_workers = value
|
||||
@ -106,8 +107,6 @@ class Arbiter(object):
|
||||
|
||||
if self.cfg.debug:
|
||||
self.log.debug("Current configuration:")
|
||||
|
||||
|
||||
for config, value in sorted(self.cfg.settings.items(),
|
||||
key=lambda setting: setting[1]):
|
||||
self.log.debug(" %s: %s", config, value.value)
|
||||
@ -322,7 +321,6 @@ class Arbiter(object):
|
||||
except KeyboardInterrupt:
|
||||
sys.exit()
|
||||
|
||||
|
||||
def stop(self, graceful=True):
|
||||
"""\
|
||||
Stop workers
|
||||
@ -367,7 +365,7 @@ class Arbiter(object):
|
||||
|
||||
# close all file descriptors except bound sockets
|
||||
util.closerange(3, fds[0])
|
||||
util.closerange(fds[-1]+1, util.get_maxfd())
|
||||
util.closerange(fds[-1] + 1, util.get_maxfd())
|
||||
|
||||
os.execvpe(self.START_CTX[0], self.START_CTX['args'], os.environ)
|
||||
|
||||
@ -470,7 +468,7 @@ class Arbiter(object):
|
||||
def spawn_worker(self):
|
||||
self.worker_age += 1
|
||||
worker = self.worker_class(self.worker_age, self.pid, self.LISTENERS,
|
||||
self.app, self.timeout/2.0,
|
||||
self.app, self.timeout / 2.0,
|
||||
self.cfg, self.log)
|
||||
self.cfg.pre_fork(self, worker)
|
||||
pid = os.fork()
|
||||
|
||||
@ -19,11 +19,13 @@ from gunicorn.six import string_types, integer_types, bytes_to_str
|
||||
|
||||
KNOWN_SETTINGS = []
|
||||
|
||||
|
||||
def wrap_method(func):
|
||||
def _wrapped(instance, *args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return _wrapped
|
||||
|
||||
|
||||
def make_settings(ignore=None):
|
||||
settings = {}
|
||||
ignore = ignore or ()
|
||||
@ -34,6 +36,7 @@ def make_settings(ignore=None):
|
||||
settings[setting.name] = setting.copy()
|
||||
return settings
|
||||
|
||||
|
||||
class Config(object):
|
||||
|
||||
def __init__(self, usage=None):
|
||||
@ -63,10 +66,10 @@ class Config(object):
|
||||
parser = optparse.OptionParser(**kwargs)
|
||||
|
||||
keys = list(self.settings)
|
||||
|
||||
def sorter(k):
|
||||
return (self.settings[k].section, self.settings[k].order)
|
||||
|
||||
|
||||
keys = sorted(self.settings, key=self.settings.__getitem__)
|
||||
for k in keys:
|
||||
self.settings[k].add_option(parser)
|
||||
@ -151,6 +154,7 @@ class SettingMeta(type):
|
||||
setattr(cls, "desc", desc)
|
||||
setattr(cls, "short", desc.splitlines()[0])
|
||||
|
||||
|
||||
class Setting(object):
|
||||
name = None
|
||||
value = None
|
||||
@ -201,6 +205,7 @@ class Setting(object):
|
||||
|
||||
Setting = SettingMeta('Setting', (Setting,), {})
|
||||
|
||||
|
||||
def validate_bool(val):
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
@ -213,11 +218,13 @@ def validate_bool(val):
|
||||
else:
|
||||
raise ValueError("Invalid boolean: %s" % val)
|
||||
|
||||
|
||||
def validate_dict(val):
|
||||
if not isinstance(val, dict):
|
||||
raise TypeError("Value is not a dictionary: %s " % val)
|
||||
return val
|
||||
|
||||
|
||||
def validate_pos_int(val):
|
||||
if not isinstance(val, integer_types):
|
||||
val = int(val, 0)
|
||||
@ -228,6 +235,7 @@ def validate_pos_int(val):
|
||||
raise ValueError("Value must be positive: %s" % val)
|
||||
return val
|
||||
|
||||
|
||||
def validate_string(val):
|
||||
if val is None:
|
||||
return None
|
||||
@ -235,6 +243,7 @@ def validate_string(val):
|
||||
raise TypeError("Not a string: %s" % val)
|
||||
return val.strip()
|
||||
|
||||
|
||||
def validate_list_string(val):
|
||||
if not val:
|
||||
return []
|
||||
@ -245,6 +254,7 @@ def validate_list_string(val):
|
||||
|
||||
return [validate_string(v) for v in val]
|
||||
|
||||
|
||||
def validate_string_to_list(val):
|
||||
val = validate_string(val)
|
||||
|
||||
@ -253,6 +263,7 @@ def validate_string_to_list(val):
|
||||
|
||||
return [v.strip() for v in val.split(",") if v]
|
||||
|
||||
|
||||
def validate_class(val):
|
||||
if inspect.isfunction(val) or inspect.ismethod(val):
|
||||
val = val()
|
||||
@ -260,6 +271,7 @@ def validate_class(val):
|
||||
return val
|
||||
return validate_string(val)
|
||||
|
||||
|
||||
def validate_callable(arity):
|
||||
def _validate_callable(val):
|
||||
if isinstance(val, string_types):
|
||||
@ -297,6 +309,7 @@ def validate_user(val):
|
||||
except KeyError:
|
||||
raise ConfigError("No such user: '%s'" % val)
|
||||
|
||||
|
||||
def validate_group(val):
|
||||
if val is None:
|
||||
return os.getegid()
|
||||
@ -311,6 +324,7 @@ def validate_group(val):
|
||||
except KeyError:
|
||||
raise ConfigError("No such group: '%s'" % val)
|
||||
|
||||
|
||||
def validate_post_request(val):
|
||||
val = validate_callable(-1)(val)
|
||||
|
||||
@ -325,7 +339,6 @@ def validate_post_request(val):
|
||||
raise TypeError("Value must have an arity of: 4")
|
||||
|
||||
|
||||
|
||||
class ConfigFile(Setting):
|
||||
name = "config"
|
||||
section = "Config File"
|
||||
@ -340,6 +353,7 @@ class ConfigFile(Setting):
|
||||
application specific configuration.
|
||||
"""
|
||||
|
||||
|
||||
class Bind(Setting):
|
||||
name = "bind"
|
||||
action = "append"
|
||||
@ -367,6 +381,7 @@ class Bind(Setting):
|
||||
and ipv4 interfaces.
|
||||
"""
|
||||
|
||||
|
||||
class Backlog(Setting):
|
||||
name = "backlog"
|
||||
section = "Server Socket"
|
||||
@ -386,6 +401,7 @@ class Backlog(Setting):
|
||||
Must be a positive integer. Generally set in the 64-2048 range.
|
||||
"""
|
||||
|
||||
|
||||
class Workers(Setting):
|
||||
name = "workers"
|
||||
section = "Worker Processes"
|
||||
@ -402,6 +418,7 @@ class Workers(Setting):
|
||||
application's work load.
|
||||
"""
|
||||
|
||||
|
||||
class WorkerClass(Setting):
|
||||
name = "worker_class"
|
||||
section = "Worker Processes"
|
||||
@ -430,6 +447,7 @@ class WorkerClass(Setting):
|
||||
can also load the gevent class with ``egg:gunicorn#gevent``
|
||||
"""
|
||||
|
||||
|
||||
class WorkerConnections(Setting):
|
||||
name = "worker_connections"
|
||||
section = "Worker Processes"
|
||||
@ -444,6 +462,7 @@ class WorkerConnections(Setting):
|
||||
This setting only affects the Eventlet and Gevent worker types.
|
||||
"""
|
||||
|
||||
|
||||
class MaxRequests(Setting):
|
||||
name = "max_requests"
|
||||
section = "Worker Processes"
|
||||
@ -463,6 +482,7 @@ class MaxRequests(Setting):
|
||||
restarts are disabled.
|
||||
"""
|
||||
|
||||
|
||||
class Timeout(Setting):
|
||||
name = "timeout"
|
||||
section = "Worker Processes"
|
||||
@ -480,6 +500,7 @@ class Timeout(Setting):
|
||||
is not tied to the length of time required to handle a single request.
|
||||
"""
|
||||
|
||||
|
||||
class GracefulTimeout(Setting):
|
||||
name = "graceful_timeout"
|
||||
section = "Worker Processes"
|
||||
@ -496,6 +517,7 @@ class GracefulTimeout(Setting):
|
||||
be force killed.
|
||||
"""
|
||||
|
||||
|
||||
class Keepalive(Setting):
|
||||
name = "keepalive"
|
||||
section = "Worker Processes"
|
||||
@ -510,6 +532,7 @@ class Keepalive(Setting):
|
||||
Generally set in the 1-5 seconds range.
|
||||
"""
|
||||
|
||||
|
||||
class LimitRequestLine(Setting):
|
||||
name = "limit_request_line"
|
||||
section = "Security"
|
||||
@ -533,6 +556,7 @@ class LimitRequestLine(Setting):
|
||||
This parameter can be used to prevent any DDOS attack.
|
||||
"""
|
||||
|
||||
|
||||
class LimitRequestFields(Setting):
|
||||
name = "limit_request_fields"
|
||||
section = "Security"
|
||||
@ -541,7 +565,7 @@ class LimitRequestFields(Setting):
|
||||
validator = validate_pos_int
|
||||
type = "int"
|
||||
default = 100
|
||||
desc= """\
|
||||
desc = """\
|
||||
Limit the number of HTTP headers fields in a request.
|
||||
|
||||
This parameter is used to limit the number of headers in a request to
|
||||
@ -550,6 +574,7 @@ class LimitRequestFields(Setting):
|
||||
32768.
|
||||
"""
|
||||
|
||||
|
||||
class LimitRequestFieldSize(Setting):
|
||||
name = "limit_request_field_size"
|
||||
section = "Security"
|
||||
@ -558,13 +583,14 @@ class LimitRequestFieldSize(Setting):
|
||||
validator = validate_pos_int
|
||||
type = "int"
|
||||
default = 8190
|
||||
desc= """\
|
||||
desc = """\
|
||||
Limit the allowed size of an HTTP request header field.
|
||||
|
||||
Value is a number from 0 (unlimited) to 8190. to set the limit
|
||||
on the allowed size of an HTTP request header field.
|
||||
"""
|
||||
|
||||
|
||||
class Debug(Setting):
|
||||
name = "debug"
|
||||
section = "Debugging"
|
||||
@ -579,6 +605,7 @@ class Debug(Setting):
|
||||
handling that's sent to clients.
|
||||
"""
|
||||
|
||||
|
||||
class Spew(Setting):
|
||||
name = "spew"
|
||||
section = "Debugging"
|
||||
@ -592,10 +619,11 @@ class Spew(Setting):
|
||||
This is the nuclear option.
|
||||
"""
|
||||
|
||||
|
||||
class ConfigCheck(Setting):
|
||||
name = "check_config"
|
||||
section = "Debugging"
|
||||
cli = ["--check-config",]
|
||||
cli = ["--check-config", ]
|
||||
validator = validate_bool
|
||||
action = "store_true"
|
||||
default = False
|
||||
@ -603,6 +631,7 @@ class ConfigCheck(Setting):
|
||||
Check the configuration..
|
||||
"""
|
||||
|
||||
|
||||
class PreloadApp(Setting):
|
||||
name = "preload_app"
|
||||
section = "Server Mechanics"
|
||||
@ -619,6 +648,7 @@ class PreloadApp(Setting):
|
||||
restarting workers.
|
||||
"""
|
||||
|
||||
|
||||
class Daemon(Setting):
|
||||
name = "daemon"
|
||||
section = "Server Mechanics"
|
||||
@ -633,6 +663,7 @@ class Daemon(Setting):
|
||||
background.
|
||||
"""
|
||||
|
||||
|
||||
class Pidfile(Setting):
|
||||
name = "pidfile"
|
||||
section = "Server Mechanics"
|
||||
@ -646,6 +677,7 @@ class Pidfile(Setting):
|
||||
If not set, no PID file will be written.
|
||||
"""
|
||||
|
||||
|
||||
class User(Setting):
|
||||
name = "user"
|
||||
section = "Server Mechanics"
|
||||
@ -661,6 +693,7 @@ class User(Setting):
|
||||
the worker process user.
|
||||
"""
|
||||
|
||||
|
||||
class Group(Setting):
|
||||
name = "group"
|
||||
section = "Server Mechanics"
|
||||
@ -676,6 +709,7 @@ class Group(Setting):
|
||||
the worker processes group.
|
||||
"""
|
||||
|
||||
|
||||
class Umask(Setting):
|
||||
name = "umask"
|
||||
section = "Server Mechanics"
|
||||
@ -694,6 +728,7 @@ class Umask(Setting):
|
||||
"0xFF", "0022" are valid for decimal, hex, and octal representations)
|
||||
"""
|
||||
|
||||
|
||||
class TmpUploadDir(Setting):
|
||||
name = "tmp_upload_dir"
|
||||
section = "Server Mechanics"
|
||||
@ -710,6 +745,7 @@ class TmpUploadDir(Setting):
|
||||
temporary directory.
|
||||
"""
|
||||
|
||||
|
||||
class SecureSchemeHeader(Setting):
|
||||
name = "secure_scheme_headers"
|
||||
section = "Server Mechanics"
|
||||
@ -734,6 +770,8 @@ class SecureSchemeHeader(Setting):
|
||||
It is important that your front-end proxy configuration ensures that
|
||||
the headers defined here can not be passed directly from the client.
|
||||
"""
|
||||
|
||||
|
||||
class XForwardedFor(Setting):
|
||||
name = "x_forwarded_for_header"
|
||||
section = "Server Mechanics"
|
||||
@ -745,6 +783,7 @@ class XForwardedFor(Setting):
|
||||
address of the client connection to gunicorn via a proxy.
|
||||
"""
|
||||
|
||||
|
||||
class ForwardedAllowIPS(Setting):
|
||||
name = "forwarded_allow_ips"
|
||||
section = "Server Mechanics"
|
||||
@ -760,6 +799,7 @@ class ForwardedAllowIPS(Setting):
|
||||
you still trust the environment)
|
||||
"""
|
||||
|
||||
|
||||
class AccessLog(Setting):
|
||||
name = "accesslog"
|
||||
section = "Logging"
|
||||
@ -773,6 +813,7 @@ class AccessLog(Setting):
|
||||
"-" means log to stderr.
|
||||
"""
|
||||
|
||||
|
||||
class AccessLogFormat(Setting):
|
||||
name = "access_log_format"
|
||||
section = "Logging"
|
||||
@ -804,6 +845,7 @@ class AccessLogFormat(Setting):
|
||||
{Header}o: response header
|
||||
"""
|
||||
|
||||
|
||||
class ErrorLog(Setting):
|
||||
name = "errorlog"
|
||||
section = "Logging"
|
||||
@ -817,6 +859,7 @@ class ErrorLog(Setting):
|
||||
"-" means log to stderr.
|
||||
"""
|
||||
|
||||
|
||||
class Loglevel(Setting):
|
||||
name = "loglevel"
|
||||
section = "Logging"
|
||||
@ -836,6 +879,7 @@ class Loglevel(Setting):
|
||||
* critical
|
||||
"""
|
||||
|
||||
|
||||
class LoggerClass(Setting):
|
||||
name = "logger_class"
|
||||
section = "Logging"
|
||||
@ -869,6 +913,7 @@ Gunicorn uses the standard Python logging module's Configuration
|
||||
file format.
|
||||
"""
|
||||
|
||||
|
||||
class Procname(Setting):
|
||||
name = "proc_name"
|
||||
section = "Process Naming"
|
||||
@ -887,6 +932,7 @@ class Procname(Setting):
|
||||
It defaults to 'gunicorn'.
|
||||
"""
|
||||
|
||||
|
||||
class DefaultProcName(Setting):
|
||||
name = "default_proc_name"
|
||||
section = "Process Naming"
|
||||
@ -911,6 +957,7 @@ class DjangoSettings(Setting):
|
||||
DJANGO_SETTINGS_MODULE environment variable will be used.
|
||||
"""
|
||||
|
||||
|
||||
class PythonPath(Setting):
|
||||
name = "pythonpath"
|
||||
section = "Server Mechanics"
|
||||
@ -925,11 +972,13 @@ class PythonPath(Setting):
|
||||
'/home/djangoprojects/myproject'.
|
||||
"""
|
||||
|
||||
|
||||
class OnStarting(Setting):
|
||||
name = "on_starting"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(1)
|
||||
type = "callable"
|
||||
|
||||
def on_starting(server):
|
||||
pass
|
||||
default = staticmethod(on_starting)
|
||||
@ -939,11 +988,13 @@ class OnStarting(Setting):
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
|
||||
class OnReload(Setting):
|
||||
name = "on_reload"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(1)
|
||||
type = "callable"
|
||||
|
||||
def on_reload(server):
|
||||
pass
|
||||
default = staticmethod(on_reload)
|
||||
@ -953,11 +1004,13 @@ class OnReload(Setting):
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
|
||||
class WhenReady(Setting):
|
||||
name = "when_ready"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(1)
|
||||
type = "callable"
|
||||
|
||||
def when_ready(server):
|
||||
pass
|
||||
default = staticmethod(when_ready)
|
||||
@ -967,11 +1020,13 @@ class WhenReady(Setting):
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
|
||||
class Prefork(Setting):
|
||||
name = "pre_fork"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(2)
|
||||
type = "callable"
|
||||
|
||||
def pre_fork(server, worker):
|
||||
pass
|
||||
default = staticmethod(pre_fork)
|
||||
@ -982,11 +1037,13 @@ class Prefork(Setting):
|
||||
new Worker.
|
||||
"""
|
||||
|
||||
|
||||
class Postfork(Setting):
|
||||
name = "post_fork"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(2)
|
||||
type = "callable"
|
||||
|
||||
def post_fork(server, worker):
|
||||
pass
|
||||
default = staticmethod(post_fork)
|
||||
@ -997,11 +1054,13 @@ class Postfork(Setting):
|
||||
new Worker.
|
||||
"""
|
||||
|
||||
|
||||
class PreExec(Setting):
|
||||
name = "pre_exec"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(1)
|
||||
type = "callable"
|
||||
|
||||
def pre_exec(server):
|
||||
pass
|
||||
default = staticmethod(pre_exec)
|
||||
@ -1011,11 +1070,13 @@ class PreExec(Setting):
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
|
||||
class PreRequest(Setting):
|
||||
name = "pre_request"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(2)
|
||||
type = "callable"
|
||||
|
||||
def pre_request(worker, req):
|
||||
worker.log.debug("%s %s" % (req.method, req.path))
|
||||
default = staticmethod(pre_request)
|
||||
@ -1026,11 +1087,13 @@ class PreRequest(Setting):
|
||||
the Request.
|
||||
"""
|
||||
|
||||
|
||||
class PostRequest(Setting):
|
||||
name = "post_request"
|
||||
section = "Server Hooks"
|
||||
validator = validate_post_request
|
||||
type = "callable"
|
||||
|
||||
def post_request(worker, req, environ, resp):
|
||||
pass
|
||||
default = staticmethod(post_request)
|
||||
@ -1041,11 +1104,13 @@ class PostRequest(Setting):
|
||||
the Request.
|
||||
"""
|
||||
|
||||
|
||||
class WorkerExit(Setting):
|
||||
name = "worker_exit"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(2)
|
||||
type = "callable"
|
||||
|
||||
def worker_exit(server, worker):
|
||||
pass
|
||||
default = staticmethod(worker_exit)
|
||||
@ -1056,11 +1121,13 @@ class WorkerExit(Setting):
|
||||
the just-exited Worker.
|
||||
"""
|
||||
|
||||
|
||||
class NumWorkersChanged(Setting):
|
||||
name = "nworkers_changed"
|
||||
section = "Server Hooks"
|
||||
validator = validate_callable(3)
|
||||
type = "callable"
|
||||
|
||||
def nworkers_changed(server, new_value, old_value):
|
||||
pass
|
||||
default = staticmethod(nworkers_changed)
|
||||
@ -1074,6 +1141,7 @@ class NumWorkersChanged(Setting):
|
||||
None.
|
||||
"""
|
||||
|
||||
|
||||
class ProxyProtocol(Setting):
|
||||
name = "proxy_protocol"
|
||||
section = "Server Mechanics"
|
||||
@ -1099,6 +1167,7 @@ class ProxyProtocol(Setting):
|
||||
key = /etc/ssl/certs/stunnel.key
|
||||
"""
|
||||
|
||||
|
||||
class ProxyAllowFrom(Setting):
|
||||
name = "proxy_allow_ips"
|
||||
section = "Server Mechanics"
|
||||
@ -1109,6 +1178,7 @@ class ProxyAllowFrom(Setting):
|
||||
Front-end's IPs from which allowed accept proxy requests (comma separate).
|
||||
"""
|
||||
|
||||
|
||||
class KeyFile(Setting):
|
||||
name = "keyfile"
|
||||
section = "Ssl"
|
||||
@ -1120,6 +1190,7 @@ class KeyFile(Setting):
|
||||
SSL key file
|
||||
"""
|
||||
|
||||
|
||||
class CertFile(Setting):
|
||||
name = "certfile"
|
||||
section = "Ssl"
|
||||
|
||||
@ -16,7 +16,6 @@ __all__ = ['spew', 'unspew']
|
||||
_token_spliter = re.compile('\W+')
|
||||
|
||||
|
||||
|
||||
class Spew(object):
|
||||
"""
|
||||
"""
|
||||
@ -69,5 +68,3 @@ def unspew():
|
||||
"""Remove the trace hook installed by spew.
|
||||
"""
|
||||
sys.settrace(None)
|
||||
|
||||
|
||||
|
||||
@ -12,5 +12,6 @@ class HaltServer(BaseException):
|
||||
def __str__(self):
|
||||
return "<HaltServer %r %d>" % (self.reason, self.exit_status)
|
||||
|
||||
|
||||
class ConfigError(BaseException):
|
||||
""" Exception raised on config error """
|
||||
|
||||
@ -17,11 +17,11 @@ from gunicorn import util
|
||||
from gunicorn.six import string_types
|
||||
|
||||
CONFIG_DEFAULTS = dict(
|
||||
version = 1,
|
||||
disable_existing_loggers = False,
|
||||
version=1,
|
||||
disable_existing_loggers=False,
|
||||
|
||||
loggers = {
|
||||
"root": { "level": "INFO", "handlers": ["console"] },
|
||||
loggers={
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
"gunicorn.error": {
|
||||
"level": "INFO",
|
||||
"handlers": ["console"],
|
||||
@ -29,14 +29,14 @@ CONFIG_DEFAULTS = dict(
|
||||
"qualname": "gunicorn.error"
|
||||
}
|
||||
},
|
||||
handlers = {
|
||||
handlers={
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "generic",
|
||||
"stream": "sys.stdout"
|
||||
}
|
||||
},
|
||||
formatters = {
|
||||
formatters={
|
||||
"generic": {
|
||||
"format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
|
||||
"datefmt": "%Y-%m-%d %H:%M:%S",
|
||||
@ -45,12 +45,14 @@ CONFIG_DEFAULTS = dict(
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def loggers():
|
||||
""" get list of all loggers """
|
||||
root = logging.root
|
||||
existing = root.manager.loggerDict.keys()
|
||||
return [logging.getLogger(name) for name in existing]
|
||||
|
||||
|
||||
class LazyWriter(object):
|
||||
|
||||
"""
|
||||
@ -100,6 +102,7 @@ class LazyWriter(object):
|
||||
def isatty(self):
|
||||
return bool(self.fileobj and self.fileobj.isatty())
|
||||
|
||||
|
||||
class SafeAtoms(dict):
|
||||
|
||||
def __init__(self, atoms):
|
||||
@ -149,7 +152,6 @@ class Logger(object):
|
||||
self.error_log.setLevel(loglevel)
|
||||
self.access_log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
if cfg.errorlog != "-":
|
||||
# if an error log file is set redirect stdout & stderr to
|
||||
# this log file.
|
||||
@ -170,7 +172,6 @@ class Logger(object):
|
||||
else:
|
||||
raise RuntimeError("Error: log config '%s' not found" % cfg.logconfig)
|
||||
|
||||
|
||||
def critical(self, msg, *args, **kwargs):
|
||||
self.error_log.critical(msg, *args, **kwargs)
|
||||
|
||||
@ -206,7 +207,7 @@ class Logger(object):
|
||||
atoms = {
|
||||
'h': environ.get('REMOTE_ADDR', '-'),
|
||||
'l': '-',
|
||||
'u': '-', # would be cool to get username from basic auth header
|
||||
'u': '-', # would be cool to get username from basic auth header
|
||||
't': self.now(),
|
||||
'r': "%s %s %s" % (environ['REQUEST_METHOD'],
|
||||
environ['RAW_URI'], environ["SERVER_PROTOCOL"]),
|
||||
@ -225,10 +226,10 @@ class Logger(object):
|
||||
else:
|
||||
req_headers = req
|
||||
|
||||
atoms.update(dict([("{%s}i" % k.lower(),v) for k, v in req_headers]))
|
||||
atoms.update(dict([("{%s}i" % k.lower(), v) for k, v in req_headers]))
|
||||
|
||||
# add response headers
|
||||
atoms.update(dict([("{%s}o" % k.lower(),v) for k, v in resp.headers]))
|
||||
atoms.update(dict([("{%s}o" % k.lower(), v) for k, v in resp.headers]))
|
||||
|
||||
# wrap atoms:
|
||||
# - make sure atoms will be test case insensitively
|
||||
@ -247,7 +248,6 @@ class Logger(object):
|
||||
return '[%02d/%s/%04d:%02d:%02d:%02d]' % (now.day, month,
|
||||
now.year, now.hour, now.minute, now.second)
|
||||
|
||||
|
||||
def reopen_files(self):
|
||||
if self.cfg.errorlog != "-":
|
||||
# Close stderr & stdout if they are redirected to error log file
|
||||
@ -276,7 +276,6 @@ class Logger(object):
|
||||
finally:
|
||||
handler.release()
|
||||
|
||||
|
||||
def _get_gunicorn_handler(self, log):
|
||||
for h in log.handlers:
|
||||
if getattr(h, "_gunicorn", False) == True:
|
||||
@ -297,4 +296,3 @@ class Logger(object):
|
||||
h.setFormatter(fmt)
|
||||
h._gunicorn = True
|
||||
log.addHandler(h)
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# -*- 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.
|
||||
|
||||
from gunicorn.http.message import Message, Request
|
||||
from gunicorn.http.parser import RequestParser
|
||||
|
||||
__all__ = [Message, Request, RequestParser]
|
||||
__all__ = [Message, Request, RequestParser]
|
||||
|
||||
@ -28,6 +28,7 @@ if sys.version_info < (2, 6) or \
|
||||
_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
|
||||
_sendfile = _libc.sendfile
|
||||
|
||||
|
||||
def sendfile(fdout, fdin, offset, nbytes):
|
||||
if sys.platform == 'darwin':
|
||||
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_uint64,
|
||||
|
||||
@ -3,12 +3,11 @@
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import sys
|
||||
|
||||
from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
|
||||
InvalidChunkSize)
|
||||
from gunicorn import six
|
||||
|
||||
|
||||
class ChunkedReader(object):
|
||||
def __init__(self, req, unreader):
|
||||
self.req = req
|
||||
@ -51,7 +50,7 @@ class ChunkedReader(object):
|
||||
unreader.unread(buf.getvalue()[2:])
|
||||
return b""
|
||||
self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx])
|
||||
unreader.unread(buf.getvalue()[idx+4:])
|
||||
unreader.unread(buf.getvalue()[idx + 4:])
|
||||
|
||||
def parse_chunked(self, unreader):
|
||||
(size, rest) = self.parse_chunk_size(unreader)
|
||||
@ -82,7 +81,7 @@ class ChunkedReader(object):
|
||||
idx = buf.getvalue().find(b"\r\n")
|
||||
|
||||
data = buf.getvalue()
|
||||
line, rest_chunk = data[:idx], data[idx+2:]
|
||||
line, rest_chunk = data[:idx], data[idx + 2:]
|
||||
|
||||
chunk_size = line.split(b";", 1)[0].strip()
|
||||
try:
|
||||
@ -104,6 +103,7 @@ class ChunkedReader(object):
|
||||
raise NoMoreData()
|
||||
buf.write(data)
|
||||
|
||||
|
||||
class LengthReader(object):
|
||||
def __init__(self, unreader, length):
|
||||
self.unreader = unreader
|
||||
@ -119,7 +119,6 @@ class LengthReader(object):
|
||||
if size == 0:
|
||||
return b""
|
||||
|
||||
|
||||
buf = six.BytesIO()
|
||||
data = self.unreader.read()
|
||||
while data:
|
||||
@ -134,6 +133,7 @@ class LengthReader(object):
|
||||
self.length -= size
|
||||
return ret
|
||||
|
||||
|
||||
class EOFReader(object):
|
||||
def __init__(self, unreader):
|
||||
self.unreader = unreader
|
||||
@ -171,6 +171,7 @@ class EOFReader(object):
|
||||
self.buf.write(rest)
|
||||
return ret
|
||||
|
||||
|
||||
class Body(object):
|
||||
def __init__(self, reader):
|
||||
self.reader = reader
|
||||
@ -233,8 +234,8 @@ class Body(object):
|
||||
|
||||
idx = line.find(b"\n")
|
||||
if idx >= 0:
|
||||
ret = line[:idx+1]
|
||||
self.buf.write(line[idx+1:])
|
||||
ret = line[:idx + 1]
|
||||
self.buf.write(line[idx + 1:])
|
||||
self.buf.write(extra_buf_data)
|
||||
return ret
|
||||
self.buf.write(extra_buf_data)
|
||||
@ -249,6 +250,6 @@ class Body(object):
|
||||
ret.append(data)
|
||||
data = b""
|
||||
else:
|
||||
line, data = data[:pos+1], data[pos+1:]
|
||||
line, data = data[:pos + 1], data[pos + 1:]
|
||||
ret.append(line)
|
||||
return ret
|
||||
|
||||
@ -3,9 +3,11 @@
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
|
||||
class ParseException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NoMoreData(IOError):
|
||||
def __init__(self, buf=None):
|
||||
self.buf = buf
|
||||
@ -13,6 +15,7 @@ class NoMoreData(IOError):
|
||||
def __str__(self):
|
||||
return "No more data after: %r" % self.buf
|
||||
|
||||
|
||||
class InvalidRequestLine(ParseException):
|
||||
def __init__(self, req):
|
||||
self.req = req
|
||||
@ -21,6 +24,7 @@ class InvalidRequestLine(ParseException):
|
||||
def __str__(self):
|
||||
return "Invalid HTTP request line: %r" % self.req
|
||||
|
||||
|
||||
class InvalidRequestMethod(ParseException):
|
||||
def __init__(self, method):
|
||||
self.method = method
|
||||
@ -28,6 +32,7 @@ class InvalidRequestMethod(ParseException):
|
||||
def __str__(self):
|
||||
return "Invalid HTTP method: %r" % self.method
|
||||
|
||||
|
||||
class InvalidHTTPVersion(ParseException):
|
||||
def __init__(self, version):
|
||||
self.version = version
|
||||
@ -35,6 +40,7 @@ class InvalidHTTPVersion(ParseException):
|
||||
def __str__(self):
|
||||
return "Invalid HTTP Version: %s" % self.version
|
||||
|
||||
|
||||
class InvalidHeader(ParseException):
|
||||
def __init__(self, hdr, req=None):
|
||||
self.hdr = hdr
|
||||
@ -43,6 +49,7 @@ class InvalidHeader(ParseException):
|
||||
def __str__(self):
|
||||
return "Invalid HTTP Header: %s" % self.hdr
|
||||
|
||||
|
||||
class InvalidHeaderName(ParseException):
|
||||
def __init__(self, hdr):
|
||||
self.hdr = hdr
|
||||
@ -50,6 +57,7 @@ class InvalidHeaderName(ParseException):
|
||||
def __str__(self):
|
||||
return "Invalid HTTP header name: %s" % self.hdr
|
||||
|
||||
|
||||
class InvalidChunkSize(IOError):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
@ -57,6 +65,7 @@ class InvalidChunkSize(IOError):
|
||||
def __str__(self):
|
||||
return "Invalid chunk size: %r" % self.data
|
||||
|
||||
|
||||
class ChunkMissingTerminator(IOError):
|
||||
def __init__(self, term):
|
||||
self.term = term
|
||||
@ -73,6 +82,7 @@ class LimitRequestLine(ParseException):
|
||||
def __str__(self):
|
||||
return "Request Line is too large (%s > %s)" % (self.size, self.max_size)
|
||||
|
||||
|
||||
class LimitRequestHeaders(ParseException):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
@ -19,6 +19,7 @@ MAX_REQUEST_LINE = 8190
|
||||
MAX_HEADERS = 32768
|
||||
MAX_HEADERFIELD_SIZE = 8190
|
||||
|
||||
|
||||
class Message(object):
|
||||
def __init__(self, cfg, unreader):
|
||||
self.cfg = cfg
|
||||
@ -150,7 +151,6 @@ class Request(Message):
|
||||
self.proxy_protocol_info = None
|
||||
super(Request, self).__init__(cfg, unreader)
|
||||
|
||||
|
||||
def get_data(self, unreader, buf, stop=False):
|
||||
data = unreader.read()
|
||||
if not data:
|
||||
@ -200,7 +200,7 @@ class Request(Message):
|
||||
|
||||
self.headers = self.parse_headers(data[:idx])
|
||||
|
||||
ret = data[idx+4:]
|
||||
ret = data[idx + 4:]
|
||||
buf = BytesIO()
|
||||
return ret
|
||||
|
||||
@ -220,8 +220,8 @@ class Request(Message):
|
||||
if len(data) - 2 > limit > 0:
|
||||
raise LimitRequestLine(len(data), limit)
|
||||
|
||||
return (data[:idx], # request line,
|
||||
data[idx + 2:]) # residue in the buffer, skip \r\n
|
||||
return (data[:idx], # request line,
|
||||
data[idx + 2:]) # residue in the buffer, skip \r\n
|
||||
|
||||
def proxy_protocol(self, line):
|
||||
"""\
|
||||
@ -337,5 +337,3 @@ class Request(Message):
|
||||
super(Request, self).set_body_reader()
|
||||
if isinstance(self.body.reader, EOFReader):
|
||||
self.body = Body(LengthReader(self.unreader, 0))
|
||||
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
from gunicorn.http.message import Request
|
||||
from gunicorn.http.unreader import SocketUnreader, IterUnreader
|
||||
|
||||
|
||||
class Parser(object):
|
||||
def __init__(self, mesg_class, cfg, source):
|
||||
self.mesg_class = mesg_class
|
||||
@ -33,7 +34,6 @@ class Parser(object):
|
||||
while data:
|
||||
data = self.mesg.body.read(8192)
|
||||
|
||||
|
||||
# Parse the next request
|
||||
self.req_count += 1
|
||||
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
|
||||
@ -43,7 +43,7 @@ class Parser(object):
|
||||
|
||||
next = __next__
|
||||
|
||||
|
||||
class RequestParser(Parser):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RequestParser, self).__init__(Request, *args, **kwargs)
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ from gunicorn import six
|
||||
# Classes that can undo reading data from
|
||||
# a given type of data source.
|
||||
|
||||
|
||||
class Unreader(object):
|
||||
def __init__(self):
|
||||
self.buf = six.BytesIO()
|
||||
@ -34,7 +35,7 @@ class Unreader(object):
|
||||
self.buf = six.BytesIO()
|
||||
return ret
|
||||
if size is None:
|
||||
d = self.chunk()
|
||||
d = self.chunk()
|
||||
return d
|
||||
|
||||
while self.buf.tell() < size:
|
||||
@ -53,6 +54,7 @@ class Unreader(object):
|
||||
self.buf.seek(0, os.SEEK_END)
|
||||
self.buf.write(data)
|
||||
|
||||
|
||||
class SocketUnreader(Unreader):
|
||||
def __init__(self, sock, max_chunk=8192):
|
||||
super(SocketUnreader, self).__init__()
|
||||
@ -62,6 +64,7 @@ class SocketUnreader(Unreader):
|
||||
def chunk(self):
|
||||
return self.sock.recv(self.mxchunk)
|
||||
|
||||
|
||||
class IterUnreader(Unreader):
|
||||
def __init__(self, iterable):
|
||||
super(IterUnreader, self).__init__()
|
||||
|
||||
@ -26,6 +26,7 @@ NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+')
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FileWrapper:
|
||||
|
||||
def __init__(self, filelike, blksize=8192):
|
||||
@ -58,6 +59,7 @@ def default_environ(req, sock, cfg):
|
||||
"SERVER_PROTOCOL": "HTTP/%s" % ".".join([str(v) for v in req.version])
|
||||
}
|
||||
|
||||
|
||||
def proxy_environ(req):
|
||||
info = req.proxy_protocol_info
|
||||
|
||||
@ -72,6 +74,7 @@ def proxy_environ(req):
|
||||
"PROXY_PORT": str(info["proxy_port"]),
|
||||
}
|
||||
|
||||
|
||||
def create(req, sock, client, server, cfg):
|
||||
resp = Response(req, sock)
|
||||
|
||||
@ -127,7 +130,7 @@ def create(req, sock, client, server, cfg):
|
||||
|
||||
# find host and port on ipv6 address
|
||||
if '[' in forward and ']' in forward:
|
||||
host = forward.split(']')[0][1:].lower()
|
||||
host = forward.split(']')[0][1:].lower()
|
||||
elif ":" in forward and forward.count(":") == 1:
|
||||
host = forward.split(":")[0].lower()
|
||||
else:
|
||||
@ -147,7 +150,7 @@ def create(req, sock, client, server, cfg):
|
||||
environ['REMOTE_PORT'] = str(remote[1])
|
||||
|
||||
if isinstance(server, string_types):
|
||||
server = server.split(":")
|
||||
server = server.split(":")
|
||||
if len(server) == 1:
|
||||
if url_scheme == "http":
|
||||
server.append("80")
|
||||
@ -168,6 +171,7 @@ def create(req, sock, client, server, cfg):
|
||||
|
||||
return resp, environ
|
||||
|
||||
|
||||
class Response(object):
|
||||
|
||||
def __init__(self, req, sock):
|
||||
@ -229,14 +233,13 @@ class Response(object):
|
||||
continue
|
||||
self.headers.append((name.strip(), value))
|
||||
|
||||
|
||||
def is_chunked(self):
|
||||
# Only use chunked responses when the client is
|
||||
# speaking HTTP/1.1 or newer and there was
|
||||
# no Content-Length header set.
|
||||
if self.response_length is not None:
|
||||
return False
|
||||
elif self.req.version <= (1,0):
|
||||
elif self.req.version <= (1, 0):
|
||||
return False
|
||||
elif self.status.startswith("304") or self.status.startswith("204"):
|
||||
# Do not use chunked responses when the response is guaranteed to
|
||||
@ -268,7 +271,7 @@ class Response(object):
|
||||
if self.headers_sent:
|
||||
return
|
||||
tosend = self.default_headers()
|
||||
tosend.extend(["%s: %s\r\n" % (k,v) for k, v in self.headers])
|
||||
tosend.extend(["%s: %s\r\n" % (k, v) for k, v in self.headers])
|
||||
|
||||
header_str = "%s\r\n" % "".join(tosend)
|
||||
util.write(self.sock, util.to_bytestring(header_str))
|
||||
@ -315,9 +318,9 @@ class Response(object):
|
||||
nbytes -= BLKSIZE
|
||||
else:
|
||||
sent = 0
|
||||
sent += sendfile(sockno, fileno, offset+sent, nbytes-sent)
|
||||
sent += sendfile(sockno, fileno, offset + sent, nbytes - sent)
|
||||
while sent != nbytes:
|
||||
sent += sendfile(sockno, fileno, offset+sent, nbytes-sent)
|
||||
sent += sendfile(sockno, fileno, offset + sent, nbytes - sent)
|
||||
|
||||
def write_file(self, respiter):
|
||||
if sendfile is not None and \
|
||||
|
||||
@ -45,6 +45,7 @@ def make_options():
|
||||
g_settings = make_settings(ignore=("version"))
|
||||
|
||||
keys = g_settings.keys()
|
||||
|
||||
def sorter(k):
|
||||
return (g_settings[k].section, g_settings[k].order)
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ class Pidfile(object):
|
||||
""" delete pidfile"""
|
||||
try:
|
||||
with open(self.fname, "r") as f:
|
||||
pid1 = int(f.read() or 0)
|
||||
pid1 = int(f.read() or 0)
|
||||
|
||||
if pid1 == self.pid:
|
||||
os.unlink(self.fname)
|
||||
|
||||
@ -12,6 +12,7 @@ import time
|
||||
from gunicorn import util
|
||||
from gunicorn.six import string_types
|
||||
|
||||
|
||||
class BaseSocket(object):
|
||||
|
||||
def __init__(self, address, conf, log, fd=None):
|
||||
@ -50,6 +51,7 @@ class BaseSocket(object):
|
||||
time.sleep(0.3)
|
||||
del self.sock
|
||||
|
||||
|
||||
class TCPSocket(BaseSocket):
|
||||
|
||||
FAMILY = socket.AF_INET
|
||||
@ -60,13 +62,14 @@ class TCPSocket(BaseSocket):
|
||||
else:
|
||||
scheme = "http"
|
||||
|
||||
addr = self.sock.getsockname()
|
||||
addr = self.sock.getsockname()
|
||||
return "%s://%s:%d" % (scheme, addr[0], addr[1])
|
||||
|
||||
def set_options(self, sock, bound=False):
|
||||
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
return super(TCPSocket, self).set_options(sock, bound=bound)
|
||||
|
||||
|
||||
class TCP6Socket(TCPSocket):
|
||||
|
||||
FAMILY = socket.AF_INET6
|
||||
@ -75,6 +78,7 @@ class TCP6Socket(TCPSocket):
|
||||
(host, port, fl, sc) = self.sock.getsockname()
|
||||
return "http://[%s]:%d" % (host, port)
|
||||
|
||||
|
||||
class UnixSocket(BaseSocket):
|
||||
|
||||
FAMILY = socket.AF_UNIX
|
||||
@ -100,6 +104,7 @@ class UnixSocket(BaseSocket):
|
||||
super(UnixSocket, self).close()
|
||||
os.unlink(self.cfg_addr)
|
||||
|
||||
|
||||
def _sock_type(addr):
|
||||
if isinstance(addr, tuple):
|
||||
if util.is_ipv6(addr[0]):
|
||||
@ -112,6 +117,7 @@ def _sock_type(addr):
|
||||
raise TypeError("Unable to create socket from: %r" % addr)
|
||||
return sock_type
|
||||
|
||||
|
||||
def create_sockets(conf, log):
|
||||
"""
|
||||
Create a new socket for the given address. If the
|
||||
@ -158,7 +164,7 @@ def create_sockets(conf, log):
|
||||
sock = None
|
||||
for i in range(5):
|
||||
try:
|
||||
sock = sock_type(addr, conf, log)
|
||||
sock = sock_type(addr, conf, log)
|
||||
except socket.error as e:
|
||||
if e.args[0] == errno.EADDRINUSE:
|
||||
log.error("Connection in use: %s", str(addr))
|
||||
|
||||
@ -24,14 +24,16 @@ import sys
|
||||
import textwrap
|
||||
import time
|
||||
import inspect
|
||||
import errno
|
||||
import warnings
|
||||
|
||||
from gunicorn.six import text_type, string_types
|
||||
|
||||
MAXFD = 1024
|
||||
if (hasattr(os, "devnull")):
|
||||
REDIRECT_TO = os.devnull
|
||||
REDIRECT_TO = os.devnull
|
||||
else:
|
||||
REDIRECT_TO = "/dev/null"
|
||||
REDIRECT_TO = "/dev/null"
|
||||
|
||||
timeout_default = object()
|
||||
|
||||
@ -83,7 +85,6 @@ except ImportError:
|
||||
"package")
|
||||
return "%s.%s" % (package[:dot], name)
|
||||
|
||||
|
||||
def import_module(name, package=None):
|
||||
"""Import a module.
|
||||
|
||||
@ -104,6 +105,7 @@ relative import to an absolute import.
|
||||
__import__(name)
|
||||
return sys.modules[name]
|
||||
|
||||
|
||||
def load_class(uri, default="sync", section="gunicorn.workers"):
|
||||
if inspect.isclass(uri):
|
||||
return uri
|
||||
@ -111,7 +113,7 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
|
||||
# uses entry points
|
||||
entry_str = uri.split("egg:")[1]
|
||||
try:
|
||||
dist, name = entry_str.rsplit("#",1)
|
||||
dist, name = entry_str.rsplit("#", 1)
|
||||
except ValueError:
|
||||
dist = entry_str
|
||||
name = default
|
||||
@ -135,7 +137,8 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
|
||||
mod = getattr(mod, comp)
|
||||
return getattr(mod, klass)
|
||||
|
||||
def set_owner_process(uid,gid):
|
||||
|
||||
def set_owner_process(uid, gid):
|
||||
""" set user and group of workers processes """
|
||||
if gid:
|
||||
try:
|
||||
@ -150,6 +153,7 @@ def set_owner_process(uid,gid):
|
||||
if uid:
|
||||
os.setuid(uid)
|
||||
|
||||
|
||||
def chown(path, uid, gid):
|
||||
try:
|
||||
os.chown(path, uid, gid)
|
||||
@ -198,6 +202,7 @@ if sys.platform.startswith("win"):
|
||||
else:
|
||||
_unlink = os.unlink
|
||||
|
||||
|
||||
def unlink(filename):
|
||||
try:
|
||||
_unlink(filename)
|
||||
@ -210,10 +215,11 @@ def unlink(filename):
|
||||
def is_ipv6(addr):
|
||||
try:
|
||||
socket.inet_pton(socket.AF_INET6, addr)
|
||||
except socket.error: # not a valid address
|
||||
except socket.error: # not a valid address
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def parse_address(netloc, default_port=8000):
|
||||
if netloc.startswith("unix:"):
|
||||
return netloc.split("unix:")[1]
|
||||
@ -239,21 +245,25 @@ def parse_address(netloc, default_port=8000):
|
||||
port = default_port
|
||||
return (host, port)
|
||||
|
||||
|
||||
def get_maxfd():
|
||||
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
||||
if (maxfd == resource.RLIM_INFINITY):
|
||||
maxfd = MAXFD
|
||||
return maxfd
|
||||
|
||||
|
||||
def close_on_exec(fd):
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
flags |= fcntl.FD_CLOEXEC
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags)
|
||||
|
||||
|
||||
def set_non_blocking(fd):
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
|
||||
|
||||
|
||||
def close(sock):
|
||||
try:
|
||||
sock.close()
|
||||
@ -268,9 +278,10 @@ except ImportError:
|
||||
for fd in range(fd_low, fd_high):
|
||||
try:
|
||||
os.close(fd)
|
||||
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||
pass
|
||||
|
||||
|
||||
def write_chunk(sock, data):
|
||||
if isinstance(data, text_type):
|
||||
data = data.encode('utf-8')
|
||||
@ -278,11 +289,13 @@ def write_chunk(sock, data):
|
||||
chunk = b"".join([chunk_size.encode('utf-8'), data, b"\r\n"])
|
||||
sock.sendall(chunk)
|
||||
|
||||
|
||||
def write(sock, data, chunked=False):
|
||||
if chunked:
|
||||
return write_chunk(sock, data)
|
||||
sock.sendall(data)
|
||||
|
||||
|
||||
def write_nonblock(sock, data, chunked=False):
|
||||
timeout = sock.gettimeout()
|
||||
if timeout != 0.0:
|
||||
@ -294,10 +307,12 @@ def write_nonblock(sock, data, chunked=False):
|
||||
else:
|
||||
return write(sock, data, chunked)
|
||||
|
||||
|
||||
def writelines(sock, lines, chunked=False):
|
||||
for line in list(lines):
|
||||
write(sock, line, chunked)
|
||||
|
||||
|
||||
def write_error(sock, status_int, reason, mesg):
|
||||
html = textwrap.dedent("""\
|
||||
<html>
|
||||
@ -321,8 +336,10 @@ def write_error(sock, status_int, reason, mesg):
|
||||
""") % (str(status_int), reason, len(html), html)
|
||||
write_nonblock(sock, http.encode('latin1'))
|
||||
|
||||
|
||||
def normalize_name(name):
|
||||
return "-".join([w.lower().capitalize() for w in name.split("-")])
|
||||
return "-".join([w.lower().capitalize() for w in name.split("-")])
|
||||
|
||||
|
||||
def import_app(module):
|
||||
parts = module.split(":", 1)
|
||||
@ -336,7 +353,7 @@ def import_app(module):
|
||||
except ImportError:
|
||||
if module.endswith(".py") and os.path.exists(module):
|
||||
raise ImportError("Failed to find application, did "
|
||||
"you mean '%s:%s'?" % (module.rsplit(".",1)[0], obj))
|
||||
"you mean '%s:%s'?" % (module.rsplit(".", 1)[0], obj))
|
||||
else:
|
||||
raise
|
||||
|
||||
@ -348,6 +365,7 @@ def import_app(module):
|
||||
raise TypeError("Application object must be callable.")
|
||||
return app
|
||||
|
||||
|
||||
def http_date(timestamp=None):
|
||||
"""Return the current date and time formatted for a message header."""
|
||||
if timestamp is None:
|
||||
@ -359,9 +377,11 @@ def http_date(timestamp=None):
|
||||
hh, mm, ss)
|
||||
return s
|
||||
|
||||
|
||||
def is_hoppish(header):
|
||||
return header.lower().strip() in hop_headers
|
||||
|
||||
|
||||
def daemonize():
|
||||
"""\
|
||||
Standard daemonization of a process.
|
||||
@ -383,6 +403,7 @@ def daemonize():
|
||||
os.dup2(0, 1)
|
||||
os.dup2(0, 2)
|
||||
|
||||
|
||||
def seed():
|
||||
try:
|
||||
random.seed(os.urandom(64))
|
||||
@ -397,6 +418,7 @@ def check_is_writeable(path):
|
||||
raise RuntimeError("Error: '%s' isn't writable [%r]" % (path, e))
|
||||
f.close()
|
||||
|
||||
|
||||
def to_bytestring(value):
|
||||
"""Converts a string argument to a byte string"""
|
||||
if isinstance(value, bytes):
|
||||
|
||||
@ -16,6 +16,7 @@ from gunicorn import six
|
||||
|
||||
ALREADY_HANDLED = object()
|
||||
|
||||
|
||||
class AsyncWorker(base.Worker):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -47,9 +48,9 @@ class AsyncWorker(base.Worker):
|
||||
except StopIteration as e:
|
||||
self.log.debug("Closing connection. %s", e)
|
||||
except ssl.SSLError:
|
||||
raise # pass to next try-except level
|
||||
raise # pass to next try-except level
|
||||
except socket.error:
|
||||
raise # pass to next try-except level
|
||||
raise # pass to next try-except level
|
||||
except Exception as e:
|
||||
self.handle_error(req, client, addr, e)
|
||||
except ssl.SSLError as e:
|
||||
@ -100,7 +101,7 @@ class AsyncWorker(base.Worker):
|
||||
self.log.access(resp, req, environ, request_time)
|
||||
finally:
|
||||
if hasattr(respiter, "close"):
|
||||
respiter.close()
|
||||
respiter.close()
|
||||
if resp.should_close():
|
||||
raise StopIteration()
|
||||
finally:
|
||||
|
||||
@ -19,6 +19,7 @@ from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
|
||||
from gunicorn.http.wsgi import default_environ, Response
|
||||
from gunicorn.six import MAXSIZE
|
||||
|
||||
|
||||
class Worker(object):
|
||||
|
||||
SIGNALS = [getattr(signal, "SIG%s" % x) \
|
||||
@ -129,7 +130,7 @@ class Worker(object):
|
||||
|
||||
def handle_error(self, req, client, addr, exc):
|
||||
request_start = datetime.now()
|
||||
addr = addr or ('', -1) # unix socket case
|
||||
addr = addr or ('', -1) # unix socket case
|
||||
if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
|
||||
InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,
|
||||
LimitRequestLine, LimitRequestHeaders,
|
||||
@ -147,7 +148,7 @@ class Worker(object):
|
||||
elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
|
||||
mesg = "<p>%s</p>" % str(exc)
|
||||
if not req and hasattr(exc, "req"):
|
||||
req = exc.req # for access log
|
||||
req = exc.req # for access log
|
||||
elif isinstance(exc, LimitRequestLine):
|
||||
mesg = "<p>%s</p>" % str(exc)
|
||||
elif isinstance(exc, LimitRequestHeaders):
|
||||
|
||||
@ -15,12 +15,13 @@ from eventlet.greenio import GreenSocket
|
||||
|
||||
from gunicorn.workers.async import AsyncWorker
|
||||
|
||||
|
||||
class EventletWorker(AsyncWorker):
|
||||
|
||||
@classmethod
|
||||
def setup(cls):
|
||||
import eventlet
|
||||
if eventlet.version_info < (0,9,7):
|
||||
if eventlet.version_info < (0, 9, 7):
|
||||
raise RuntimeError("You need eventlet >= 0.9.7")
|
||||
eventlet.monkey_patch(os=False)
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ BASE_WSGI_ENV = {
|
||||
'wsgi.run_once': False
|
||||
}
|
||||
|
||||
|
||||
class GeventWorker(AsyncWorker):
|
||||
|
||||
server_class = None
|
||||
@ -52,7 +53,6 @@ class GeventWorker(AsyncWorker):
|
||||
def timeout_ctx(self):
|
||||
return gevent.Timeout(self.cfg.keepalive, False)
|
||||
|
||||
|
||||
def run(self):
|
||||
servers = []
|
||||
ssl_args = {}
|
||||
@ -80,7 +80,7 @@ class GeventWorker(AsyncWorker):
|
||||
while self.alive:
|
||||
self.notify()
|
||||
|
||||
if pid == os.getpid() and self.ppid != os.getppid():
|
||||
if pid == os.getpid() and self.ppid != os.getppid():
|
||||
self.log.info("Parent changed, shutting down: %s", self)
|
||||
break
|
||||
|
||||
@ -137,12 +137,12 @@ class GeventResponse(object):
|
||||
headers = None
|
||||
response_length = None
|
||||
|
||||
|
||||
def __init__(self, status, headers, clength):
|
||||
self.status = status
|
||||
self.headers = headers
|
||||
self.response_length = clength
|
||||
|
||||
|
||||
class PyWSGIHandler(pywsgi.WSGIHandler):
|
||||
|
||||
def log_request(self):
|
||||
@ -160,9 +160,11 @@ class PyWSGIHandler(pywsgi.WSGIHandler):
|
||||
env['RAW_URI'] = self.path
|
||||
return env
|
||||
|
||||
|
||||
class PyWSGIServer(pywsgi.WSGIServer):
|
||||
base_env = BASE_WSGI_ENV
|
||||
|
||||
|
||||
class GeventPyWSGIWorker(GeventWorker):
|
||||
"The Gevent StreamServer based workers."
|
||||
server_class = PyWSGIServer
|
||||
|
||||
@ -17,6 +17,7 @@ import gunicorn.util as util
|
||||
import gunicorn.workers.base as base
|
||||
from gunicorn import six
|
||||
|
||||
|
||||
class SyncWorker(base.Worker):
|
||||
|
||||
def run(self):
|
||||
|
||||
@ -8,6 +8,7 @@ import tempfile
|
||||
|
||||
from gunicorn import util
|
||||
|
||||
|
||||
class WorkerTmp(object):
|
||||
|
||||
def __init__(self, cfg):
|
||||
@ -30,7 +31,7 @@ class WorkerTmp(object):
|
||||
|
||||
def notify(self):
|
||||
try:
|
||||
self.spinner = (self.spinner+1) % 2
|
||||
self.spinner = (self.spinner + 1) % 2
|
||||
os.fchmod(self._tmp.fileno(), self.spinner)
|
||||
except AttributeError:
|
||||
# python < 2.6
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user