Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import hashlib | |
| 5 import logging | 6 import logging |
| 6 import posixpath | 7 import posixpath |
| 7 import traceback | 8 import traceback |
| 8 | 9 |
| 9 from branch_utility import BranchUtility | 10 from branch_utility import BranchUtility |
| 10 from environment import IsPreviewServer | 11 from environment import IsPreviewServer |
| 11 from file_system import FileNotFoundError | 12 from file_system import FileNotFoundError |
| 12 from redirector import Redirector | 13 from redirector import Redirector |
| 13 from servlet import Servlet, Response | 14 from servlet import Servlet, Response |
| 14 from special_paths import SITE_VERIFICATION_FILE | 15 from special_paths import SITE_VERIFICATION_FILE |
| 15 from third_party.handlebar import Handlebar | 16 from third_party.handlebar import Handlebar |
| 16 | 17 |
| 17 | 18 |
| 18 def _MakeHeaders(content_type): | 19 def _MakeHeaders(content_type, etag=None): |
| 19 return { | 20 headers = { |
| 21 'Cache-Control': 'public, max-age=0, no-cache', | |
|
Jeffrey Yasskin
2014/04/02 19:54:50
Maybe link to http://www.w3.org/Protocols/rfc2616/
not at google - send to devlin
2014/04/02 22:52:53
I'll link to the spec.
| |
| 22 'Content-Type': content_type, | |
| 23 'ETag': etag, | |
|
Jeffrey Yasskin
2014/04/02 19:54:50
Remove this line, I think. you don't want to send
not at google - send to devlin
2014/04/02 22:52:53
Oops. forgot to remove it from this list.
| |
| 20 'X-Frame-Options': 'sameorigin', | 24 'X-Frame-Options': 'sameorigin', |
| 21 'Content-Type': content_type, | |
| 22 'Cache-Control': 'max-age=300', | |
| 23 } | 25 } |
| 26 if etag is not None: | |
| 27 headers['ETag'] = etag | |
| 28 return headers | |
| 24 | 29 |
| 25 | 30 |
| 26 class RenderServlet(Servlet): | 31 class RenderServlet(Servlet): |
| 27 '''Servlet which renders templates. | 32 '''Servlet which renders templates. |
| 28 ''' | 33 ''' |
| 29 | 34 |
| 30 class Delegate(object): | 35 class Delegate(object): |
| 31 def CreateServerInstance(self): | 36 def CreateServerInstance(self): |
| 32 raise NotImplementedError(self.__class__) | 37 raise NotImplementedError(self.__class__) |
| 33 | 38 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 server_instance.template_renderer.Render(content, self._request)) | 120 server_instance.template_renderer.Render(content, self._request)) |
| 116 # HACK: the site verification file (google2ed...) doesn't have a title. | 121 # HACK: the site verification file (google2ed...) doesn't have a title. |
| 117 content, doc_warnings = server_instance.document_renderer.Render( | 122 content, doc_warnings = server_instance.document_renderer.Render( |
| 118 template_content, | 123 template_content, |
| 119 path, | 124 path, |
| 120 render_title=path != SITE_VERIFICATION_FILE) | 125 render_title=path != SITE_VERIFICATION_FILE) |
| 121 warnings = template_warnings + doc_warnings | 126 warnings = template_warnings + doc_warnings |
| 122 if warnings: | 127 if warnings: |
| 123 sep = '\n - ' | 128 sep = '\n - ' |
| 124 logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) | 129 logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) |
| 130 # Content was dynamic. The new etag is the md5 hash of the content. | |
|
Jeffrey Yasskin
2014/04/02 19:54:50
Maybe comment here that we're relying on SSL for s
not at google - send to devlin
2014/04/02 22:52:53
good point.
| |
| 131 etag = None | |
| 132 elif content_and_type.version is not None: | |
| 133 # Content was static. The new etag is the version of the content. | |
| 134 etag = '"%s"' % content_and_type.version | |
| 135 else: | |
| 136 # Sometimes non-dynamic content does not have a version, for example | |
| 137 # .zip files. The new etag is the md5 hash of the content. | |
| 138 etag = None | |
| 125 | 139 |
| 126 content_type = content_and_type.content_type | 140 content_type = content_and_type.content_type |
| 127 if isinstance(content, unicode): | 141 if isinstance(content, unicode): |
| 128 content = content.encode('utf-8') | 142 content = content.encode('utf-8') |
| 129 content_type += '; charset=utf-8' | 143 content_type += '; charset=utf-8' |
| 130 | 144 |
| 131 return Response.Ok(content, headers=_MakeHeaders(content_type)) | 145 if etag is None: |
| 146 m = hashlib.md5() | |
|
Jeffrey Yasskin
2014/04/02 19:54:50
You can just use hashlib.md5(content).hexdigest().
not at google - send to devlin
2014/04/02 22:52:53
Done.
| |
| 147 m.update(content) | |
| 148 etag = '"%s"' % m.hexdigest() | |
| 149 | |
| 150 headers = _MakeHeaders(content_type, etag=etag) | |
| 151 if etag == self._request.headers.get('If-None-Match'): | |
| 152 return Response.NotModified('Not Modified', headers=headers) | |
|
Jeffrey Yasskin
2014/04/02 19:54:50
Since we've already done the work to generate the
not at google - send to devlin
2014/04/02 22:52:53
We might as well. The only reason not to do it is
| |
| 153 return Response.Ok(content, headers=headers) | |
| OLD | NEW |