Mercurial > piecrust2
comparison piecrust/serving/wrappers.py @ 917:33a89139c284
serve: Add `--admin` option to run the administration panel.
- Removed the `admin run` command.
- Cleaned up middlewares a bit.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Fri, 29 Sep 2017 08:42:38 -0700 |
parents | 1bb0d973dc69 |
children | 7ecb946bfafd |
comparison
equal
deleted
inserted
replaced
916:84ce51430346 | 917:33a89139c284 |
---|---|
4 | 4 |
5 | 5 |
6 logger = logging.getLogger(__name__) | 6 logger = logging.getLogger(__name__) |
7 | 7 |
8 | 8 |
9 def run_werkzeug_server(appfactory, host, port, | 9 def run_piecrust_server(wsgi, appfactory, host, port, |
10 use_debugger=False, use_reloader=False): | 10 is_cmdline_mode=False, |
11 serve_admin=False, | |
12 use_debugger=False, | |
13 use_reloader=False): | |
14 | |
15 if wsgi == 'werkzeug': | |
16 _run_werkzeug_server(appfactory, host, port, | |
17 is_cmdline_mode=is_cmdline_mode, | |
18 serve_admin=serve_admin, | |
19 use_debugger=use_debugger, | |
20 use_reloader=use_reloader) | |
21 | |
22 elif wsgi == 'gunicorn': | |
23 options = { | |
24 'bind': '%s:%s' % (host, port), | |
25 'accesslog': '-', # print access log to stderr | |
26 } | |
27 if use_debugger: | |
28 options['loglevel'] = 'debug' | |
29 if use_reloader: | |
30 options['reload'] = True | |
31 _run_gunicorn_server(appfactory, | |
32 is_cmdline_mode=is_cmdline_mode, | |
33 gunicorn_options=options) | |
34 | |
35 else: | |
36 raise Exception("Unknown WSGI server: %s" % wsgi) | |
37 | |
38 | |
39 def _run_werkzeug_server(appfactory, host, port, *, | |
40 is_cmdline_mode=False, | |
41 serve_admin=False, | |
42 use_debugger=False, | |
43 use_reloader=False): | |
11 from werkzeug.serving import run_simple | 44 from werkzeug.serving import run_simple |
12 | 45 |
13 def _run_sse_check(): | 46 def _run_sse_check(): |
14 # We don't want to run the processing loop here if this isn't | 47 # We don't want to run the processing loop here if this isn't |
15 # the actual process that does the serving. In most cases it is, | 48 # the actual process that does the serving. In most cases it is, |
19 # `WERKZEUG_RUN_MAIN` variable set. | 52 # `WERKZEUG_RUN_MAIN` variable set. |
20 return (not use_reloader or | 53 return (not use_reloader or |
21 os.environ.get('WERKZEUG_RUN_MAIN') == 'true') | 54 os.environ.get('WERKZEUG_RUN_MAIN') == 'true') |
22 | 55 |
23 app = _get_piecrust_server(appfactory, | 56 app = _get_piecrust_server(appfactory, |
57 is_cmdline_mode=is_cmdline_mode, | |
58 serve_site=True, | |
59 serve_admin=serve_admin, | |
24 run_sse_check=_run_sse_check) | 60 run_sse_check=_run_sse_check) |
25 | 61 |
26 # We need to do a few things to get Werkzeug to properly shutdown or | 62 # We need to do a few things to get Werkzeug to properly shutdown or |
27 # restart while SSE responses are running. This is because Werkzeug runs | 63 # restart while SSE responses are running. This is because Werkzeug runs |
28 # them in background threads (because we tell it to), but those threads | 64 # them in background threads (because we tell it to), but those threads |
43 # see the comment down there for more info. | 79 # see the comment down there for more info. |
44 def _shutdown_server(): | 80 def _shutdown_server(): |
45 from piecrust.serving import procloop | 81 from piecrust.serving import procloop |
46 procloop.server_shutdown = True | 82 procloop.server_shutdown = True |
47 | 83 |
84 if serve_admin: | |
85 from piecrust.admin import pubutil | |
86 pubutil.server_shutdown = True | |
87 | |
48 def _shutdown_server_and_raise_sigint(): | 88 def _shutdown_server_and_raise_sigint(): |
49 if not use_reloader or os.environ.get('WERKZEUG_RUN_MAIN') == 'true': | 89 if not use_reloader or os.environ.get('WERKZEUG_RUN_MAIN') == 'true': |
50 # We only need to shutdown the SSE requests for the process | 90 # We only need to shutdown the SSE requests for the process |
51 # that actually runs them. | 91 # that actually runs them. |
52 print("") | 92 print("") |
73 # not exit. | 113 # not exit. |
74 _shutdown_server() | 114 _shutdown_server() |
75 raise | 115 raise |
76 | 116 |
77 | 117 |
78 def run_gunicorn_server(appfactory, gunicorn_options=None): | 118 def _run_gunicorn_server(appfactory, |
119 is_cmdline_mode=False, | |
120 gunicorn_options=None): | |
79 from gunicorn.app.base import BaseApplication | 121 from gunicorn.app.base import BaseApplication |
80 | 122 |
81 class PieCrustGunicornApplication(BaseApplication): | 123 class PieCrustGunicornApplication(BaseApplication): |
82 def __init__(self, app, options): | 124 def __init__(self, app, options): |
83 self.app = app | 125 self.app = app |
90 self.cfg.set(k, v) | 132 self.cfg.set(k, v) |
91 | 133 |
92 def load(self): | 134 def load(self): |
93 return self.app | 135 return self.app |
94 | 136 |
95 app = _get_piecrust_server(appfactory) | 137 app = _get_piecrust_server(appfactory, |
138 is_cmdline_mode=is_cmdline_mode) | |
96 | 139 |
97 gunicorn_options = gunicorn_options or {} | 140 gunicorn_options = gunicorn_options or {} |
98 app_wrapper = PieCrustGunicornApplication(app, gunicorn_options) | 141 app_wrapper = PieCrustGunicornApplication(app, gunicorn_options) |
99 app_wrapper.run() | 142 app_wrapper.run() |
100 | 143 |
101 | 144 |
102 def _get_piecrust_server(appfactory, run_sse_check=None): | 145 def _get_piecrust_server(appfactory, *, |
103 from piecrust.serving.middlewares import ( | 146 serve_site=True, |
104 StaticResourcesMiddleware, PieCrustDebugMiddleware) | 147 serve_admin=False, |
105 from piecrust.serving.server import WsgiServer | 148 is_cmdline_mode=False, |
106 app = WsgiServer(appfactory) | 149 run_sse_check=None): |
107 app = StaticResourcesMiddleware(app) | 150 app = None |
108 app = PieCrustDebugMiddleware( | 151 |
109 app, appfactory, run_sse_check=run_sse_check) | 152 if serve_site: |
153 from piecrust.serving.middlewares import ( | |
154 PieCrustStaticResourcesMiddleware, PieCrustDebugMiddleware) | |
155 from piecrust.serving.server import PieCrustServer | |
156 | |
157 app = PieCrustServer(appfactory) | |
158 app = PieCrustStaticResourcesMiddleware(app) | |
159 | |
160 if is_cmdline_mode: | |
161 app = PieCrustDebugMiddleware( | |
162 app, appfactory, run_sse_check=run_sse_check) | |
163 | |
164 if serve_admin: | |
165 from piecrust.admin.web import create_foodtruck_app | |
166 | |
167 admin_root_url = '/pc-admin' | |
168 es = { | |
169 'FOODTRUCK_CMDLINE_MODE': is_cmdline_mode, | |
170 'FOODTRUCK_ROOT': appfactory.root_dir, | |
171 'FOODTRUCK_URL_PREFIX': admin_root_url, | |
172 'DEBUG': appfactory.debug} | |
173 if is_cmdline_mode: | |
174 es.update({ | |
175 'SECRET_KEY': os.urandom(22), | |
176 'LOGIN_DISABLED': True}) | |
177 | |
178 if appfactory.debug and is_cmdline_mode: | |
179 # Disable PIN protection with Werkzeug's debugger. | |
180 os.environ['WERKZEUG_DEBUG_PIN'] = 'off' | |
181 | |
182 admin_app = create_foodtruck_app(es) | |
183 admin_app.wsgi_app = _PieCrustSiteOrAdminMiddleware( | |
184 app, admin_app.wsgi_app, admin_root_url) | |
185 app = admin_app | |
186 | |
110 return app | 187 return app |
111 | 188 |
189 | |
190 class _PieCrustSiteOrAdminMiddleware: | |
191 def __init__(self, main_app, admin_app, admin_root_url): | |
192 from werkzeug.exceptions import abort | |
193 | |
194 def _err_resp(e, sr): | |
195 abort(404) | |
196 | |
197 self.main_app = main_app | |
198 self.admin_app = admin_app or _err_resp | |
199 self.admin_root_url = admin_root_url | |
200 | |
201 def __call__(self, environ, start_response): | |
202 path_info = environ.get('PATH_INFO', '') | |
203 if path_info.startswith(self.admin_root_url): | |
204 return self.admin_app(environ, start_response) | |
205 return self.main_app(environ, start_response) |