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 from fnmatch import fnmatch | 5 from fnmatch import fnmatch |
6 import logging | 6 import logging |
7 import mimetypes | 7 import mimetypes |
8 import os | 8 import os |
9 import traceback | 9 import traceback |
10 | 10 |
11 from appengine_wrappers import IsDevServer | 11 from appengine_wrappers import IsDevServer |
12 from branch_utility import BranchUtility | |
13 from file_system import FileNotFoundError | 12 from file_system import FileNotFoundError |
14 from server_instance import ServerInstance | 13 from server_instance import ServerInstance |
15 from servlet import Servlet, Response | 14 from servlet import Servlet, Response |
16 import svn_constants | 15 import svn_constants |
17 | 16 |
18 def _IsBinaryMimetype(mimetype): | 17 def _IsBinaryMimetype(mimetype): |
19 return any(mimetype.startswith(prefix) | 18 return any(mimetype.startswith(prefix) |
20 for prefix in ['audio', 'image', 'video']) | 19 for prefix in ['audio', 'image', 'video']) |
21 | 20 |
22 class RenderServlet(Servlet): | 21 class RenderServlet(Servlet): |
23 '''Servlet which renders templates. | 22 '''Servlet which renders templates. |
24 ''' | 23 ''' |
25 class Delegate(object): | 24 class Delegate(object): |
26 def CreateServerInstanceForChannel(self, channel): | 25 def CreateServerInstance(self): |
27 raise NotImplementedError() | 26 raise NotImplementedError(self.__class__) |
28 | 27 |
29 def __init__(self, request, delegate, default_channel='stable'): | 28 def __init__(self, request, delegate): |
30 Servlet.__init__(self, request) | 29 Servlet.__init__(self, request) |
31 self._delegate = delegate | 30 self._delegate = delegate |
32 self._default_channel = default_channel | |
33 | 31 |
34 def Get(self): | 32 def Get(self): |
35 path_with_channel, headers = (self._request.path, self._request.headers) | 33 server_instance = self._delegate.CreateServerInstance() |
36 | 34 |
37 # Redirect "extensions" and "extensions/" to "extensions/index.html", etc. | 35 path = self._request.path |
38 if (os.path.splitext(path_with_channel)[1] == '' and | 36 canonical_result = server_instance.path_canonicalizer.Canonicalize(path) |
cduvall
2013/05/15 00:50:50
does the path passed in here have a leading '/'? I
not at google - send to devlin
2013/05/15 01:26:50
yeah, the servlet strips off the leading '/' for t
| |
39 path_with_channel.find('/') == -1): | 37 canonical_path = canonical_result.path.lstrip('/') |
40 path_with_channel += '/' | 38 # TODO(kalman): do this generically by detecting index.html. |
41 if path_with_channel.endswith('/'): | 39 if canonical_path in ('apps/', 'extensions/'): |
42 return Response.Redirect('/%sindex.html' % path_with_channel) | 40 canonical_path += 'index.html' |
43 | |
44 channel, path = BranchUtility.SplitChannelNameFromPath(path_with_channel) | |
45 | |
46 if channel == self._default_channel: | |
47 return Response.Redirect('/%s' % path) | |
48 | |
49 if channel is None: | |
50 channel = self._default_channel | |
51 | |
52 server_instance = self._delegate.CreateServerInstanceForChannel(channel) | |
53 | |
54 canonical_path = ( | |
55 server_instance.path_canonicalizer.Canonicalize(path).lstrip('/')) | |
56 if path != canonical_path: | 41 if path != canonical_path: |
57 redirect_path = (canonical_path if channel is None else | 42 return Response.Redirect('/%s' % canonical_path, |
58 '%s/%s' % (channel, canonical_path)) | 43 permanent=canonical_result.permanent) |
59 return Response.Redirect('/%s' % redirect_path) | |
60 | 44 |
61 templates = server_instance.template_data_source_factory.Create( | 45 templates = server_instance.template_data_source_factory.Create( |
62 self._request, path) | 46 self._request, path) |
63 | 47 |
64 content = None | 48 content = None |
65 content_type = None | 49 content_type = None |
66 | 50 |
67 try: | 51 try: |
68 if fnmatch(path, 'extensions/examples/*.zip'): | 52 if fnmatch(path, 'extensions/examples/*.zip'): |
69 content = server_instance.example_zipper.Create( | 53 content = server_instance.example_zipper.Create( |
(...skipping 23 matching lines...) Expand all Loading... | |
93 return Response.NotFound(templates.Render('404'), headers=headers) | 77 return Response.NotFound(templates.Render('404'), headers=headers) |
94 | 78 |
95 if not content: | 79 if not content: |
96 logging.error('%s had empty content' % path) | 80 logging.error('%s had empty content' % path) |
97 | 81 |
98 headers.update({ | 82 headers.update({ |
99 'content-type': content_type, | 83 'content-type': content_type, |
100 'cache-control': 'max-age=300', | 84 'cache-control': 'max-age=300', |
101 }) | 85 }) |
102 return Response.Ok(content, headers=headers) | 86 return Response.Ok(content, headers=headers) |
OLD | NEW |