async def handle_redirect(self, request: Request, response: Response, stream: bool, follow_redirects: bool, max_redirects: int, decode: bool, validate_ssl, headers: dict) -> Response: """ :param headers: :param validate_ssl: :param decode: :param max_redirects: :param follow_redirects: :param stream: :param response: :param request: :return: """ if max_redirects == 0: raise TooManyRedirects try: location = response.headers['location'] except KeyError: raise Exception('HTTP redirect response missing location header.') if not location.startswith('http'): if not location.startswith('/'): location = '/' + location location = request.url.netloc + location redirect_url = parse_url(location.encode()) headers['Host'] = redirect_url.host return await self.request( url=redirect_url, method='GET', stream=stream, follow_redirects=follow_redirects, max_redirects=(max_redirects - 1), decode=decode, validate_ssl=validate_ssl, headers=headers, origin=response )
async def request(self, url: str = '/', stream: bool = None, follow_redirects: bool = None, max_redirects: int = 30, decode: bool = True, ssl=None, timeout=ClientDefaults.TIMEOUT, retries: Union[RetryStrategy, int] = None, headers: dict = None, method: str = 'GET', query: dict = None, json: dict = None, ignore_prefix: bool = False, body=None, form: dict = None) -> Response: # Asserting the user is not using conflicting params. if sum([body is not None, json is not None, form is not None]) > 1: raise ValueError('You cannot set body, json or form together. You must pick one and only one.') # Handling default parameters. stream = stream if stream is not None else self.stream follow_redirects = follow_redirects if follow_redirects is not None else self.follow_redirects max_redirects = max_redirects if max_redirects is not None else self.max_redirects decode = decode if decode else self.decode ssl = ssl if ssl is not None else self.ssl retries = retries.clone() if retries is not None else RetryStrategy() request_headers = self._headers.copy() if headers: request_headers.update(headers) # Constructing the URL. url = self.build_url(prefix=self.prefix if not ignore_prefix else b'', url=url.encode(URL_ENCODING), query=query) parsed_url = parse_url(url) if json is not None: body = json_module.dumps(json).encode('utf-8') request_headers['Content-Type'] = 'application/json' if form is not None: boundary = str(uuid.uuid4()).replace('-', '').encode() body = MultipartEncoder(delimiter=boundary, params=form) request_headers['Content-Type'] = f'multipart/form-data; boundary={boundary.decode()}' while True: try: task = self._engine.request( url=parsed_url, data=body, method=method, stream=stream, follow_redirects=follow_redirects, max_redirects=max_redirects, decode=decode, validate_ssl=ssl, headers=request_headers) if timeout: response = await asyncio.wait_for(task, timeout) else: response = await task if retries.responses.get(response.status_code, 0) > 0: retries.responses[response.status_code] -= 1 continue return response except (ConnectionError, TimeoutError) as error: if retries.network_failures.get(method, 0) > 0: retries.network_failures[method] -= 1 continue raise error