OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2012 Google Inc. All Rights Reserved. | 2 # Copyright 2012 Google Inc. All Rights Reserved. |
3 # | 3 # |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
7 # | 7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # | 9 # |
10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 else: | 193 else: |
194 httplib.HTTPSConnection.__init__(self, host=host, port=port) | 194 httplib.HTTPSConnection.__init__(self, host=host, port=port) |
195 | 195 |
196 | 196 |
197 class RealHttpFetch(object): | 197 class RealHttpFetch(object): |
198 | 198 |
199 def __init__(self, real_dns_lookup): | 199 def __init__(self, real_dns_lookup): |
200 """Initialize RealHttpFetch. | 200 """Initialize RealHttpFetch. |
201 | 201 |
202 Args: | 202 Args: |
203 real_dns_lookup: a function that resolves a host to an IP. | 203 real_dns_lookup: a function that resolves a host to an IP. RealHttpFetch |
| 204 will resolve host name to the IP before making fetching request if this |
| 205 is not None. |
204 """ | 206 """ |
205 self._real_dns_lookup = real_dns_lookup | 207 self._real_dns_lookup = real_dns_lookup |
206 | 208 |
207 @staticmethod | 209 @staticmethod |
208 def _GetHeaderNameValue(header): | 210 def _GetHeaderNameValue(header): |
209 """Parse the header line and return a name/value tuple. | 211 """Parse the header line and return a name/value tuple. |
210 | 212 |
211 Args: | 213 Args: |
212 header: a string for a header such as "Content-Length: 314". | 214 header: a string for a header such as "Content-Length: 314". |
213 Returns: | 215 Returns: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 A DetailedHTTPSConnection or DetailedHTTPConnection instance. | 290 A DetailedHTTPSConnection or DetailedHTTPConnection instance. |
289 """ | 291 """ |
290 connection_host = request_host | 292 connection_host = request_host |
291 connection_port = request_port | 293 connection_port = request_port |
292 system_proxy = self._get_system_proxy(is_ssl) | 294 system_proxy = self._get_system_proxy(is_ssl) |
293 if system_proxy: | 295 if system_proxy: |
294 connection_host = system_proxy.host | 296 connection_host = system_proxy.host |
295 connection_port = system_proxy.port | 297 connection_port = system_proxy.port |
296 | 298 |
297 # Use an IP address because WPR may override DNS settings. | 299 # Use an IP address because WPR may override DNS settings. |
298 connection_ip = self._real_dns_lookup(connection_host) | 300 if self._real_dns_lookup: |
299 if not connection_ip: | 301 connection_ip = self._real_dns_lookup(connection_host) |
300 logging.critical('Unable to find host ip for name: %s', connection_host) | 302 if not connection_ip: |
301 return None | 303 logging.critical( |
| 304 'Unable to find IP for host name: %s', connection_host) |
| 305 return None |
| 306 connection_host = connection_ip |
302 | 307 |
303 if is_ssl: | 308 if is_ssl: |
304 connection = DetailedHTTPSConnection(connection_ip, connection_port) | 309 connection = DetailedHTTPSConnection(connection_host, connection_port) |
305 if system_proxy: | 310 if system_proxy: |
306 connection.set_tunnel(request_host, request_port) | 311 connection.set_tunnel(request_host, request_port) |
307 else: | 312 else: |
308 connection = DetailedHTTPConnection(connection_ip, connection_port) | 313 connection = DetailedHTTPConnection(connection_host, connection_port) |
309 return connection | 314 return connection |
310 | 315 |
311 def __call__(self, request): | 316 def __call__(self, request): |
312 """Fetch an HTTP request. | 317 """Fetch an HTTP request. |
313 | 318 |
314 Args: | 319 Args: |
315 request: an ArchivedHttpRequest | 320 request: an ArchivedHttpRequest |
316 Returns: | 321 Returns: |
317 an ArchivedHttpResponse | 322 an ArchivedHttpResponse |
318 """ | 323 """ |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 retries -= 1 | 359 retries -= 1 |
355 logging.warning('Retrying fetch %s: %s', request, repr(e)) | 360 logging.warning('Retrying fetch %s: %s', request, repr(e)) |
356 continue | 361 continue |
357 logging.critical('Could not fetch %s: %s', request, repr(e)) | 362 logging.critical('Could not fetch %s: %s', request, repr(e)) |
358 return None | 363 return None |
359 | 364 |
360 | 365 |
361 class RecordHttpArchiveFetch(object): | 366 class RecordHttpArchiveFetch(object): |
362 """Make real HTTP fetches and save responses in the given HttpArchive.""" | 367 """Make real HTTP fetches and save responses in the given HttpArchive.""" |
363 | 368 |
364 def __init__(self, http_archive, real_dns_lookup, inject_script): | 369 def __init__(self, http_archive, inject_script): |
365 """Initialize RecordHttpArchiveFetch. | 370 """Initialize RecordHttpArchiveFetch. |
366 | 371 |
367 Args: | 372 Args: |
368 http_archive: an instance of a HttpArchive | 373 http_archive: an instance of a HttpArchive |
369 real_dns_lookup: a function that resolves a host to an IP. | |
370 inject_script: script string to inject in all pages | 374 inject_script: script string to inject in all pages |
371 """ | 375 """ |
372 self.http_archive = http_archive | 376 self.http_archive = http_archive |
373 self.real_http_fetch = RealHttpFetch(real_dns_lookup) | 377 # Do not resolve host name to IP when recording to avoid SSL3 handshake |
| 378 # failure. |
| 379 # See https://github.com/chromium/web-page-replay/issues/73 for details. |
| 380 self.real_http_fetch = RealHttpFetch(real_dns_lookup=None) |
374 self.inject_script = inject_script | 381 self.inject_script = inject_script |
375 | 382 |
376 def __call__(self, request): | 383 def __call__(self, request): |
377 """Fetch the request and return the response. | 384 """Fetch the request and return the response. |
378 | 385 |
379 Args: | 386 Args: |
380 request: an ArchivedHttpRequest. | 387 request: an ArchivedHttpRequest. |
381 Returns: | 388 Returns: |
382 an ArchivedHttpResponse | 389 an ArchivedHttpResponse |
383 """ | 390 """ |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 http_archive: an instance of a HttpArchive | 478 http_archive: an instance of a HttpArchive |
472 real_dns_lookup: a function that resolves a host to an IP. | 479 real_dns_lookup: a function that resolves a host to an IP. |
473 inject_script: script string to inject in all pages. | 480 inject_script: script string to inject in all pages. |
474 use_diff_on_unknown_requests: If True, log unknown requests | 481 use_diff_on_unknown_requests: If True, log unknown requests |
475 with a diff to requests that look similar. | 482 with a diff to requests that look similar. |
476 use_record_mode: If True, start in server in record mode. | 483 use_record_mode: If True, start in server in record mode. |
477 use_closest_match: If True, on replay mode, serve the closest match | 484 use_closest_match: If True, on replay mode, serve the closest match |
478 in the archive instead of giving a 404. | 485 in the archive instead of giving a 404. |
479 """ | 486 """ |
480 self.http_archive = http_archive | 487 self.http_archive = http_archive |
481 self.record_fetch = RecordHttpArchiveFetch( | 488 self.record_fetch = RecordHttpArchiveFetch(http_archive, inject_script) |
482 http_archive, real_dns_lookup, inject_script) | |
483 self.replay_fetch = ReplayHttpArchiveFetch( | 489 self.replay_fetch = ReplayHttpArchiveFetch( |
484 http_archive, real_dns_lookup, inject_script, | 490 http_archive, real_dns_lookup, inject_script, |
485 use_diff_on_unknown_requests, use_closest_match, scramble_images) | 491 use_diff_on_unknown_requests, use_closest_match, scramble_images) |
486 if use_record_mode: | 492 if use_record_mode: |
487 self.SetRecordMode() | 493 self.SetRecordMode() |
488 else: | 494 else: |
489 self.SetReplayMode() | 495 self.SetReplayMode() |
490 | 496 |
491 def SetRecordMode(self): | 497 def SetRecordMode(self): |
492 self.fetch = self.record_fetch | 498 self.fetch = self.record_fetch |
493 self.is_record_mode = True | 499 self.is_record_mode = True |
494 | 500 |
495 def SetReplayMode(self): | 501 def SetReplayMode(self): |
496 self.fetch = self.replay_fetch | 502 self.fetch = self.replay_fetch |
497 self.is_record_mode = False | 503 self.is_record_mode = False |
498 | 504 |
499 def __call__(self, *args, **kwargs): | 505 def __call__(self, *args, **kwargs): |
500 """Forward calls to Replay/Record fetch functions depending on mode.""" | 506 """Forward calls to Replay/Record fetch functions depending on mode.""" |
501 return self.fetch(*args, **kwargs) | 507 return self.fetch(*args, **kwargs) |
OLD | NEW |