OLD | NEW |
---|---|
1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2016 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 """The request data track. | 5 """The request data track. |
6 | 6 |
7 When executed, parses a JSON dump of DevTools messages. | 7 When executed, parses a JSON dump of DevTools messages. |
8 """ | 8 """ |
9 | 9 |
10 import bisect | 10 import bisect |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 for (k, v) in data_dict.items(): | 172 for (k, v) in data_dict.items(): |
173 setattr(result, k, v) | 173 setattr(result, k, v) |
174 if not result.response_headers: | 174 if not result.response_headers: |
175 result.response_headers = {} | 175 result.response_headers = {} |
176 if result.timing: | 176 if result.timing: |
177 result.timing = Timing(*result.timing) | 177 result.timing = Timing(*result.timing) |
178 else: | 178 else: |
179 result.timing = TimingFromDict({'requestTime': result.timestamp}) | 179 result.timing = TimingFromDict({'requestTime': result.timestamp}) |
180 return result | 180 return result |
181 | 181 |
182 """Gets the value of a HTTP response header. | |
Benoit L
2016/02/18 11:01:27
docstrings go below the function name, not above.
| |
183 | |
184 Does a case-insensitive search for the header name in the HTTP response | |
185 headers, in order to support servers that use a wrong capitalization. | |
186 """ | |
187 def GetHTTPResponseHeader(self, header_name): | |
188 small_caps_name = header_name.lower() | |
Benoit L
2016/02/18 11:01:27
nit: lower_case_name?
| |
189 result = None | |
190 for name, value in self.response_headers.iteritems(): | |
191 if name.lower() == small_caps_name: | |
192 result = value | |
193 break | |
194 return result | |
195 | |
182 def GetContentType(self): | 196 def GetContentType(self): |
183 """Returns the content type, or None.""" | 197 """Returns the content type, or None.""" |
198 # Check for redirects. Use the "Location" header, because the HTTP status is | |
199 # not reliable. | |
200 if self.GetHTTPResponseHeader('Location') is not None: | |
201 return 'redirect' | |
202 | |
203 # Check if the response is empty. | |
204 if (self.GetHTTPResponseHeader('Content-Length') == '0' or | |
205 self.status == 204): | |
206 return 'ping' | |
207 | |
184 if self.mime_type: | 208 if self.mime_type: |
185 return self.mime_type | 209 return self.mime_type |
186 | 210 |
187 # Case-insensitive search because servers sometimes use a wrong | 211 content_type = self.GetHTTPResponseHeader('Content-Type') |
188 # capitalization. | |
189 content_type = None | |
190 for header, value in self.response_headers.iteritems(): | |
191 if header.lower() == 'content-type': | |
192 content_type = value | |
193 break | |
194 | |
195 if not content_type or ';' not in content_type: | 212 if not content_type or ';' not in content_type: |
196 return content_type | 213 return content_type |
197 else: | 214 else: |
198 return content_type[:content_type.index(';')] | 215 return content_type[:content_type.index(';')] |
199 | 216 |
200 def IsDataRequest(self): | 217 def IsDataRequest(self): |
201 return self.protocol == 'data' | 218 return self.protocol == 'data' |
202 | 219 |
203 def MaxAge(self): | 220 def MaxAge(self): |
204 """Returns the max-age of a resource, or -1.""" | 221 """Returns the max-age of a resource, or -1.""" |
205 # TODO(lizeb): Handle the "Expires" header as well. | 222 # TODO(lizeb): Handle the "Expires" header as well. |
206 cache_control = {} | 223 cache_control = {} |
207 if not self.response_headers: | 224 if not self.response_headers: |
208 return -1 | 225 return -1 |
209 | 226 |
210 # Case-insensitive search because servers sometimes use a wrong | 227 cache_control_str = self.GetHTTPResponseHeader('Cache-Control') |
211 # capitalization. | |
212 cache_control_str = None | |
213 for header, value in self.response_headers.iteritems(): | |
214 if header.lower() == 'cache-control': | |
215 cache_control_str = value | |
216 break | |
217 | |
218 if cache_control_str is not None: | 228 if cache_control_str is not None: |
219 directives = [s.strip() for s in cache_control_str.split(',')] | 229 directives = [s.strip() for s in cache_control_str.split(',')] |
220 for directive in directives: | 230 for directive in directives: |
221 parts = [s.strip() for s in directive.split('=')] | 231 parts = [s.strip() for s in directive.split('=')] |
222 if len(parts) == 1: | 232 if len(parts) == 1: |
223 cache_control[parts[0]] = True | 233 cache_control[parts[0]] = True |
224 else: | 234 else: |
225 cache_control[parts[0]] = parts[1] | 235 cache_control[parts[0]] = parts[1] |
226 if (u'no-store' in cache_control | 236 if (u'no-store' in cache_control |
227 or u'no-cache' in cache_control | 237 or u'no-cache' in cache_control |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 | 564 |
555 | 565 |
556 if __name__ == '__main__': | 566 if __name__ == '__main__': |
557 import json | 567 import json |
558 import sys | 568 import sys |
559 events = json.load(open(sys.argv[1], 'r')) | 569 events = json.load(open(sys.argv[1], 'r')) |
560 request_track = RequestTrack(None) | 570 request_track = RequestTrack(None) |
561 for event in events: | 571 for event in events: |
562 event_method = event['method'] | 572 event_method = event['method'] |
563 request_track.Handle(event_method, event) | 573 request_track.Handle(event_method, event) |
OLD | NEW |