def auth_flow( self, request: httpx.Request ) -> Generator[httpx.Request, httpx.Response, None]: """ Add x-amz-date, x-amz-content-sha256 and Authorization headers to the request. """ date = datetime.datetime.utcnow() scope = f"{date.strftime('%Y%m%d')}/{self.region}/{self.service}/aws4_request" signing_key = generate_key(self.secret_key, self.region, self.service, date.strftime("%Y%m%d")) request.headers["x-amz-date"] = date.strftime("%Y%m%dT%H%M%SZ") # encode body and generate body hash request.headers["x-amz-content-sha256"] = hashlib.sha256( request.read()).hexdigest() if self.security_token: request.headers["x-amz-security-token"] = self.security_token cano_headers, signed_headers = self._get_canonical_headers( request, self.include_headers) cano_req = self._get_canonical_request(request, cano_headers, signed_headers) sig_string = self._get_sig_string(request, cano_req, scope) sig_string = sig_string.encode("utf-8") signature = hmac.new(signing_key, sig_string, hashlib.sha256).hexdigest() auth_str = "AWS4-HMAC-SHA256 " auth_str += f"Credential={self.access_id}/{scope}, " auth_str += f"SignedHeaders={signed_headers}, " auth_str += f"Signature={signature}" request.headers["Authorization"] = auth_str yield request
def send( self, request: Request, verify: VerifyTypes = None, cert: CertTypes = None, timeout: TimeoutTypes = None, ) -> Response: return Response(200, content=request.read())
def mock_post(request: httpx.Request, response): url = str(request.url).split('?')[0] if url not in post_apis or request.method != 'POST': return None data = json.loads(request.read().decode()) res = post(url=request.url, json=data, headers=request.headers) response.content = json.loads(res.content.decode('utf-8')) response.status_code = res.status_code return response
def delete_token(self, request: Request) -> Response: assert self.token, "Must obtain GitHub token first" assert request.headers["Accept"] == "application/json" basic_auth_raw = f"{self.config.client_id}:{self.config.client_secret}" basic_auth = base64.b64encode(basic_auth_raw.encode()).decode() assert request.headers["Authorization"] == f"Basic {basic_auth}" assert json.loads(request.read().decode()) == { "access_token": self.token } return Response(status_code=204)
def post_token(self, request: Request) -> Response: assert self.config.oidc assert request.headers["Accept"] == "application/json" assert parse_qs(request.read().decode()) == { "grant_type": ["authorization_code"], "client_id": [self.config.oidc.client_id], "client_secret": [self.config.oidc.client_secret], "code": [self.code], "redirect_uri": [self.config.oidc.redirect_url], } return Response(200, json={ "id_token": self.token.encoded, "token_type": "Bearer" })
def callback(request: Request, ext: Dict[str, Any]) -> Response: assert self.config.github assert str(request.url) == GitHubProvider._TOKEN_URL assert request.method == "POST" assert request.headers["Accept"] == "application/json" assert parse_qs(request.read().decode()) == { "client_id": [self.config.github.client_id], "client_secret": [self.config.github.client_secret], "code": [code], "state": [ANY], } return to_response( json={ "access_token": token, "scope": ",".join(GitHubProvider._SCOPES), "token_type": "bearer", })
def post_token(self, request: Request) -> Response: assert request.headers["Accept"] == "application/json" assert parse_qs(request.read().decode()) == { "client_id": [self.config.client_id], "client_secret": [self.config.client_secret], "code": [self.code], "state": [ANY], } self.token = str(uuid.uuid4()) return Response( 200, json={ "access_token": self.token, "scope": ",".join(GitHubProvider._SCOPES), "token_type": "bearer", }, )
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 send( self, request: Request, verify: VerifyTypes = None, cert: CertTypes = None, timeout: TimeoutTypes = None, ) -> Response: if request.url.path == "/streaming_response": return Response(200, content=streaming_body(), request=request) elif request.url.path == "/echo_request_body": content = request.read() return Response(200, content=content, request=request) elif request.url.path == "/echo_request_body_streaming": content = b"".join([part for part in request.stream()]) return Response(200, content=content, request=request) else: body = json.dumps({"hello": "world"}).encode() return Response(200, content=body, request=request)
def callback(request: Request, ext: Dict[str, Any]) -> Response: assert self.config.oidc if str(request.url) != self.config.oidc.token_url: assert request.method == "GET" return to_response(status_code=404) assert request.method == "POST" assert request.headers["Accept"] == "application/json" assert parse_qs(request.read().decode()) == { "grant_type": ["authorization_code"], "client_id": [self.config.oidc.client_id], "client_secret": [self.config.oidc.client_secret], "code": [code], "redirect_uri": [self.config.oidc.redirect_url], } return to_response(json={ "id_token": token.encoded, "token_type": "Bearer" })
def custom_matcher(self, request: httpx.Request, *args, **kwargs): """Match URLs to sample files.""" port_suffix = "" if request.url.port == 8080: port_suffix = "-8080" try: if request.url.path == STATUS_URL: content = get_sample_content( "{receiver}-formMainZone_MainZoneXmlStatus{port}" ".xml".format(receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == STATUS_Z2_URL: content = get_sample_content( "{receiver}-formZone2_Zone2XmlStatus{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == STATUS_Z3_URL: content = get_sample_content( "{receiver}-formZone3_Zone3XmlStatus{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == MAINZONE_URL: content = get_sample_content( "{receiver}-formMainZone_MainZoneXml{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == DEVICEINFO_URL: content = get_sample_content( "{receiver}-Deviceinfo{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == NETAUDIOSTATUS_URL: content = get_sample_content( "{receiver}-formNetAudio_StatusXml{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == TUNERSTATUS_URL: content = get_sample_content( "{receiver}-formTuner_TunerXml{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == HDTUNERSTATUS_URL: content = get_sample_content( "{receiver}-formTuner_HdXml{port}.xml".format( receiver=self.testing_receiver, port=port_suffix)) elif request.url.path == APPCOMMAND_URL: content_str = request.read().decode("utf-8") if "GetFriendlyName" in content_str: ep_suffix = "-setup" else: ep_suffix = "-update" content = get_sample_content( "{receiver}-AppCommand{port}{ep}.xml".format( receiver=self.testing_receiver, port=port_suffix, ep=ep_suffix)) elif request.url.path in [DESCRIPTION_URL1, DESCRIPTION_URL2]: content = get_sample_content("AVR-X1600H_upnp.xml") else: content = "DATA" except FileNotFoundError: content = "Error 403: Forbidden\nAccess Forbidden" status_code = 403 else: status_code = 200 resp = to_response(status_code=status_code, data=content) return resp
def _content_match(self, request: httpx.Request) -> bool: if self.content is None: return True return request.read() == self.content
def parse(self, request: httpx.Request) -> Any: content = request.read() return content
def entity_created_response( request: httpx.Request, req_id: str) -> typing.Dict[str, typing.Union[str, typing.List[str]]]: """Simulate response for creating an entity.""" content = json.loads(request.read()) response: typing.Dict[str, typing.Union[str, typing.List[str]]] = { "requestId": req_id, "proof": "/api/v1/proofs/" + req_id, } if content["_type"] == "IssueIdentityRequest": response["resources"] = ["/api/v1/identities/" + content["identityId"]] elif content["_type"] == "DefineAssetTypeRequest": response["resources"] = [ "/api/v1/asset-types/" + content["assetTypeId"] ] elif content["_type"] == "CreateAssetRequest": response["resources"] = [ "/".join(( "/api/v1/asset-types", content["assetTypeId"], "assets", content["assetId"], )) ] elif content["_type"] == "CreateIdentityClaimsRequest": response["resources"] = [ "/".join(( "/api/v1/identities", content["subjectId"], "claims", claim, )) for claim in [*content["claims"]] ] elif content["_type"] == "CreateIdentityEndorsementsRequest": response["resources"] = [ "/".join(( "/api/v1/identities", content["subjectId"], "claims", claim, "endorsements", content["endorserId"], )) for claim in [*content["endorsements"]] ] elif content["_type"] == "CreateAssetTypeClaimsRequest": response["resources"] = [ "/".join(( "/api/v1/asset-types", content["subjectId"], "claims", claim, )) for claim in [*content["claims"]] ] elif content["_type"] == "CreateAssetTypeEndorsementsRequest": response["resources"] = [ "/".join(( "/api/v1/asset-types", content["subjectId"], "claims", claim, "endorsements", content["endorserId"], )) for claim in [*content["endorsements"]] ] elif content["_type"] in ["CreateAssetClaimsRequest"]: response["resources"] = [ "/".join(( "/api/v1/asset-types", content["subjectTypeId"], "assets", content["subjectId"], "claims", claim, )) for claim in [*content["claims"]] ] elif content["_type"] in ["CreateAssetEndorsementsRequest"]: response["resources"] = [ "/".join(( "/api/v1/asset-types", content["subjectTypeId"], "assets", content["subjectId"], "claims", claim, "endorsements", content["endorserId"], )) for claim in [*content["endorsements"]] ] else: raise NotImplementedError("mocked service - unknown _type: " + content["_type"]) return response