OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 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 atexit | 5 import atexit |
6 import datetime | 6 import datetime |
7 import email.utils | 7 import email.utils |
8 import errno | 8 import errno |
| 9 import gzip |
9 import hashlib | 10 import hashlib |
10 import logging | 11 import logging |
11 import math | 12 import math |
12 import os.path | 13 import os.path |
| 14 import shutil |
13 import socket | 15 import socket |
14 import threading | 16 import threading |
15 | 17 |
16 import SimpleHTTPServer | 18 import SimpleHTTPServer |
17 import SocketServer | 19 import SocketServer |
18 | 20 |
19 _ZERO = datetime.timedelta(0) | 21 _ZERO = datetime.timedelta(0) |
20 | 22 |
21 | 23 |
22 class UTC_TZINFO(datetime.tzinfo): | 24 class UTC_TZINFO(datetime.tzinfo): |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 if last_modified <= ims: | 115 if last_modified <= ims: |
114 self.send_response(304) | 116 self.send_response(304) |
115 return None | 117 return None |
116 | 118 |
117 return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) | 119 return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) |
118 | 120 |
119 def end_headers(self): | 121 def end_headers(self): |
120 path = self.translate_path(self.path) | 122 path = self.translate_path(self.path) |
121 | 123 |
122 if os.path.isfile(path): | 124 if os.path.isfile(path): |
| 125 self.send_header('Content-Encoding', 'gzip') |
123 etag = self.get_etag() | 126 etag = self.get_etag() |
124 if etag: | 127 if etag: |
125 self.send_header('ETag', etag) | 128 self.send_header('ETag', etag) |
126 self.send_header('Cache-Control', 'must-revalidate') | 129 self.send_header('Cache-Control', 'must-revalidate') |
127 | 130 |
128 return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) | 131 return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) |
129 | 132 |
130 def translate_path(self, path): | 133 def translate_path(self, path): |
131 # Parent translate_path() will strip away the query string and fragment | 134 # Parent translate_path() will strip away the query string and fragment |
132 # identifier, but also will prepend the cwd to the path. relpath() gives | 135 # identifier, but also will prepend the cwd to the path. relpath() gives |
133 # us the relative path back. | 136 # us the relative path back. |
134 normalized_path = os.path.relpath( | 137 normalized_path = os.path.relpath( |
135 SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path)) | 138 SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path)) |
136 | 139 |
137 for prefix, local_base_path in mappings: | 140 for prefix, local_base_path in mappings: |
138 if normalized_path.startswith(prefix): | 141 if normalized_path.startswith(prefix): |
139 return os.path.join(local_base_path, normalized_path[len(prefix):]) | 142 result = os.path.join(local_base_path, normalized_path[len(prefix):]) |
| 143 if os.path.isfile(result): |
| 144 gz_result = result + '.gz' |
| 145 if (not os.path.isfile(gz_result) or |
| 146 os.path.getmtime(gz_result) <= os.path.getmtime(result)): |
| 147 with open(result, 'rb') as f: |
| 148 with gzip.open(gz_result, 'wb') as zf: |
| 149 shutil.copyfileobj(f, zf) |
| 150 result = gz_result |
| 151 return result |
140 | 152 |
141 # This class is only used internally, and we're adding a catch-all '' | 153 # This class is only used internally, and we're adding a catch-all '' |
142 # prefix at the end of |mappings|. | 154 # prefix at the end of |mappings|. |
143 assert False | 155 assert False |
144 | 156 |
145 def guess_type(self, path): | 157 def guess_type(self, path): |
146 # This is needed so that Sky files without shebang can still run thanks to | 158 # This is needed so that Sky files without shebang can still run thanks to |
147 # content-type mappings. | 159 # content-type mappings. |
148 # TODO(ppi): drop this part once we can rely on the Sky files declaring | 160 # TODO(ppi): drop this part once we can rely on the Sky files declaring |
149 # correct shebang. | 161 # correct shebang. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 return httpd.server_address | 206 return httpd.server_address |
195 except socket.error as v: | 207 except socket.error as v: |
196 error_code = v[0] | 208 error_code = v[0] |
197 print 'Failed to start http server for %s on port %d: %s.' % ( | 209 print 'Failed to start http server for %s on port %d: %s.' % ( |
198 local_dir_path, host_port, os.strerror(error_code)) | 210 local_dir_path, host_port, os.strerror(error_code)) |
199 if error_code == errno.EADDRINUSE: | 211 if error_code == errno.EADDRINUSE: |
200 print (' Run `fuser %d/tcp` to find out which process is using the port.' | 212 print (' Run `fuser %d/tcp` to find out which process is using the port.' |
201 % host_port) | 213 % host_port) |
202 print '---' | 214 print '---' |
203 raise | 215 raise |
OLD | NEW |