Exemple #1
0
def test_update_cached_sync_token():
    test_sync_token = "syncToken1=val1;sn=6"
    header = {"Sync-Token": test_sync_token}
    request = HttpRequest("GET", "https://bing.com/")
    response = HttpResponse(request, None)
    response.headers = header
    pipeline_response = PipelineResponse(request, response, None)
    sync_token_policy = SyncTokenPolicy()
    sync_token_policy.on_response(None, pipeline_response)
    sync_token = sync_token_policy._sync_tokens['syncToken1']
    assert sync_token.token_id == 'syncToken1'
    assert sync_token.value == 'val1'
    assert sync_token.sequence_number == 6
    test_new_sync_token = "syncToken1=val2;sn=10"
    header["Sync-Token"] = test_new_sync_token
    response.headers = header
    pipeline_response = PipelineResponse(request, response, None)
    sync_token_policy.on_response(None, pipeline_response)
    sync_token = sync_token_policy._sync_tokens['syncToken1']
    assert sync_token.token_id == 'syncToken1'
    assert sync_token.value == 'val2'
    assert sync_token.sequence_number == 10
Exemple #2
0
    async def _send_request(self, http_request: HttpRequest,
                            **kwargs: Any) -> AsyncHttpResponse:
        """Runs the network request through the client's chained policies.

        :param http_request: The network request you want to make. Required.
        :type http_request: ~azure.core.pipeline.transport.HttpRequest
        :keyword bool stream: Whether the response payload will be streamed. Defaults to True.
        :return: The response of your network call. Does not do error handling on your response.
        :rtype: ~azure.core.pipeline.transport.AsyncHttpResponse
        """
        path_format_arguments = {
            'subscriptionId':
            self._serialize.url("self._config.subscription_id",
                                self._config.subscription_id, 'str'),
        }
        http_request.url = self._client.format_url(http_request.url,
                                                   **path_format_arguments)
        stream = kwargs.pop("stream", True)
        pipeline_response = await self._client._pipeline.run(http_request,
                                                             stream=stream,
                                                             **kwargs)
        return pipeline_response.http_response
Exemple #3
0
async def test_example_async_pipeline_client():

    url = "https://bing.com"

    # [START build_async_pipeline_client]
    from azure.core import AsyncPipelineClient
    from azure.core.configuration import Configuration
    from azure.core.pipeline.policies import AsyncRedirectPolicy, UserAgentPolicy
    from azure.core.pipeline.transport import HttpRequest

    # example configuration with some policies
    request = HttpRequest("GET", url)
    config = Configuration()
    config.user_agent_policy = UserAgentPolicy("myuseragent")
    config.redirect_policy = AsyncRedirectPolicy()

    async with AsyncPipelineClient(base_url=url, config=config) as client:
        response = await client._pipeline.run(request)
    # [END build_async_pipeline_client]

    assert client._pipeline._transport.session is None
    assert response.http_response.status_code == 200
    def _get_auth_code_request(self,
                               scopes,
                               code,
                               redirect_uri,
                               client_secret=None):
        # type: (Iterable[str], str, str, Optional[str]) -> HttpRequest
        data = {
            "client_id": self._client_id,
            "code": code,
            "grant_type": "authorization_code",
            "redirect_uri": redirect_uri,
            "scope": " ".join(scopes),
        }
        if client_secret:
            data["client_secret"] = client_secret

        request = HttpRequest(
            "POST",
            self._token_endpoint,
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            data=data)
        return request
Exemple #5
0
async def test_example_async_pipeline_client():

    url = "https://bing.com"

    # [START build_async_pipeline_client]
    from azure.core import AsyncPipelineClient
    from azure.core.pipeline.policies import AsyncRedirectPolicy, UserAgentPolicy
    from azure.core.pipeline.transport import HttpRequest

    # example policies
    request = HttpRequest("GET", url)
    policies = [
        UserAgentPolicy("myuseragent"),
        AsyncRedirectPolicy(),
    ]

    async with AsyncPipelineClient(base_url=url, policies=policies) as client:
        response = await client._pipeline.run(request)
    # [END build_async_pipeline_client]

    assert client._pipeline._transport.session is None
    assert isinstance(response.http_response.status_code, int)
def test_multipart_send_with_context():

    transport = mock.MagicMock(spec=HttpTransport)

    header_policy = HeadersPolicy({
        'x-ms-date': 'Thu, 14 Jun 2018 16:46:54 GMT'
    })

    req0 = HttpRequest("DELETE", "/container0/blob0")
    req1 = HttpRequest("DELETE", "/container1/blob1")

    request = HttpRequest("POST", "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(
        req0,
        req1,
        policies=[header_policy],
        boundary="batch_357de4f7-6d0b-4e02-8cd2-6361411a9525", # Fix it so test are deterministic
        headers={'Accept': 'application/json'}
    )

    with Pipeline(transport) as pipeline:
        pipeline.run(request)

    assert request.body == (
        b'--batch_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'Accept: application/json\r\n'
        b'\r\n'
        b'\r\n'
        b'--batch_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'Accept: application/json\r\n'
        b'\r\n'
        b'\r\n'
        b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n'
    )
Exemple #7
0
    def update_key(self, name, version, key_ops=None, attributes=None, tags=None, **kwargs):
        # type: (str, str, Optional[List[str]], Mapping[str, str], Mapping[str, str], Any) -> Key
        url = "/".join([self.vault_url, "keys", name, version])

        headers = {"Content-Type": "application/json; charset=utf-8", "x-ms-client-request-id": str(uuid.uuid1())}

        update_params = KeyUpdateParameters(key_ops=key_ops, key_attributes=attributes, tags=tags)
        body = self._serialize.body(update_params, "KeyUpdateParameters")
        request = HttpRequest("PATCH", url, headers=headers)
        request.set_json_body(body)
        request.format_parameters({"api-version": self.API_VERSION})
        response = self._pipeline.run(request, **kwargs).http_response
        if response.status_code != 200:
            raise HttpResponseError("Request failed with code {}: '{}'".format(response.status_code, response.text()))
        key = self._deserialize("Key", response)

        return key
 def post(
     self,
     url,  # type: str
     data=None,  # type: Optional[Mapping[str, str]]
     headers=None,  # type: Optional[Mapping[str, str]]
     params=None,  # type: Optional[Dict[str, str]]
     timeout=None,  # type: float
     verify=None,  # type: bool
     **kwargs  # type: Any
 ):
     # type: (...) -> MsalTransportResponse
     request = HttpRequest("POST", url, headers=headers)
     if params:
         request.format_parameters(params)
     if data:
         request.headers["Content-Type"] = "application/x-www-form-urlencoded"
         request.set_formdata_body(data)
     response = self._pipeline.run(
         request, stream=False, connection_timeout=timeout, connection_verify=verify, **kwargs
     )
     return MsalTransportResponse(response)
Exemple #9
0
async def test_preserves_options_and_headers():
    """After a challenge, the original request should be sent with its options and headers preserved.

    If a policy mutates the options or headers of the challenge (unauthorized) request, the options of the service
    request should be present when it is sent with authorization.
    """

    url = get_random_url()

    token = "**"

    async def get_token(*_, **__):
        return AccessToken(token, 0)

    credential = Mock(get_token=Mock(wraps=get_token))

    transport = async_validating_transport(
        requests=[Request()] * 2 +
        [Request(required_headers={"Authorization": "Bearer " + token})],
        responses=[
            mock_response(
                status_code=401,
                headers={
                    "WWW-Authenticate":
                    'Bearer authorization="{}", resource=foo'.format(url)
                })
        ] + [mock_response()] * 2,
    )
    challenge_policy = AsyncChallengeAuthPolicy(credential=credential)
    policies = get_policies_for_request_mutation_test(challenge_policy)
    pipeline = AsyncPipeline(policies=policies, transport=transport)

    response = await pipeline.run(HttpRequest("GET", url))

    # ensure the mock sans I/O policies were used
    for policy in policies:
        if hasattr(policy, "on_request"):
            assert policy.on_request.called, "mock policy wasn't invoked"
Exemple #10
0
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
async 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(spec=PipelineResponse)

    async def verify_request(request):
        assert request.http_request is expected_request
        return expected_response

    async def get_token(_):
        return ""

    fake_credential = Mock(get_token=get_token)
    policies = [
        AsyncBearerTokenCredentialPolicy(fake_credential, "scope"),
        Mock(spec=HTTPPolicy, send=verify_request),
    ]
    pipeline = AsyncPipeline(transport=Mock(spec=AsyncHttpTransport),
                             policies=policies)

    response = await pipeline.run(expected_request)

    assert response is expected_response
def test_response_deserialization():

    # Method + Url
    request = HttpRequest("DELETE", "/container0/blob0")
    body = (
        b'HTTP/1.1 202 Accepted\r\n'
        b'x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n'
        b'x-ms-version: 2018-11-09\r\n'
    )

    response = _deserialize_response(body, request)

    assert response.status_code == 202
    assert response.reason == "Accepted"
    assert response.headers == {
        'x-ms-request-id': '778fdc83-801e-0000-62ff-0334671e284f',
        'x-ms-version': '2018-11-09'
    }

    # Method + Url + Headers + Body
    request = HttpRequest(
        "DELETE",
        "/container0/blob0",
        headers={
            "x-ms-date": "Thu, 14 Jun 2018 16:46:54 GMT",
        },
    )
    request.set_bytes_body(b"I am groot")
    body = (
        b'HTTP/1.1 200 OK\r\n'
        b'x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n'
        b'x-ms-version: 2018-11-09\r\n'
        b'\r\n'
        b'I am groot'
    )

    response = _deserialize_response(body, request)

    assert isinstance(response.status_code, int)
    assert response.reason == "OK"
    assert response.headers == {
        'x-ms-request-id': '778fdc83-801e-0000-62ff-0334671e284f',
        'x-ms-version': '2018-11-09'
    }
    assert response.text() == "I am groot"
async def test_multipart_send():
    transport = MockAsyncHttpTransport()

    class RequestPolicy(object):
        async def on_request(self, request):
            # type: (PipelineRequest) -> None
            request.http_request.headers[
                'x-ms-date'] = 'Thu, 14 Jun 2018 16:46:54 GMT'

    req0 = HttpRequest("DELETE", "/container0/blob0")
    req1 = HttpRequest("DELETE", "/container1/blob1")

    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(
        req0,
        req1,
        policies=[RequestPolicy()],
        boundary=
        "batch_357de4f7-6d0b-4e02-8cd2-6361411a9525"  # Fix it so test are deterministic
    )

    async with AsyncPipeline(transport) as pipeline:
        await pipeline.run(request)

    assert request.body == (
        b'--batch_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'--batch_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'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n')
def test_distributed_tracing_policy_attributes():
    """Test policy with no other policy and happy path"""
    settings.tracing_implementation.set_value(FakeSpan)
    with FakeSpan(name="parent") as root_span:
        policy = DistributedTracingPolicy(
            tracing_attributes={'myattr': 'myvalue'})

        request = HttpRequest("GET", "http://127.0.0.1/temp?query=query")

        pipeline_request = PipelineRequest(request, PipelineContext(None))
        policy.on_request(pipeline_request)

        response = HttpResponse(request, None)
        response.headers = request.headers
        response.status_code = 202

        policy.on_response(
            pipeline_request,
            PipelineResponse(request, response, PipelineContext(None)))

    # Check on_response
    network_span = root_span.children[0]
    assert network_span.attributes.get("myattr") == "myvalue"
Exemple #15
0
    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)
            ])
async 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)

    async def verify_authorization_header(request):
        assert request.http_request.headers[
            "Authorization"] == "Bearer {}".format(expected_token.token)

    get_token_calls = 0

    async def get_token(_):
        nonlocal get_token_calls
        get_token_calls += 1
        return expected_token

    fake_credential = Mock(get_token=get_token)
    policies = [
        AsyncBearerTokenCredentialPolicy(fake_credential, "scope"),
        Mock(send=verify_authorization_header)
    ]
    pipeline = AsyncPipeline(transport=Mock(), policies=policies)

    await pipeline.run(HttpRequest("GET", "https://spam.eggs"), context=None)
    assert get_token_calls == 1
Exemple #17
0
    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)])

        get_token_future = asyncio.Future()
        get_token_future.set_result(token)
        async_credential = Mock(get_token=Mock(return_value=get_token_future))

        send_future = asyncio.Future()
        send_future.set_result(Mock())
        async_transport = Mock(send=Mock(return_value=send_future))
        self.async_pipeline = AsyncPipeline(
            async_transport,
            policies=[
                AsyncBearerTokenCredentialPolicy(credential=async_credential)
            ])
def _set_body(content: ContentType, data: dict, files: Any, json_body: Any,
              internal_request: _PipelineTransportHttpRequest) -> None:
    if data is not None and not isinstance(data, dict):
        content = data
        data = None
    if content is not None:
        _set_content_body(content, internal_request)
    elif json_body is not None:
        internal_request.set_json_body(json_body)
        _set_content_type_header("application/json", internal_request)
    elif files is not None:
        internal_request.set_formdata_body(files)
        # if you don't supply your content type, we'll create a boundary for you with multipart/form-data
        boundary = binascii.hexlify(os.urandom(16)).decode(
            "ascii")  # got logic from httpx, thanks httpx!
        # _set_content_type_header("multipart/form-data; boundary={}".format(boundary), internal_request)
    elif data:
        _set_content_type_header("application/x-www-form-urlencoded",
                                 internal_request)
        internal_request.set_formdata_body(data)
        # need to set twice because Content-Type is being popped in set_formdata_body
        # don't want to risk changing pipeline.transport, so doing twice here
        _set_content_type_header("application/x-www-form-urlencoded",
                                 internal_request)
Exemple #19
0
def test_bearer_policy_optionally_enforces_https():
    """HTTPS enforcement should be controlled by a keyword argument, and enabled by default"""

    def assert_option_popped(request, **kwargs):
        assert "enforce_https" not in kwargs, "BearerTokenCredentialPolicy didn't pop the 'enforce_https' option"

    credential = Mock(get_token=lambda *_, **__: AccessToken("***", 42))
    pipeline = Pipeline(
        transport=Mock(send=assert_option_popped), policies=[BearerTokenCredentialPolicy(credential, "scope")]
    )

    # by default and when enforce_https=True, the policy should raise when given an insecure request
    with pytest.raises(ServiceRequestError):
        pipeline.run(HttpRequest("GET", "http://not.secure"))
    with pytest.raises(ServiceRequestError):
        pipeline.run(HttpRequest("GET", "http://not.secure"), enforce_https=True)

    # when enforce_https=False, an insecure request should pass
    pipeline.run(HttpRequest("GET", "http://not.secure"), enforce_https=False)

    # https requests should always pass
    pipeline.run(HttpRequest("GET", "https://secure"), enforce_https=False)
    pipeline.run(HttpRequest("GET", "https://secure"), enforce_https=True)
    pipeline.run(HttpRequest("GET", "https://secure"))
async def test_recursive_multipart_receive():
    req0 = HttpRequest("DELETE", "/container0/blob0")
    internal_req0 = HttpRequest("DELETE", "/container0/blob0")
    req0.set_multipart_mixed(internal_req0)

    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(req0)

    class MockResponse(AsyncHttpResponse):
        def __init__(self, request, body, content_type):
            super(MockResponse, self).__init__(request, None)
            self._body = body
            self.content_type = content_type

        def body(self):
            return self._body

    internal_body_as_str = (
        "--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\r\n"
        "Content-Type: application/http\r\n"
        "Content-ID: 0\r\n"
        "\r\n"
        "HTTP/1.1 400 Accepted\r\n"
        "x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n"
        "x-ms-version: 2018-11-09\r\n"
        "\r\n"
        "--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed--")

    body_as_str = (
        "--batchresponse_8d5f5bcd-2cb5-44bb-91b5-e9a722e68cb6\r\n"
        "Content-Type: application/http\r\n"
        "Content-ID: 0\r\n"
        "\r\n"
        "HTTP/1.1 202 Accepted\r\n"
        "Content-Type: multipart/mixed; boundary=batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\r\n"
        "\r\n"
        "{}"
        "--batchresponse_8d5f5bcd-2cb5-44bb-91b5-e9a722e68cb6--"
    ).format(internal_body_as_str)

    response = MockResponse(
        request, body_as_str.encode('ascii'),
        "multipart/mixed; boundary=batchresponse_8d5f5bcd-2cb5-44bb-91b5-e9a722e68cb6"
    )

    parts = []
    async for part in response.parts():
        parts.append(part)

    assert len(parts) == 1

    res0 = parts[0]
    assert res0.status_code == 202

    internal_parts = []
    async for part in res0.parts():
        internal_parts.append(part)
    assert len(internal_parts) == 1

    internal_response0 = internal_parts[0]
    assert internal_response0.status_code == 400
async def test_multipart_receive():
    class MockResponse(AsyncHttpResponse):
        def __init__(self, request, body, content_type):
            super(MockResponse, self).__init__(request, None)
            self._body = body
            self.content_type = content_type

        def body(self):
            return self._body

    class ResponsePolicy(object):
        def on_response(self, request, response):
            # type: (PipelineRequest, PipelineResponse) -> None
            response.http_response.headers['x-ms-fun'] = 'true'

    class AsyncResponsePolicy(object):
        async def on_response(self, request, response):
            # type: (PipelineRequest, PipelineResponse) -> None
            response.http_response.headers['x-ms-async-fun'] = 'true'

    req0 = HttpRequest("DELETE", "/container0/blob0")
    req1 = HttpRequest("DELETE", "/container1/blob1")

    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(
        req0, req1, policies=[ResponsePolicy(),
                              AsyncResponsePolicy()])

    body_as_str = (
        "--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\r\n"
        "Content-Type: application/http\r\n"
        "Content-ID: 0\r\n"
        "\r\n"
        "HTTP/1.1 202 Accepted\r\n"
        "x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n"
        "x-ms-version: 2018-11-09\r\n"
        "\r\n"
        "--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\r\n"
        "Content-Type: application/http\r\n"
        "Content-ID: 2\r\n"
        "\r\n"
        "HTTP/1.1 404 The specified blob does not exist.\r\n"
        "x-ms-error-code: BlobNotFound\r\n"
        "x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e2852\r\n"
        "x-ms-version: 2018-11-09\r\n"
        "Content-Length: 216\r\n"
        "Content-Type: application/xml\r\n"
        "\r\n"
        '<?xml version="1.0" encoding="utf-8"?>\r\n'
        "<Error><Code>BlobNotFound</Code><Message>The specified blob does not exist.\r\n"
        "RequestId:778fdc83-801e-0000-62ff-0334671e2852\r\n"
        "Time:2018-06-14T16:46:54.6040685Z</Message></Error>\r\n"
        "--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed--")

    response = MockResponse(
        request, body_as_str.encode('ascii'),
        "multipart/mixed; boundary=batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed"
    )

    parts = []
    async for part in response.parts():
        parts.append(part)

    assert len(parts) == 2

    res0 = parts[0]
    assert res0.status_code == 202
    assert res0.headers['x-ms-fun'] == 'true'
    assert res0.headers['x-ms-async-fun'] == 'true'

    res1 = parts[1]
    assert res1.status_code == 404
    assert res1.headers['x-ms-fun'] == 'true'
    assert res1.headers['x-ms-async-fun'] == 'true'
Exemple #22
0
 async def do():
     request = HttpRequest("GET", "https://bing.com/")
     policies = [UserAgentPolicy("myusergant"), AsyncRedirectPolicy()]
     async with AsyncPipeline(TrioRequestsTransport(),
                              policies=policies) as pipeline:
         return await pipeline.run(request)
async def test_multipart_send():

    # transport = mock.MagicMock(spec=AsyncHttpTransport)
    # MagicMock support async cxt manager only after 3.8
    # https://github.com/python/cpython/pull/9296

    class MockAsyncHttpTransport(AsyncHttpTransport):
        async def __aenter__(self):
            return self

        async def __aexit__(self, *args):
            pass

        async def open(self):
            pass

        async def close(self):
            pass

        async def send(self, request, **kwargs):
            pass

    transport = MockAsyncHttpTransport()

    class RequestPolicy(object):
        async def on_request(self, request):
            # type: (PipelineRequest) -> None
            request.http_request.headers[
                'x-ms-date'] = 'Thu, 14 Jun 2018 16:46:54 GMT'

    req0 = HttpRequest("DELETE", "/container0/blob0")
    req1 = HttpRequest("DELETE", "/container1/blob1")

    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(
        req0,
        req1,
        policies=[RequestPolicy()],
        boundary=
        "batch_357de4f7-6d0b-4e02-8cd2-6361411a9525"  # Fix it so test are deterministic
    )

    async with AsyncPipeline(transport) as pipeline:
        await pipeline.run(request)

    assert request.body == (
        b'--batch_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'--batch_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'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n')
    def test_request_url_with_params_with_none(self):

        request = HttpRequest("GET", "/")
        request.url = "a/b/c?t=y"
        with pytest.raises(ValueError):
            request.format_parameters({"g": None})
async def test_multipart_receive_with_combination_changeset_last():

    changeset = HttpRequest(None, None)
    changeset.set_multipart_mixed(HttpRequest("DELETE", "/container1/blob1"),
                                  HttpRequest("DELETE", "/container2/blob2"))

    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(HttpRequest("DELETE", "/container0/blob0"),
                                changeset)

    body_as_bytes = (
        b'--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\r\n'
        b'Content-Type: application/http\r\n'
        b'Content-Transfer-Encoding: binary\r\n'
        b'Content-ID: 2\r\n'
        b'\r\n'
        b'HTTP/1.1 200\r\n'
        b'x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n'
        b'x-ms-version: 2018-11-09\r\n'
        b'\r\n'
        b'\r\n'
        b'--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed\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'HTTP/1.1 202\r\n'
        b'x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n'
        b'x-ms-version: 2018-11-09\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'HTTP/1.1 404\r\n'
        b'x-ms-request-id: 778fdc83-801e-0000-62ff-0334671e284f\r\n'
        b'x-ms-version: 2018-11-09\r\n'
        b'\r\n'
        b'\r\n'
        b'--changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n'
        b'\r\n'
        b'--batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed--\r\n')

    response = MockResponse(
        request, body_as_bytes,
        "multipart/mixed; boundary=batchresponse_66925647-d0cb-4109-b6d3-28efe3e1e5ed"
    )

    parts = []
    async for part in response.parts():
        parts.append(part)
    assert len(parts) == 3
    assert parts[0].status_code == 200
    assert parts[1].status_code == 202
    assert parts[2].status_code == 404
async def test_multipart_send_with_combination_changeset_middle():
    transport = MockAsyncHttpTransport()
    changeset = HttpRequest(None, None)
    changeset.set_multipart_mixed(
        HttpRequest("DELETE", "/container1/blob1"),
        boundary="changeset_357de4f7-6d0b-4e02-8cd2-6361411a9525")
    request = HttpRequest("POST",
                          "http://account.blob.core.windows.net/?comp=batch")
    request.set_multipart_mixed(
        HttpRequest("DELETE", "/container0/blob0"),
        changeset,
        HttpRequest("DELETE", "/container2/blob2"),
        boundary="batch_357de4f7-6d0b-4e02-8cd2-6361411a9525")

    async with AsyncPipeline(transport) as pipeline:
        await pipeline.run(request)

    assert request.body == (
        b'--batch_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'\r\n'
        b'\r\n'
        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: 1\r\n'
        b'\r\n'
        b'DELETE /container1/blob1 HTTP/1.1\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'
        b'Content-Type: application/http\r\n'
        b'Content-Transfer-Encoding: binary\r\n'
        b'Content-ID: 2\r\n'
        b'\r\n'
        b'DELETE /container2/blob2 HTTP/1.1\r\n'
        b'\r\n'
        b'\r\n'
        b'--batch_357de4f7-6d0b-4e02-8cd2-6361411a9525--\r\n')
 def test_repr(self):
     request = HttpRequest("GET", "hello.com")
     assert repr(request) == "<HttpRequest [GET], url: 'hello.com'>"
    async def _batch_send(
        self,
        entities,  # type: List[TableEntity]
        *reqs: "HttpRequest",
        **kwargs
    ):
        """Given a series of request, do a Storage batch call."""
        # Pop it here, so requests doesn't feel bad about additional kwarg
        raise_on_any_failure = kwargs.pop("raise_on_any_failure", True)
        policies = [StorageHeadersPolicy()]

        changeset = HttpRequest("POST", None)
        changeset.set_multipart_mixed(
            *reqs, policies=policies, boundary="changeset_{}".format(uuid4())
        )
        request = self._client._client.post(  # pylint: disable=protected-access
            url="https://{}/$batch".format(self._primary_hostname),
            headers={
                "x-ms-version": self.api_version,
                "DataServiceVersion": "3.0",
                "MaxDataServiceVersion": "3.0;NetFx",
            },
        )
        request.set_multipart_mixed(
            changeset,
            policies=policies,
            enforce_https=False,
            boundary="batch_{}".format(uuid4()),
        )

        pipeline_response = await self._pipeline.run(request, **kwargs)
        response = pipeline_response.http_response

        if response.status_code == 403:
            raise ClientAuthenticationError(
                message="There was an error authenticating with the service",
                response=response,
            )
        if response.status_code == 404:
            raise ResourceNotFoundError(
                message="The resource could not be found", response=response
            )
        if response.status_code != 202:
            raise BatchErrorException(
                message="There is a failure in the batch operation.",
                response=response,
                parts=None,
            )

        parts_iter = response.parts()
        parts = []
        async for p in parts_iter:
            parts.append(p)
        transaction_result = BatchTransactionResult(reqs, parts, entities)
        if raise_on_any_failure:
            if any(p for p in parts if not 200 <= p.status_code < 300):

                if any(p for p in parts if p.status_code == 404):
                    raise ResourceNotFoundError(
                        message="The resource could not be found", response=response
                    )

                raise BatchErrorException(
                    message="There is a failure in the batch operation.",
                    response=response,
                    parts=parts,
                )
        return transaction_result
Exemple #29
0
    def test_request_xml(self):
        request = HttpRequest("GET", "/")
        data = ET.Element("root")
        request.set_xml_body(data)

        assert request.data == b"<?xml version='1.0' encoding='utf8'?>\n<root />"
Exemple #30
0
        # HttpXTransport does not support stream data:
        #   File "lib\site-packages\httpx\_content_streams.py", line 404, in encode
        #     raise TypeError(f"Unexpected type for 'data', {type(data)!r}")
        # TypeError: Unexpected type for 'data', <class '__main__.LargeStream'>
        #
        # start = time.perf_counter()
        # req = HttpRequest("PUT", url, data=LargeStream(size), headers=headers)
        # resp = pipelinex.run(req)
        # stop = time.perf_counter()
        # duration = stop - start
        # mbps = ((size / duration) * 8) / (1024 * 1024)
        # print(f'[PipelineX, stream] Put {size:,} bytes in {duration:.2f} seconds ({mbps:.2f} Mbps), Response={resp.http_response.status_code}')

        start = time.perf_counter()
        req = HttpRequest("PUT", url, data=array, headers=headers)
        resp = pipelinex.run(req)
        stop = time.perf_counter()
        duration = stop - start
        mbps = ((size / duration) * 8) / (1024 * 1024)
        print(
            f'[PipelineX, array] Put {size:,} bytes in {duration:.2f} seconds ({mbps:.2f} Mbps), Response={resp.http_response.status_code}'
        )

        start = time.perf_counter()
        req = HttpRequest("PUT", url, data=LargeStream(size), headers=headers)
        resp = pipeline.run(req)
        stop = time.perf_counter()
        duration = stop - start
        mbps = ((size / duration) * 8) / (1024 * 1024)
        print(