| 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 gzip |
| 10 import hashlib | 10 import hashlib |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 """ | 67 """ |
| 68 | 68 |
| 69 def __init__(self, *args, **kwargs): | 69 def __init__(self, *args, **kwargs): |
| 70 self.etag = None | 70 self.etag = None |
| 71 SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) | 71 SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) |
| 72 | 72 |
| 73 def get_etag(self): | 73 def get_etag(self): |
| 74 if self.etag: | 74 if self.etag: |
| 75 return self.etag | 75 return self.etag |
| 76 | 76 |
| 77 path = self.translate_path(self.path) | 77 path = self.translate_path(self.path, False) |
| 78 if not os.path.isfile(path): | 78 if not os.path.isfile(path): |
| 79 return None | 79 return None |
| 80 | 80 |
| 81 sha256 = hashlib.sha256() | 81 sha256 = hashlib.sha256() |
| 82 BLOCKSIZE = 65536 | 82 BLOCKSIZE = 65536 |
| 83 with open(path, 'rb') as hashed: | 83 with open(path, 'rb') as hashed: |
| 84 buf = hashed.read(BLOCKSIZE) | 84 buf = hashed.read(BLOCKSIZE) |
| 85 while len(buf) > 0: | 85 while len(buf) > 0: |
| 86 sha256.update(buf) | 86 sha256.update(buf) |
| 87 buf = hashed.read(BLOCKSIZE) | 87 buf = hashed.read(BLOCKSIZE) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 123 |
| 124 if os.path.isfile(path): | 124 if os.path.isfile(path): |
| 125 self.send_header('Content-Encoding', 'gzip') | 125 self.send_header('Content-Encoding', 'gzip') |
| 126 etag = self.get_etag() | 126 etag = self.get_etag() |
| 127 if etag: | 127 if etag: |
| 128 self.send_header('ETag', etag) | 128 self.send_header('ETag', etag) |
| 129 self.send_header('Cache-Control', 'must-revalidate') | 129 self.send_header('Cache-Control', 'must-revalidate') |
| 130 | 130 |
| 131 return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) | 131 return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) |
| 132 | 132 |
| 133 def translate_path(self, path): | 133 # pylint: disable=W0221 |
| 134 def translate_path(self, path, gzipped=True): |
| 134 # Parent translate_path() will strip away the query string and fragment | 135 # Parent translate_path() will strip away the query string and fragment |
| 135 # identifier, but also will prepend the cwd to the path. relpath() gives | 136 # identifier, but also will prepend the cwd to the path. relpath() gives |
| 136 # us the relative path back. | 137 # us the relative path back. |
| 137 normalized_path = os.path.relpath( | 138 normalized_path = os.path.relpath( |
| 138 SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path)) | 139 SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path)) |
| 139 | 140 |
| 140 for prefix, local_base_path in mappings: | 141 for prefix, local_base_path in mappings: |
| 141 if normalized_path.startswith(prefix): | 142 if normalized_path.startswith(prefix): |
| 142 result = os.path.join(local_base_path, normalized_path[len(prefix):]) | 143 result = os.path.join(local_base_path, normalized_path[len(prefix):]) |
| 143 if os.path.isfile(result): | 144 if os.path.isfile(result): |
| 144 gz_result = result + '.gz' | 145 if gzipped: |
| 145 if (not os.path.isfile(gz_result) or | 146 gz_result = result + '.gz' |
| 146 os.path.getmtime(gz_result) <= os.path.getmtime(result)): | 147 if (not os.path.isfile(gz_result) or |
| 147 with open(result, 'rb') as f: | 148 os.path.getmtime(gz_result) <= os.path.getmtime(result)): |
| 148 with gzip.open(gz_result, 'wb') as zf: | 149 with open(result, 'rb') as f: |
| 149 shutil.copyfileobj(f, zf) | 150 with gzip.open(gz_result, 'wb') as zf: |
| 150 result = gz_result | 151 shutil.copyfileobj(f, zf) |
| 152 result = gz_result |
| 151 return result | 153 return result |
| 152 | 154 |
| 153 # This class is only used internally, and we're adding a catch-all '' | 155 # This class is only used internally, and we're adding a catch-all '' |
| 154 # prefix at the end of |mappings|. | 156 # prefix at the end of |mappings|. |
| 155 assert False | 157 assert False |
| 156 | 158 |
| 157 def guess_type(self, path): | 159 def guess_type(self, path): |
| 158 # This is needed so that exploded Sky apps without shebang can still run | 160 # This is needed so that exploded Sky apps without shebang can still run |
| 159 # thanks to content-type mappings. | 161 # thanks to content-type mappings. |
| 160 # TODO(ppi): drop this part once we can rely on the Sky files declaring | 162 # TODO(ppi): drop this part once we can rely on the Sky files declaring |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 return httpd.server_address | 206 return httpd.server_address |
| 205 except socket.error as v: | 207 except socket.error as v: |
| 206 error_code = v[0] | 208 error_code = v[0] |
| 207 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.' % ( |
| 208 local_dir_path, host_port, os.strerror(error_code)) | 210 local_dir_path, host_port, os.strerror(error_code)) |
| 209 if error_code == errno.EADDRINUSE: | 211 if error_code == errno.EADDRINUSE: |
| 210 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.' |
| 211 % host_port) | 213 % host_port) |
| 212 print '---' | 214 print '---' |
| 213 raise | 215 raise |
| OLD | NEW |