def __init__( self, auth_url, # type: str config=None, # type: Optional[Configuration] policies=None, # type: Optional[Iterable[HTTPPolicy]] transport=None, # type: Optional[HttpTransport] **kwargs # type: Any ): # type: (...) -> None config = config or self._create_config(**kwargs) policies = policies or [ ContentDecodePolicy(), config.retry_policy, config.logging_policy, DistributedTracingPolicy(), ] if not transport: transport = RequestsTransport(**kwargs) self._pipeline = Pipeline(transport=transport, policies=policies) super(AuthnClient, self).__init__(auth_url, **kwargs)
class AuthnClient(AuthnClientBase): """ Synchronous authentication client. :param str auth_url: :param config: Optional configuration for the HTTP pipeline. :type config: :class:`azure.core.configuration` :param policies: Optional policies for the HTTP pipeline. :type policies: :param transport: Optional HTTP transport. :type transport: """ def __init__(self, auth_url, config=None, policies=None, transport=None, **kwargs): # type: (str, Optional[Configuration], Optional[Iterable[HTTPPolicy]], Optional[HttpTransport], Mapping[str, Any]) -> None config = config or self._create_config(**kwargs) policies = policies or [ ContentDecodePolicy(), config.retry_policy, config.logging_policy, DistributedTracingPolicy() ] if not transport: transport = RequestsTransport(**kwargs) self._pipeline = Pipeline(transport=transport, policies=policies) super(AuthnClient, self).__init__(auth_url, **kwargs) def request_token(self, scopes, method="POST", headers=None, form_data=None, params=None, **kwargs): # type: (Iterable[str], Optional[str], Optional[Mapping[str, str]], Optional[Mapping[str, str]], Optional[Dict[str, str]], Any) -> AccessToken request = self._prepare_request(method, headers=headers, form_data=form_data, params=params) request_time = int(time.time()) response = self._pipeline.run(request, stream=False, **kwargs) token = self._deserialize_and_cache_token(response, scopes, request_time) return token @staticmethod def _create_config(**kwargs): # type: (Mapping[str, Any]) -> Configuration config = Configuration(**kwargs) config.logging_policy = NetworkTraceLoggingPolicy(**kwargs) config.retry_policy = RetryPolicy(**kwargs) return config
def test_tuple_timeout(caplog): transport = RequestsTransport() request = HttpRequest("GET", "https://www.bing.com") with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): with Pipeline(transport) as pipeline: pipeline.run(request, connection_timeout=(100, 100)) assert "Tuple timeout setting is deprecated" in caplog.text
def test_policy(): # ensure the test starts with an empty cache HttpChallengeCache.clear() expected_scope = "https://challenge.resource/.default" expected_token = "expected_token" challenge = Mock( status_code=401, headers={ "WWW-Authenticate": 'Bearer authorization="https://login.authority.net/tenant", resource={}'.format( expected_scope ) }, ) success = Mock(status_code=200) data = {"spam": "eggs"} responses = (r for r in (challenge, success)) def send(request): response = next(responses) if response is challenge: # this is the first request assert not request.body assert request.headers["Content-Length"] == "0" elif response is success: # this is the second request assert request.body == data assert expected_token in request.headers["Authorization"] return response def get_token(*scopes): assert len(scopes) is 1 assert scopes[0] == expected_scope return AccessToken(expected_token, 0) credential = Mock(get_token=Mock(wraps=get_token)) pipeline = Pipeline(policies=[ChallengeAuthPolicy(credential=credential)], transport=Mock(send=send)) pipeline.run(HttpRequest("POST", "https://azure.service", data=data)) assert credential.get_token.call_count == 1
def test_tuple_timeout(caplog, port): transport = RequestsTransport() request = HttpRequest("GET", "http://localhost:{}/basic/string".format(port)) with caplog.at_level(logging.WARNING, logger="azure.core.pipeline.transport"): with Pipeline(transport) as pipeline: pipeline.run(request, connection_timeout=(100, 100)) assert "Tuple timeout setting is deprecated" in caplog.text
def test_basic_options_requests(self): request = HttpRequest("OPTIONS", "https://httpbin.org") policies = [ UserAgentPolicy("myusergant"), RedirectPolicy() ] with Pipeline(RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request) assert pipeline._transport.session is None assert response.http_response.status_code == 200
def test_multipart_send_with_one_changeset(): transport = mock.MagicMock(spec=HttpTransport) header_policy = HeadersPolicy( {'x-ms-date': 'Thu, 14 Jun 2018 16:46:54 GMT'}) requests = [ HttpRequest("DELETE", "/container0/blob0"), HttpRequest("DELETE", "/container1/blob1") ] changeset = HttpRequest(None, None) changeset.set_multipart_mixed( *requests, policies=[header_policy], boundary="changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525") request = HttpRequest("POST", "http://account.blob.core.windows.net/?comp=batch") request.set_multipart_mixed( changeset, boundary="batch_357de4f7-6d0b-4e02-8cd2-6361411a9525", ) with Pipeline(transport) as pipeline: pipeline.run(request) assert request.body == ( b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525\r\n' b'Content-Type: multipart/mixed; boundary=changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525\r\n' b'\r\n' b'--changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525\r\n' b'Content-Type: application/http\r\n' b'Content-Transfer-Encoding: binary\r\n' b'Content-ID: 0\r\n' b'\r\n' b'DELETE /container0/blob0 HTTP/1.1\r\n' b'x-ms-date: Thu, 14 Jun 2018 16:46:54 GMT\r\n' b'\r\n' b'\r\n' b'--changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525\r\n' b'Content-Type: application/http\r\n' b'Content-Transfer-Encoding: binary\r\n' b'Content-ID: 1\r\n' b'\r\n' b'DELETE /container1/blob1 HTTP/1.1\r\n' b'x-ms-date: Thu, 14 Jun 2018 16:46:54 GMT\r\n' b'\r\n' b'\r\n' b'--changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n' b'\r\n' b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n')
def test_requests_socket_timeout(self): conf = Configuration() request = HttpRequest("GET", "https://bing.com") policies = [UserAgentPolicy("myusergant"), RedirectPolicy()] # Sometimes this will raise a read timeout, sometimes a socket timeout depending on timing. # Either way, the error should always be wrapped as an AzureError to ensure it's caught # by the retry policy. with pytest.raises(AzureError): with Pipeline(RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request, connection_timeout=0.000001, read_timeout=0.000001)
def _build_pipeline(self, config=None, policies=None, transport=None, **kwargs): config = config or self._create_config(**kwargs) policies = policies or [ ContentDecodePolicy(), config.retry_policy, config.logging_policy ] if not transport: transport = RequestsTransport(**kwargs) return Pipeline(transport=transport, policies=policies)
def test_bearer_policy_calls_on_challenge(http_request): """BearerTokenCredentialPolicy should call its on_challenge method when it receives an authentication challenge""" class TestPolicy(BearerTokenCredentialPolicy): called = False def on_challenge(self, request, challenge): self.__class__.called = True return False credential = Mock(get_token=Mock( return_value=AccessToken("***", int(time.time()) + 3600))) policies = [TestPolicy(credential, "scope")] response = Mock(status_code=401, headers={"WWW-Authenticate": 'Basic realm="localhost"'}) transport = Mock(send=Mock(return_value=response)) pipeline = Pipeline(transport=transport, policies=policies) pipeline.run(http_request("GET", "https://localhost")) assert TestPolicy.called
async def test_response_stream_download_trio(get_old_response_trio, get_new_response_trio): old_response = await get_old_response_trio(stream=True) new_response = await get_new_response_trio(stream=True) pipeline = Pipeline(TrioRequestsTransport()) old_string = b"".join([ part async for part in old_response.stream_download(pipeline=pipeline) ]) new_string = b"".join([ part async for part in new_response.stream_download(pipeline=pipeline) ]) assert old_string == new_string == b"Hello, world!"
def test_basic_options_requests(port): request = HttpRequest("OPTIONS", "http://localhost:{}/basic/string".format(port)) policies = [ UserAgentPolicy("myusergant"), RedirectPolicy() ] with Pipeline(RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request) assert pipeline._transport.session is None assert isinstance(response.http_response.status_code, int)
def test_bearer_policy_adds_header(http_request): """The bearer token policy should add a header containing a token from its credential""" # 2524608000 == 01/01/2050 @ 12:00am (UTC) expected_token = AccessToken("expected_token", 2524608000) def verify_authorization_header(request): assert request.http_request.headers[ "Authorization"] == "Bearer {}".format(expected_token.token) return Mock() fake_credential = Mock(get_token=Mock(return_value=expected_token)) policies = [ BearerTokenCredentialPolicy(fake_credential, "scope"), Mock(send=verify_authorization_header) ] pipeline = Pipeline(transport=Mock(), policies=policies) pipeline.run(http_request("GET", "https://spam.eggs")) assert fake_credential.get_token.call_count == 1 pipeline.run(http_request("GET", "https://spam.eggs")) # Didn't need a new token assert fake_credential.get_token.call_count == 1
def get_blob_client( self, container, # type: Union[ContainerProperties, str] blob, # type: Union[BlobProperties, str] snapshot=None # type: Optional[Union[Dict[str, Any], str]] ): # type: (...) -> BlobClient """Get a client to interact with the specified blob. The blob need not already exist. :param container: The container that the blob is in. This can either be the name of the container, or an instance of ContainerProperties. :type container: str or ~azure.storage.blob.ContainerProperties :param blob: The blob with which to interact. This can either be the name of the blob, or an instance of BlobProperties. :type blob: str or ~azure.storage.blob.BlobProperties :param snapshot: The optional blob snapshot on which to operate. This can either be the ID of the snapshot, or a dictionary output returned by :func:`~azure.storage.blob.BlobClient.create_snapshot()`. :type snapshot: str or dict(str, Any) :returns: A BlobClient. :rtype: ~azure.storage.blob.BlobClient .. admonition:: Example: .. literalinclude:: ../samples/blob_samples_service.py :start-after: [START bsc_get_blob_client] :end-before: [END bsc_get_blob_client] :language: python :dedent: 12 :caption: Getting the blob client to interact with a specific blob. """ try: container_name = container.name except AttributeError: container_name = container try: blob_name = blob.name except AttributeError: blob_name = blob _pipeline = Pipeline( transport=TransportWrapper(self._pipeline._transport), # pylint: disable = protected-access policies=self._pipeline._impl_policies # pylint: disable = protected-access ) return BlobClient( # type: ignore self.url, container_name=container_name, blob_name=blob_name, snapshot=snapshot, credential=self.credential, api_version=self.api_version, _configuration=self._config, _pipeline=_pipeline, _location_mode=self._location_mode, _hosts=self._hosts, require_encryption=self.require_encryption, key_encryption_key=self.key_encryption_key, key_resolver_function=self.key_resolver_function)
def test_bearer_policy_adds_header(): """The bearer token policy should add a header containing a token from its credential""" expected_token = AccessToken("expected_token", 0) def verify_authorization_header(request): assert request.http_request.headers["Authorization"] == "Bearer {}".format(expected_token.token) fake_credential = Mock(get_token=Mock(return_value=expected_token)) policies = [BearerTokenCredentialPolicy(fake_credential, "scope"), Mock(send=verify_authorization_header)] Pipeline(transport=Mock(), policies=policies).run(HttpRequest("GET", "https://spam.eggs")) assert fake_credential.get_token.call_count == 1
def test_basic_requests(port, http_request): conf = Configuration() request = http_request("GET", "http://localhost:{}/basic/string".format(port)) policies = [UserAgentPolicy("myusergant"), RedirectPolicy()] with Pipeline(RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request) if is_rest(request): assert is_rest(response.http_response) assert pipeline._transport.session is None assert isinstance(response.http_response.status_code, int)
def test_example_requests(): request = HttpRequest("GET", "https://bing.com") config = Configuration() policies = [UserAgentPolicy("myuseragent"), RedirectPolicy()] # [START requests] from azure.core.pipeline.transport import RequestsTransport with Pipeline(transport=RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request) # [END requests] assert pipeline._transport.session is None assert response.http_response.status_code == 200
def _create_appconfig_pipeline(self): policies = [ self.config.headers_policy, self.config.user_agent_policy, self.config.logging_policy, # HTTP request/response log AppConfigRequestsCredentialsPolicy(self.config.credentials), DistributedTracingPolicy(), ] return Pipeline( RequestsTransport(configuration=self.config), policies # Send HTTP request using requests )
def test_basic_requests(self): conf = Configuration() request = HttpRequest("GET", "https://bing.com") policies = [ UserAgentPolicy("myusergant"), RedirectPolicy() ] with Pipeline(RequestsTransport(), policies=policies) as pipeline: response = pipeline.run(request) assert pipeline._transport.session is None assert response.http_response.status_code == 200
def __init__(self, configuration=None, **kwargs): config = configuration or FooServiceClient.create_config(**kwargs) transport = kwargs.get('transport', RequestsTransport(**kwargs)) policies = [ config.user_agent_policy, config.headers_policy, config.authentication_policy, ContentDecodePolicy(), config.redirect_policy, config.retry_policy, config.logging_policy, ] self._pipeline = Pipeline(transport, policies=policies)
class MockClient: @distributed_trace def __init__(self, policies=None, assert_current_span=False): time.sleep(0.001) self.request = HttpRequest("GET", "https://bing.com") if policies is None: policies = [] policies.append(mock.Mock(spec=HTTPPolicy, send=self.verify_request)) self.policies = policies self.transport = mock.Mock(spec=HttpTransport) self.pipeline = Pipeline(self.transport, policies=policies) self.expected_response = mock.Mock(spec=PipelineResponse) self.assert_current_span = assert_current_span def verify_request(self, request): if self.assert_current_span: assert execution_context.get_current_span() is not None return self.expected_response @distributed_trace_async async def make_request(self, numb_times, **kwargs): time.sleep(0.001) if numb_times < 1: return None response = self.pipeline.run(self.request, **kwargs) await self.get_foo(merge_span=True) kwargs['merge_span'] = True await self.make_request(numb_times - 1, **kwargs) return response @distributed_trace_async async def merge_span_method(self): return await self.get_foo(merge_span=True) @distributed_trace_async async def no_merge_span_method(self): return await self.get_foo() @distributed_trace_async async def get_foo(self): time.sleep(0.001) return 5 @distributed_trace_async(name_of_span="different name") async def check_name_is_different(self): time.sleep(0.001) @distributed_trace_async async def raising_exception(self): raise ValueError("Something went horribly wrong here")
def test_bearer_policy_send(): """The bearer token policy should invoke the next policy's send method and return the result""" expected_request = HttpRequest("GET", "https://spam.eggs") expected_response = Mock() def verify_request(request): assert request.http_request is expected_request return expected_response fake_credential = Mock(get_token=lambda _: AccessToken("", 0)) policies = [BearerTokenCredentialPolicy(fake_credential, "scope"), Mock(send=verify_request)] response = Pipeline(transport=Mock(), policies=policies).run(expected_request) assert response is expected_response
def test_basic_requests_separate_session(self): session = requests.Session() request = HttpRequest("GET", "https://bing.com") policies = [UserAgentPolicy("myusergant"), RedirectPolicy()] transport = RequestsTransport(session=session, session_owner=False) with Pipeline(transport, policies=policies) as pipeline: response = pipeline.run(request) assert transport.session assert isinstance(response.http_response.status_code, int) transport.close() assert transport.session transport.session.close()
def get_queue_client( self, queue, # type: Union[QueueProperties, str] **kwargs # type: Any ): # type: (...) -> QueueClient """Get a client to interact with the specified queue. The queue need not already exist. :param queue: The queue. This can either be the name of the queue, or an instance of QueueProperties. :type queue: str or ~azure.storage.queue.QueueProperties :returns: A :class:`~azure.storage.queue.QueueClient` object. :rtype: ~azure.storage.queue.QueueClient .. admonition:: Example: .. literalinclude:: ../samples/queue_samples_service.py :start-after: [START get_queue_client] :end-before: [END get_queue_client] :language: python :dedent: 8 :caption: Get the queue client. """ try: queue_name = queue.name except AttributeError: queue_name = queue _pipeline = Pipeline( transport=TransportWrapper(self._pipeline._transport ), # pylint: disable = protected-access policies=self._pipeline. _impl_policies # pylint: disable = protected-access ) return QueueClient(self.url, queue_name=queue_name, credential=self.credential, key_resolver_function=self.key_resolver_function, require_encryption=self.require_encryption, key_encryption_key=self.key_encryption_key, api_version=self.api_version, _pipeline=_pipeline, _configuration=self._config, _location_mode=self._location_mode, _hosts=self._hosts, **kwargs)
def get_directory_client(self, file_system, # type: Union[FileSystemProperties, str] directory # type: Union[DirectoryProperties, str] ): # type: (...) -> DataLakeDirectoryClient """Get a client to interact with the specified directory. The directory need not already exist. :param file_system: The file system that the directory is in. This can either be the name of the file system, or an instance of FileSystemProperties. :type file_system: str or ~azure.storage.filedatalake.FileSystemProperties :param directory: The directory with which to interact. This can either be the name of the directory, or an instance of DirectoryProperties. :type directory: str or ~azure.storage.filedatalake.DirectoryProperties :returns: A DataLakeDirectoryClient. :rtype: ~azure.storage.filedatalake.DataLakeDirectoryClient .. admonition:: Example: .. literalinclude:: ../samples/datalake_samples_service.py :start-after: [START get_directory_client_from_service_client] :end-before: [END get_directory_client_from_service_client] :language: python :dedent: 8 :caption: Getting the directory client to interact with a specific directory. """ try: file_system_name = file_system.name except AttributeError: file_system_name = file_system try: directory_name = directory.name except AttributeError: directory_name = directory _pipeline = Pipeline( transport=TransportWrapper(self._pipeline._transport), # pylint: disable = protected-access policies=self._pipeline._impl_policies # pylint: disable = protected-access ) return DataLakeDirectoryClient(self.url, file_system_name, directory_name=directory_name, credential=self._raw_credential, api_version=self.api_version, _configuration=self._config, _pipeline=_pipeline, _hosts=self._hosts, require_encryption=self.require_encryption, key_encryption_key=self.key_encryption_key, key_resolver_function=self.key_resolver_function )
def _create_pipeline(**kwargs): """Creates and returns a PipelineClient configured for the provided base_url and kwargs""" transport = kwargs.get("transport", RequestsTransport(**kwargs)) policies = [ kwargs.get("user_agent_policy", UserAgentPolicy(_constants.USER_AGENT, **kwargs)), kwargs.get("headers_policy", HeadersPolicy(**kwargs)), kwargs.get("authentication_policy"), kwargs.get("retry_policy", RetryPolicy(**kwargs)), kwargs.get("redirect_policy", RedirectPolicy(**kwargs)), kwargs.get("logging_policy", NetworkTraceLoggingPolicy(**kwargs)), kwargs.get("proxy_policy", ProxyPolicy(**kwargs)), ] return Pipeline(policies=policies, transport=transport)
def test_connection_error_response(): class MockTransport(HttpTransport): def __init__(self): self._count = 0 def __exit__(self, exc_type, exc_val, exc_tb): pass def close(self): pass def open(self): pass def send(self, request, **kwargs): request = HttpRequest('GET', 'http://127.0.0.1/') response = HttpResponse(request, None) response.status_code = 200 return response def next(self): self.__next__() def __next__(self): if self._count == 0: self._count += 1 raise requests.exceptions.ConnectionError def stream(self, chunk_size, decode_content=False): if self._count == 0: self._count += 1 raise requests.exceptions.ConnectionError while True: yield b"test" class MockInternalResponse(): def __init__(self): self.raw = MockTransport() def close(self): pass http_request = HttpRequest('GET', 'http://127.0.0.1/') pipeline = Pipeline(MockTransport()) http_response = HttpResponse(http_request, None) http_response.internal_response = MockInternalResponse() stream = StreamDownloadGenerator(pipeline, http_response, decompress=False) with mock.patch('time.sleep', return_value=None): with pytest.raises(requests.exceptions.ConnectionError): stream.__next__()
def __init__(self, arguments): super().__init__(arguments) token = AccessToken("**", int(time.time() + 3600)) self.request = HttpRequest("GET", "https://localhost") credential = Mock(get_token=Mock(return_value=token)) self.pipeline = Pipeline( transport=Mock(), policies=[BearerTokenCredentialPolicy(credential=credential)]) completed_future = asyncio.Future() completed_future.set_result(token) async_credential = Mock(get_token=Mock(return_value=completed_future)) # returning a token is okay because the policy does nothing with the transport's response async_transport = Mock(send=Mock(return_value=completed_future)) self.async_pipeline = AsyncPipeline( async_transport, policies=[ AsyncBearerTokenCredentialPolicy(credential=async_credential) ])
def test_retry_on_429(): class MockTransport(HttpTransport): def __init__(self): self._count = 0 def __exit__(self, exc_type, exc_val, exc_tb): pass def close(self): pass def open(self): pass def send(self, request, **kwargs): # type: (PipelineRequest, Any) -> PipelineResponse self._count += 1 response = HttpResponse(request, None) response.status_code = 429 return response http_request = HttpRequest('GET', 'http://127.0.0.1/') http_retry = RetryPolicy(retry_total = 1) transport = MockTransport() pipeline = Pipeline(transport, [http_retry]) pipeline.run(http_request) assert transport._count == 2
def __init__( self, config=None, # type: Optional[Configuration] policies=None, # type: Optional[PolicyListType] transport=None, # type: Optional[HttpTransport] **kwargs # type: Any ): # type: (...) -> None config = config or self._create_config(**kwargs) policies = policies or [ ContentDecodePolicy(), config.user_agent_policy, config.proxy_policy, config.retry_policy, config.logging_policy, DistributedTracingPolicy(**kwargs), HttpLoggingPolicy(**kwargs), ] if not transport: transport = RequestsTransport(**kwargs) self._pipeline = Pipeline(transport=transport, policies=policies) # type: Pipeline super(AuthnClient, self).__init__(**kwargs)