annotate piecrust/serving/server.py @ 663:3ceeca7bb71c

themes: Add support for a `--theme` argument to `chef`.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 01 Mar 2016 22:27:28 -0800
parents 657384f08ca3
children 81d9c3a3a0b5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
1 import io
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
2 import os
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
3 import gzip
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
4 import time
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
5 import os.path
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
6 import hashlib
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
7 import logging
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
8 from werkzeug.exceptions import (
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
9 NotFound, MethodNotAllowed, InternalServerError, HTTPException)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
10 from werkzeug.wrappers import Request, Response
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
11 from jinja2 import FileSystemLoader, Environment
409
2bb5327c4c1f debug: Fix serving of resources now that the module moved to a sub-folder.
Ludovic Chabant <ludovic@chabant.com>
parents: 391
diff changeset
12 from piecrust import CACHE_DIR, RESOURCES_DIR
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
13 from piecrust.rendering import PageRenderingContext, render_page
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
14 from piecrust.routing import RouteNotFoundError
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
15 from piecrust.serving.util import (
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
16 content_type_map, make_wrapped_file_response, get_requested_page,
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
17 get_app_for_server)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
18 from piecrust.sources.base import SourceNotFoundError
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
19
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
20
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
21 logger = logging.getLogger(__name__)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
22
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
23
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
24 class WsgiServer(object):
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
25 def __init__(self, root_dir, **kwargs):
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
26 self.server = Server(root_dir, **kwargs)
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
27
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
28 def __call__(self, environ, start_response):
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
29 return self.server._run_request(environ, start_response)
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
30
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
31
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
32 class ServeRecord(object):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
33 def __init__(self):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
34 self.entries = {}
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
35
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
36 def addEntry(self, entry):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
37 key = self._makeKey(entry.uri, entry.sub_num)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
38 self.entries[key] = entry
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
39
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
40 def getEntry(self, uri, sub_num):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
41 key = self._makeKey(uri, sub_num)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
42 return self.entries.get(key)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
43
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
44 def _makeKey(self, uri, sub_num):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
45 return "%s:%s" % (uri, sub_num)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
46
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
47
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
48 class ServeRecordPageEntry(object):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
49 def __init__(self, uri, sub_num):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
50 self.uri = uri
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
51 self.sub_num = sub_num
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
52 self.used_source_names = set()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
53
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
54
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
55 class MultipleNotFound(HTTPException):
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
56 code = 404
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
57
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
58 def __init__(self, description, nfes):
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
59 super(MultipleNotFound, self).__init__(description)
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
60 self._nfes = nfes
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
61
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
62 def get_description(self, environ=None):
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
63 from werkzeug.utils import escape
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
64 desc = '<p>' + self.description + '</p>'
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
65 desc += '<p>'
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
66 for nfe in self._nfes:
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
67 desc += '<li>' + escape(str(nfe)) + '</li>'
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
68 desc += '</p>'
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
69 return desc
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
70
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
71
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
72 class Server(object):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
73 def __init__(self, root_dir,
663
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
74 debug=False, theme_site=False,
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
75 sub_cache_dir=None, enable_debug_info=True,
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
76 root_url='/', static_preview=True):
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
77 self.root_dir = root_dir
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
78 self.debug = debug
663
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
79 self.theme_site = theme_site
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
80 self.sub_cache_dir = sub_cache_dir
375
aade4ea57e7f serve: Add ability to suppress the debug info window programmatically.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
81 self.enable_debug_info = enable_debug_info
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
82 self.root_url = root_url
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
83 self.static_preview = static_preview
391
3e4bb57d8506 tests: Add support for testing the Chef server.
Ludovic Chabant <ludovic@chabant.com>
parents: 390
diff changeset
84 self._page_record = ServeRecord()
3e4bb57d8506 tests: Add support for testing the Chef server.
Ludovic Chabant <ludovic@chabant.com>
parents: 390
diff changeset
85 self._out_dir = os.path.join(root_dir, CACHE_DIR, 'server')
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
86 if sub_cache_dir:
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
87 self._out_dir = os.path.join(sub_cache_dir, 'server')
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
88
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
89 def _run_request(self, environ, start_response):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
90 try:
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 551
diff changeset
91 response = self._try_run_request(environ)
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
92 return response(environ, start_response)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
93 except Exception as ex:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
94 if self.debug:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
95 raise
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
96 return self._handle_error(ex, environ, start_response)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
97
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 551
diff changeset
98 def _try_run_request(self, environ):
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
99 request = Request(environ)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
100
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
101 # We don't support anything else than GET requests since we're
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
102 # previewing something that will be static later.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
103 if self.static_preview and request.method != 'GET':
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
104 logger.error("Only GET requests are allowed, got %s" %
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
105 request.method)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
106 raise MethodNotAllowed()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
107
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
108 # Also handle requests to a pipeline-built asset right away.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
109 response = self._try_serve_asset(environ, request)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
110 if response is not None:
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 551
diff changeset
111 return response
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
112
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
113 # Create the app for this request.
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
114 app = get_app_for_server(self.root_dir, debug=self.debug,
663
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
115 theme_site=self.theme_site,
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
116 sub_cache_dir=self.sub_cache_dir,
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
117 root_url=self.root_url)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
118 if (app.config.get('site/enable_debug_info') and
375
aade4ea57e7f serve: Add ability to suppress the debug info window programmatically.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
119 self.enable_debug_info and
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
120 '!debug' in request.args):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
121 app.config.set('site/show_debug_info', True)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
122
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
123 # We'll serve page assets directly from where they are.
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
124 app.env.base_asset_url_format = self.root_url + '_asset/%path%'
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
125
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
126 # Let's see if it can be a page asset.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
127 response = self._try_serve_page_asset(app, environ, request)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
128 if response is not None:
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 551
diff changeset
129 return response
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
130
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
131 # Nope. Let's see if it's an actual page.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
132 try:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
133 response = self._try_serve_page(app, environ, request)
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 551
diff changeset
134 return response
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
135 except (RouteNotFoundError, SourceNotFoundError) as ex:
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
136 raise NotFound() from ex
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
137 except HTTPException:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
138 raise
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
139 except Exception as ex:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
140 if app.debug:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
141 logger.exception(ex)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
142 raise
523
b22e69ff54f4 serve: Don't show the same error message twice.
Ludovic Chabant <ludovic@chabant.com>
parents: 520
diff changeset
143 logger.error(str(ex))
b22e69ff54f4 serve: Don't show the same error message twice.
Ludovic Chabant <ludovic@chabant.com>
parents: 520
diff changeset
144 msg = "There was an error trying to serve: %s" % request.path
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
145 raise InternalServerError(msg) from ex
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
146
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
147 def _try_serve_asset(self, environ, request):
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
148 offset = len(self.root_url)
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
149 rel_req_path = request.path[offset:].replace('/', os.sep)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
150 if request.path.startswith('/_cache/'):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
151 # Some stuff needs to be served directly from the cache directory,
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
152 # like LESS CSS map files.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
153 full_path = os.path.join(self.root_dir, rel_req_path)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
154 else:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
155 full_path = os.path.join(self._out_dir, rel_req_path)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
156
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
157 try:
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
158 response = make_wrapped_file_response(environ, request, full_path)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
159 return response
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
160 except OSError:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
161 pass
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
162 return None
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
163
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
164 def _try_serve_page_asset(self, app, environ, request):
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
165 if not request.path.startswith(self.root_url + '_asset/'):
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
166 return None
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
167
575
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
168 offset = len(self.root_url + '_asset/')
657384f08ca3 serve: Make it possible to preview pages with a custom root URL.
Ludovic Chabant <ludovic@chabant.com>
parents: 555
diff changeset
169 full_path = os.path.join(app.root_dir, request.path[offset:])
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
170 if not os.path.isfile(full_path):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
171 return None
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
172
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
173 return make_wrapped_file_response(environ, request, full_path)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
174
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
175 def _try_serve_page(self, app, environ, request):
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
176 # Find a matching page.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
177 req_page = get_requested_page(app, request.path)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
178
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
179 # If we haven't found any good match, report all the places we didn't
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
180 # find it at.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
181 qp = req_page.qualified_page
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
182 if qp is None:
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
183 msg = "Can't find path for '%s':" % request.path
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
184 raise MultipleNotFound(msg, req_page.not_found_errors)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
185
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
186 # We have a page, let's try to render it.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
187 render_ctx = PageRenderingContext(qp,
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
188 page_num=req_page.page_num,
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
189 force_render=True)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
190 if qp.route.taxonomy_name is not None:
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
191 taxonomy = app.getTaxonomy(qp.route.taxonomy_name)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
192 tax_terms = qp.route.getTaxonomyTerms(qp.route_metadata)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
193 render_ctx.setTaxonomyFilter(tax_terms, needs_slugifier=True)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
194
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
195 # See if this page is known to use sources. If that's the case,
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
196 # just don't use cached rendered segments for that page (but still
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
197 # use them for pages that are included in it).
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
198 uri = qp.getUri()
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
199 entry = self._page_record.getEntry(uri, req_page.page_num)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
200 if (qp.route.taxonomy_name is not None or entry is None or
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
201 entry.used_source_names):
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
202 cache_key = '%s:%s' % (uri, req_page.page_num)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
203 app.env.rendered_segments_repository.invalidate(cache_key)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
204
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
205 # Render the page.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
206 rendered_page = render_page(render_ctx)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
207
555
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
208 # Check if this page is a taxonomy page that actually doesn't match
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
209 # anything.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
210 if qp.route.taxonomy_name is not None:
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
211 paginator = rendered_page.data.get('pagination')
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
212 if (paginator and paginator.is_loaded and
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
213 len(paginator.items) == 0):
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
214 taxonomy = app.getTaxonomy(qp.route.taxonomy_name)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
215 message = ("This URL matched a route for taxonomy '%s' but "
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
216 "no pages have been found to have it. This page "
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
217 "won't be generated by a bake." % taxonomy.name)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
218 raise NotFound(message)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
219
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
220 # Remember stuff for next time.
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
221 if entry is None:
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
222 entry = ServeRecordPageEntry(req_page.req_path, req_page.page_num)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
223 self._page_record.addEntry(entry)
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
224 for p, pinfo in render_ctx.render_passes.items():
daf8df5ade7d serve: Refactor the server to make pieces usable by the debugging middleware.
Ludovic Chabant <ludovic@chabant.com>
parents: 554
diff changeset
225 entry.used_source_names |= pinfo.used_source_names
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
226
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
227 # Start doing stuff.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
228 page = rendered_page.page
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
229 rp_content = rendered_page.content
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
230
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
231 # Profiling.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
232 if app.config.get('site/show_debug_info'):
554
155c7e20414f serve: Fix timing information in the debug window.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
233 now_time = time.perf_counter()
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
234 timing_info = (
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
235 '%8.1f ms' %
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
236 ((now_time - app.env.start_time) * 1000.0))
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
237 rp_content = rp_content.replace(
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
238 '__PIECRUST_TIMING_INFORMATION__', timing_info)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
239
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
240 # Build the response.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
241 response = Response()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
242
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
243 etag = hashlib.md5(rp_content.encode('utf8')).hexdigest()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
244 if not app.debug and etag in request.if_none_match:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
245 response.status_code = 304
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
246 return response
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
247
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
248 response.set_etag(etag)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
249 response.content_md5 = etag
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
250
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
251 cache_control = response.cache_control
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
252 if app.debug:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
253 cache_control.no_cache = True
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
254 cache_control.must_revalidate = True
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
255 else:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
256 cache_time = (page.config.get('cache_time') or
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
257 app.config.get('site/cache_time'))
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
258 if cache_time:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
259 cache_control.public = True
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
260 cache_control.max_age = cache_time
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
261
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
262 content_type = page.config.get('content_type')
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
263 if content_type and '/' not in content_type:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
264 mimetype = content_type_map.get(content_type, content_type)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
265 else:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
266 mimetype = content_type
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
267 if mimetype:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
268 response.mimetype = mimetype
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
269
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
270 if ('gzip' in request.accept_encodings and
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
271 app.config.get('site/enable_gzip')):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
272 try:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
273 with io.BytesIO() as gzip_buffer:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
274 with gzip.open(gzip_buffer, mode='wt',
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
275 encoding='utf8') as gzip_file:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
276 gzip_file.write(rp_content)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
277 rp_content = gzip_buffer.getvalue()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
278 response.content_encoding = 'gzip'
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
279 except Exception:
523
b22e69ff54f4 serve: Don't show the same error message twice.
Ludovic Chabant <ludovic@chabant.com>
parents: 520
diff changeset
280 logger.error("Error compressing response, "
b22e69ff54f4 serve: Don't show the same error message twice.
Ludovic Chabant <ludovic@chabant.com>
parents: 520
diff changeset
281 "falling back to uncompressed.")
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
282 response.set_data(rp_content)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
283
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
284 return response
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
285
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
286 def _handle_error(self, exception, environ, start_response):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
287 code = 500
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
288 if isinstance(exception, HTTPException):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
289 code = exception.code
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
290
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
291 path = 'error'
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
292 if isinstance(exception, (NotFound, MultipleNotFound)):
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
293 path += '404'
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
294
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
295 descriptions = self._get_exception_descriptions(exception)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
296
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
297 env = Environment(loader=ErrorMessageLoader())
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
298 template = env.get_template(path)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
299 context = {'details': descriptions}
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
300 response = Response(template.render(context), mimetype='text/html')
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
301 response.status_code = code
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
302 return response(environ, start_response)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
303
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
304 def _get_exception_descriptions(self, exception):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
305 desc = []
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
306 while exception is not None:
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
307 if isinstance(exception, MultipleNotFound):
663
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
308 desc += [str(e) for e in exception._nfes]
517
c7e8b4a5afe3 serve: Improve error reporting when pages are not found.
Ludovic Chabant <ludovic@chabant.com>
parents: 515
diff changeset
309 elif isinstance(exception, HTTPException):
663
3ceeca7bb71c themes: Add support for a `--theme` argument to `chef`.
Ludovic Chabant <ludovic@chabant.com>
parents: 575
diff changeset
310 desc.append(exception.get_description())
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
311 else:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
312 desc.append(str(exception))
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
313
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
314 inner_ex = exception.__cause__
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
315 if inner_ex is None:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
316 inner_ex = exception.__context__
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
317 exception = inner_ex
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
318 return desc
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
319
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
320
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
321 class ErrorMessageLoader(FileSystemLoader):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
322 def __init__(self):
409
2bb5327c4c1f debug: Fix serving of resources now that the module moved to a sub-folder.
Ludovic Chabant <ludovic@chabant.com>
parents: 391
diff changeset
323 base_dir = os.path.join(RESOURCES_DIR, 'messages')
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
324 super(ErrorMessageLoader, self).__init__(base_dir)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
325
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
326 def get_source(self, env, template):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
327 template += '.html'
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
328 return super(ErrorMessageLoader, self).get_source(env, template)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
329
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
330