comparison piecrust/serving/middlewares.py @ 852:4850f8c21b6e

core: Start of the big refactor for PieCrust 3.0. * Everything is a `ContentSource`, including assets directories. * Most content sources are subclasses of the base file-system source. * A source is processed by a "pipeline", and there are 2 built-in pipelines, one for assets and one for pages. The asset pipeline is vaguely functional, but the page pipeline is completely broken right now. * Rewrite the baking process as just running appropriate pipelines on each content item. This should allow for better parallelization.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 17 May 2017 00:11:48 -0700
parents c2ea75e37540
children f070a4fc033c
comparison
equal deleted inserted replaced
851:2c7e57d80bba 852:4850f8c21b6e
2 from werkzeug.exceptions import NotFound, Forbidden 2 from werkzeug.exceptions import NotFound, Forbidden
3 from werkzeug.wrappers import Request, Response 3 from werkzeug.wrappers import Request, Response
4 from werkzeug.wsgi import ClosingIterator 4 from werkzeug.wsgi import ClosingIterator
5 from piecrust import RESOURCES_DIR, CACHE_DIR 5 from piecrust import RESOURCES_DIR, CACHE_DIR
6 from piecrust.data.builder import ( 6 from piecrust.data.builder import (
7 DataBuildingContext, build_page_data) 7 DataBuildingContext, build_page_data)
8 from piecrust.data.debug import build_var_debug_info 8 from piecrust.data.debug import build_var_debug_info
9 from piecrust.page import PageNotFoundError
9 from piecrust.routing import RouteNotFoundError 10 from piecrust.routing import RouteNotFoundError
10 from piecrust.serving.util import ( 11 from piecrust.serving.util import (
11 make_wrapped_file_response, get_requested_page, get_app_for_server) 12 make_wrapped_file_response, get_requested_page, get_app_for_server)
12 from piecrust.sources.pageref import PageNotFoundError
13 13
14 14
15 class StaticResourcesMiddleware(object): 15 class StaticResourcesMiddleware(object):
16 """ WSGI middleware that serves static files from the `resources/server` 16 """ WSGI middleware that serves static files from the `resources/server`
17 directory in the PieCrust package. 17 directory in the PieCrust package.
27 rel_req_path = request.path[len(static_mount):] 27 rel_req_path = request.path[len(static_mount):]
28 mount = os.path.join(RESOURCES_DIR, 'server') 28 mount = os.path.join(RESOURCES_DIR, 'server')
29 full_path = os.path.join(mount, rel_req_path) 29 full_path = os.path.join(mount, rel_req_path)
30 try: 30 try:
31 response = make_wrapped_file_response( 31 response = make_wrapped_file_response(
32 environ, request, full_path) 32 environ, request, full_path)
33 return response(environ, start_response) 33 return response(environ, start_response)
34 except OSError: 34 except OSError:
35 pass 35 pass
36 36
37 return self.app(environ, start_response) 37 return self.app(environ, start_response)
45 self.app = app 45 self.app = app
46 self.appfactory = appfactory 46 self.appfactory = appfactory
47 self.run_sse_check = run_sse_check 47 self.run_sse_check = run_sse_check
48 self._proc_loop = None 48 self._proc_loop = None
49 self._out_dir = os.path.join( 49 self._out_dir = os.path.join(
50 appfactory.root_dir, CACHE_DIR, appfactory.cache_key, 'server') 50 appfactory.root_dir, CACHE_DIR, appfactory.cache_key, 'server')
51 self._handlers = { 51 self._handlers = {
52 'debug_info': self._getDebugInfo, 52 'debug_info': self._getDebugInfo,
53 'werkzeug_shutdown': self._shutdownWerkzeug, 53 'werkzeug_shutdown': self._shutdownWerkzeug,
54 'pipeline_status': self._startSSEProvider} 54 'pipeline_status': self._startSSEProvider}
55 55
56 if not self.run_sse_check or self.run_sse_check(): 56 if not self.run_sse_check or self.run_sse_check():
57 # When using a server with code reloading, some implementations 57 # When using a server with code reloading, some implementations
58 # use process forking and we end up going here twice. We only want 58 # use process forking and we end up going here twice. We only want
59 # to start the pipeline loop in the inner process most of the 59 # to start the pipeline loop in the inner process most of the
109 response = Response("Server shutting down...") 109 response = Response("Server shutting down...")
110 return response(request.environ, start_response) 110 return response(request.environ, start_response)
111 111
112 def _startSSEProvider(self, request, start_response): 112 def _startSSEProvider(self, request, start_response):
113 from piecrust.serving.procloop import ( 113 from piecrust.serving.procloop import (
114 PipelineStatusServerSentEventProducer) 114 PipelineStatusServerSentEventProducer)
115 provider = PipelineStatusServerSentEventProducer( 115 provider = PipelineStatusServerSentEventProducer(
116 self._proc_loop) 116 self._proc_loop)
117 it = provider.run() 117 it = provider.run()
118 response = Response(it, mimetype='text/event-stream') 118 response = Response(it, mimetype='text/event-stream')
119 response.headers['Cache-Control'] = 'no-cache' 119 response.headers['Cache-Control'] = 'no-cache'
120 response.headers['Last-Event-ID'] = \ 120 response.headers['Last-Event-ID'] = \
121 self._proc_loop.last_status_id 121 self._proc_loop.last_status_id
122 return ClosingIterator( 122 return ClosingIterator(
123 response(request.environ, start_response), 123 response(request.environ, start_response),
124 [provider.close]) 124 [provider.close])
125 125