| 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 |