def _play_responses(cassette, request, vcr_request, client, kwargs): history = [] allow_redirects = kwargs.get("allow_redirects", True) vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(request, vcr_response) while allow_redirects and 300 <= response.status_code <= 399: next_url = response.headers.get("location") if not next_url: break # Even though 302 shouldn't change request's method, browsers like Chromium # change method to GET for compatibility method = request.method if response.status_code not in [302, 303 ] else "GET" vcr_request = VcrRequest(method, next_url, None, dict(response.headers)) vcr_request = cassette.find_requests_with_most_matches( vcr_request)[0][0] history.append(response) # add cookies from response to session cookie store client.cookies.extract_cookies(response) vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(vcr_request, vcr_response, history) return response
def _play_responses(cassette, request, vcr_request, client, kwargs): history = [] allow_redirects = kwargs.get( HTTPX_REDIRECT_PARAM.name, HTTPX_REDIRECT_PARAM.default, ) vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(request, vcr_response) while allow_redirects and 300 <= response.status_code <= 399: next_url = response.headers.get("location") if not next_url: break vcr_request = VcrRequest("GET", next_url, None, dict(response.headers)) vcr_request = cassette.find_requests_with_most_matches( vcr_request)[0][0] history.append(response) # add cookies from response to session cookie store client.cookies.extract_cookies(response) vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(vcr_request, vcr_response, history) return response
async def wrapped_request(method, url, **kwargs): '''Actually wrap asks.request, storing cassettes as needed. Heavily based on the VCR stub for aiohttp; see https://github.com /kevin1024/vcrpy/blob/master/vcr/stubs/aiohttp_stubs.py ''' # IMPORTANT NOTE! We're ignoring the other headers that asks adds into # the request here, so the server response could potentially change if # asks modifies its header prep logic in a new version and we # subsequently upgrade to that newer asks version. Fixing this is not # simple, so I'm punting on it here. We're also ignoring several # potentially-important but tricky things like authentication headers, # cookies, etc, but ghibli doesn't use any of them, so... headers = kwargs.get('headers') # Query params params = kwargs.get('params') # Possible request bodies. Unlike asks-added headers and auth, this # is pretty trivial to raise on, and much more likely to be # accidentally used down the road data = kwargs.get('data') json_data = kwargs.get('json') if data or json_data: raise NotImplementedError() url_with_query = f'{url}?{urllib.parse.urlencode(params)}' vcr_request = VcrRequest(method, url_with_query, None, headers) if cassette.can_play_response_for(vcr_request): # Logging has semantics assigned to %s so don't use format strings! # We want to preserve the difference between the log message and # the interpolated values. VCR source misbehaves here. vcr_logger.info( 'Playing response for %s from cassette', vcr_request) response = vcr_play_responses(cassette, vcr_request) # Note: this is where we'd need to handle redirects return response elif cassette.write_protected and cassette.filter_request(vcr_request): raise vcr.errors.CannotOverwriteExistingCassetteException( cassette=cassette, failed_request=vcr_request) else: vcr_logger.info( '%s not in cassette, performing real request', vcr_request) response = await real_request(method, url, **kwargs) await vcr_record_responses(cassette, vcr_request, response) return response
def _make_vcr_request(httpx_request: httpx.Request, **_kwargs: Any) -> VcrRequest: body = _handle_special_formats(httpx_request.read()) if isinstance(body, bytes): partially_decoded = body.decode("utf-8", "ignore") if "Content-Type: application/octet-stream" in partially_decoded: partially_decoded = re.sub( r"Content-Type: application/octet-stream.*--\s*", "Content-Type: application/octet-stream<omitted> --", partially_decoded, flags=re.DOTALL, ) body = partially_decoded uri = str(httpx_request.url) headers = dict(httpx_request.headers) return VcrRequest(httpx_request.method, uri, body, headers)
def _play_responses(cassette, request, vcr_request, client): history = [] vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(request, vcr_response) while 300 <= response.status_code <= 399: next_url = response.headers.get("location") if not next_url: break vcr_request = VcrRequest("GET", next_url, None, dict(response.headers)) vcr_request = cassette.find_requests_with_most_matches( vcr_request)[0][0] history.append(response) # add cookies from response to session cookie store client.cookies.extract_cookies(response) vcr_response = cassette.play_response(vcr_request) response = _from_serialized_response(vcr_request, vcr_response, history) return response
def _make_vcr_request(httpx_request, **kwargs): body = httpx_request.read().decode("utf-8") uri = str(httpx_request.url) headers = dict(httpx_request.headers) return VcrRequest(httpx_request.method, uri, body, headers)