diff --git a/docs/source/custom.rst b/docs/source/custom.rst new file mode 100644 index 00000000..4dfba9e6 --- /dev/null +++ b/docs/source/custom.rst @@ -0,0 +1,61 @@ +.. _custom: + +================== +Custom Application +================== + +.. versionadded:: 19.0 + +Sometimes, you want to integrate Gunicorn with your WSGI application. In this +case, you can inherit from :class:`gunicorn.app.base.BaseApplication`. + +Here is a small example where we create a very small WSGI app and load it with a +custom Application:: + + #!/usr/bin/env python + import gunicorn.app.base + + def handler_app(environ, start_response): + response_body = 'Works fine' + status = '200 OK' + + response_headers = [ + ('Content-Type', 'text/plain'), + ('Content-Length', str(len(response_body))) + ] + + start_response(status, response_headers) + + return [response_body] + + class StandaloneApplication(gunicorn.app.base.BaseApplication): + def __init__(self, app, options=None): + self.options = dict(options or {}) + self.application = app + super(StandaloneApplication, self).__init__() + + def load_config(self): + tmp_config = map( + lambda item: (item[0].lower(), item[1]), + self.options.iteritems() + ) + + config = dict( + (key, value) + for key, value in tmp_config + if key in self.cfg.settings and value is not None + ) + + for key, value in config.iteritems(): + self.cfg.set(key.lower(), value) + + def load(self): + return self.application + + if __name__ == '__main__': + options = { + 'bind': '%s:%s' % ('127.0.0.1', '8080'), + 'workers': 4, + # 'pidfile': pidfile, + } + StandaloneApplication(handler_app, options).run() diff --git a/docs/source/index.rst b/docs/source/index.rst index 51f19959..b7e33b45 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -43,6 +43,7 @@ Contents deploy design signals + custom community faq news diff --git a/docs/source/run.rst b/docs/source/run.rst index 2ff0ce1c..baa0fa32 100644 --- a/docs/source/run.rst +++ b/docs/source/run.rst @@ -128,59 +128,3 @@ new workers are started. See the note about preloading_. .. _preloading: configure.html#preload-app - -custom application ------------------- - -Sometimes, you want to integrate Gunicorn with your WSGI application. In this -case, you can inherit from gunicorn.app.base.BaseApplication. - -Example:: - - #!/usr/bin/env python - import gunicorn.app.base - - def my_index(environ, start_response): - response_body = 'Works fine' - status = '200 OK' - - response_headers = [ - ('Content-Type', 'text/plain'), - ('Content-Length', str(len(response_body))) - ] - - start_response(status, response_headers) - - return [response_body] - - class MyApplication(gunicorn.app.base.BaseApplication): - def __init__(self, app, options=None): - self.options = dict(options or {}) - self.application = app - super(MyApplication, self).__init__() - - def load_config(self): - tmp_config = map( - lambda item: (item[0].lower(), item[1]), - self.options.iteritems() - ) - - config = dict( - (key, value) - for key, value in tmp_config - if key in self.cfg.settings and value is not None - ) - - for key, value in config.iteritems(): - self.cfg.set(key.lower(), value) - - def load(self): - return self.application - - if __name__ == '__main__': - options = { - 'bind': '%s:%s' % ('127.0.0.1', '8080'), - 'workers': 4, - # 'pidfile': pidfile, - } - MyApplication(my_index, options).run() diff --git a/examples/standalone_app.py b/examples/standalone_app.py new file mode 100644 index 00000000..800d5a1c --- /dev/null +++ b/examples/standalone_app.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# An example of a standalone application using the internal API of Gunicorn. +# +# $ python standalone_app.py +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import gunicorn +import gunicorn.app.base +import multiprocessing + +def number_of_workers(): + return (multiprocessing.cpu_count() * 2) + 1 + + +def handler_app(environ, start_response): + response_body = 'Works fine' + status = '200 OK' + + response_headers = [ + ('Content-Type', 'text/plain'), + ('Content-Lenfth', str(len(response_body))), + ] + + start_response(status, response_headers) + + return [response_body] + + +class StandaloneApplication(gunicorn.app.base.BaseApplication): + def __init__(self, app, options=None): + self.options = dict(options or {}) + self.application = app + super(StandaloneApplication, self).__init__() + + def load_config(self): + tmp_config = map( + lambda item: (item[0].lower(), item[1]), + self.options.iteritems() + ) + + config = dict( + (key, value) + for key, value in tmp_config + if key in self.cfg.settings and value is not None + ) + + for key, value in config.iteritems(): + self.cfg.set(key.lower(), value) + + def load(self): + return self.application + + +if __name__ == '__main__': + options = { + 'bind': '%s:%s' % ('127.0.0.1', '8080'), + 'workers': number_of_workers(), + } + StandaloneApplication(handler_app, options).run() \ No newline at end of file diff --git a/gunicorn/app/base.py b/gunicorn/app/base.py index 1ad0aeb5..08958e25 100644 --- a/gunicorn/app/base.py +++ b/gunicorn/app/base.py @@ -27,6 +27,9 @@ class BaseApplication(object): self.do_load_config() def do_load_config(self): + """ + Loads the configuration + """ try: self.load_default_config() self.load_config() @@ -45,6 +48,14 @@ class BaseApplication(object): def load(self): raise NotImplementedError + def load_config(self): + """ + This method is used to load the configuration from one or several input(s). + Custom Command line, configuration file. + You have to override this method in your class. + """ + raise NotImplementedError + def reload(self): self.do_load_config() if self.cfg.spew: @@ -65,6 +76,10 @@ class BaseApplication(object): class Application(BaseApplication): def load_config_from_file(self, filename): + """ + Loads the configuration file: the file is a python file, otherwise raise an RuntimeError + Exception or stop the process if the configuration file contains a syntax error. + """ if not os.path.exists(filename): raise RuntimeError("%r doesn't exist" % filename)