예제 #1
0
def _make_request():
    """Make mocked request to get token."""
    return PipelineRequest(HttpRequest("CredentialWrapper", "https://fakeurl"),
                           PipelineContext(None))
예제 #2
0
def test_http_logger_operation_level():
    class MockHandler(logging.Handler):
        def __init__(self):
            super(MockHandler, self).__init__()
            self.messages = []

        def reset(self):
            self.messages = []

        def emit(self, record):
            self.messages.append(record)

    mock_handler = MockHandler()

    logger = logging.getLogger("testlogger")
    logger.addHandler(mock_handler)
    logger.setLevel(logging.DEBUG)

    policy = HttpLoggingPolicy()
    kwargs = {'logger': logger}

    universal_request = HttpRequest('GET', 'http://127.0.0.1/')
    http_response = HttpResponse(universal_request, None)
    http_response.status_code = 202
    request = PipelineRequest(universal_request,
                              PipelineContext(None, **kwargs))

    # Basics

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    assert all(m.levelname == 'INFO' for m in mock_handler.messages)
    assert len(mock_handler.messages) == 5
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'

    mock_handler.reset()

    # Let's make this request a failure, retried twice

    request = PipelineRequest(universal_request,
                              PipelineContext(None, **kwargs))

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    assert all(m.levelname == 'INFO' for m in mock_handler.messages)
    assert len(mock_handler.messages) == 10
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'

    mock_handler.reset()
예제 #3
0
def test_no_log(mock_http_logger):
    universal_request = HttpRequest('GET', 'http://127.0.0.1/')
    request = PipelineRequest(universal_request, PipelineContext(None))
    http_logger = NetworkTraceLoggingPolicy()
    response = PipelineResponse(request, HttpResponse(universal_request, None),
                                request.context)

    # By default, no log handler for HTTP
    http_logger.on_request(request)
    mock_http_logger.debug.assert_not_called()
    http_logger.on_response(request, response)
    mock_http_logger.debug.assert_not_called()
    mock_http_logger.reset_mock()

    # I can enable it per request
    request.context.options['logging_enable'] = True
    http_logger.on_request(request)
    assert mock_http_logger.debug.call_count >= 1
    mock_http_logger.reset_mock()
    request.context.options['logging_enable'] = True
    http_logger.on_response(request, response)
    assert mock_http_logger.debug.call_count >= 1
    mock_http_logger.reset_mock()

    # I can enable it per request (bool value should be honored)
    request.context.options['logging_enable'] = False
    http_logger.on_request(request)
    mock_http_logger.debug.assert_not_called()
    request.context.options['logging_enable'] = False
    http_logger.on_response(request, response)
    mock_http_logger.debug.assert_not_called()
    mock_http_logger.reset_mock()

    # I can enable it globally
    request.context.options = {}
    http_logger.enable_http_logger = True
    http_logger.on_request(request)
    assert mock_http_logger.debug.call_count >= 1
    http_logger.on_response(request, response)
    assert mock_http_logger.debug.call_count >= 1
    mock_http_logger.reset_mock()

    # I can enable it globally and override it locally
    http_logger.enable_http_logger = True
    request.context.options['logging_enable'] = False
    http_logger.on_request(request)
    mock_http_logger.debug.assert_not_called()
    response.context['logging_enable'] = False
    http_logger.on_response(request, response)
    mock_http_logger.debug.assert_not_called()
    mock_http_logger.reset_mock()

    # Let's make this request a failure, retried twice
    request.context.options['logging_enable'] = True
    http_logger.on_request(request)
    http_logger.on_response(request, response)

    first_count = mock_http_logger.debug.call_count
    assert first_count >= 1

    http_logger.on_request(request)
    http_logger.on_response(request, response)

    second_count = mock_http_logger.debug.call_count
    assert second_count == first_count * 2
예제 #4
0
def test_http_logger():
    class MockHandler(logging.Handler):
        def __init__(self):
            super(MockHandler, self).__init__()
            self.messages = []

        def reset(self):
            self.messages = []

        def emit(self, record):
            self.messages.append(record)

    mock_handler = MockHandler()

    logger = logging.getLogger("testlogger")
    logger.addHandler(mock_handler)
    logger.setLevel(logging.DEBUG)

    policy = HttpLoggingPolicy(logger=logger)

    universal_request = HttpRequest('GET', 'http://127.0.0.1/')
    http_response = HttpResponse(universal_request, None)
    http_response.status_code = 202
    request = PipelineRequest(universal_request, PipelineContext(None))

    # Basics

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    assert all(m.levelname == 'INFO' for m in mock_handler.messages)
    assert len(mock_handler.messages) == 5
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'

    mock_handler.reset()

    # Let's make this request a failure, retried twice

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    assert all(m.levelname == 'INFO' for m in mock_handler.messages)
    assert len(mock_handler.messages) == 10
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == 'Request headers:'
    assert mock_handler.messages[3].message == 'Response status: 202'
    assert mock_handler.messages[4].message == 'Response headers:'

    mock_handler.reset()

    # Headers and query parameters

    policy.allowed_query_params = ['country']

    universal_request.headers = {
        "Accept": "Caramel",
        "Hate": "Chocolat",
    }
    http_response.headers = {
        "Content-Type": "Caramel",
        "HateToo": "Chocolat",
    }
    universal_request.url = "http://127.0.0.1/?country=france&city=aix"

    policy.on_request(request)
    response = PipelineResponse(request, http_response, request.context)
    policy.on_response(request, response)

    assert all(m.levelname == 'INFO' for m in mock_handler.messages)
    assert len(mock_handler.messages) == 9
    assert mock_handler.messages[
        0].message == "Request URL: 'http://127.0.0.1/?country=france&city=REDACTED'"
    assert mock_handler.messages[1].message == "Request method: 'GET'"
    assert mock_handler.messages[2].message == "Request headers:"
    # Dict not ordered in Python, exact logging order doesn't matter
    assert set([
        mock_handler.messages[3].message, mock_handler.messages[4].message
    ]) == set(["    'Accept': 'Caramel'", "    'Hate': 'REDACTED'"])
    assert mock_handler.messages[5].message == "Response status: 202"
    assert mock_handler.messages[6].message == "Response headers:"
    # Dict not ordered in Python, exact logging order doesn't matter
    assert set([
        mock_handler.messages[7].message, mock_handler.messages[8].message
    ]) == set(["    'Content-Type': 'Caramel'", "    'HateToo': 'REDACTED'"])

    mock_handler.reset()
예제 #5
0
 def _make_request(self):
     return PipelineRequest(
         HttpRequest("AzureIdentityCredentialAdapter", "https://fakeurl"),
         PipelineContext(None),
     )
예제 #6
0
def test_raw_deserializer(http_request, http_response,
                          requests_transport_response):
    raw_deserializer = ContentDecodePolicy()
    context = PipelineContext(None, stream=False)
    universal_request = http_request('GET', 'http://localhost/')
    request = PipelineRequest(universal_request, context)

    def build_response(body, content_type=None):
        if is_rest(http_response):

            class MockResponse(http_response):
                def __init__(self, body, content_type):
                    super(MockResponse, self).__init__(
                        request=None,
                        internal_response=None,
                        status_code=400,
                        reason="Bad Request",
                        content_type="application/json",
                        headers={},
                        stream_download_generator=None,
                    )
                    self._body = body
                    self.content_type = content_type

                def body(self):
                    return self._body

                def read(self):
                    self._content = self._body
                    return self.content

        else:

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

                def body(self):
                    return self._body

        return PipelineResponse(request, MockResponse(body, content_type),
                                context)

    response = build_response(b"<groot/>", content_type="application/xml")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result.tag == "groot"

    response = build_response(b"\xef\xbb\xbf<utf8groot/>",
                              content_type="application/xml")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result.tag == "utf8groot"

    # The basic deserializer works with unicode XML
    response = build_response(u'<groot language="français"/>'.encode('utf-8'),
                              content_type="application/xml")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result.attrib["language"] == u"français"

    # Catch some weird situation where content_type is XML, but content is JSON
    response = build_response(b'{"ugly": true}',
                              content_type="application/xml")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["ugly"] is True

    # Be sure I catch the correct exception if it's neither XML nor JSON
    response = build_response(b'gibberish', content_type="application/xml")
    with pytest.raises(DecodeError) as err:
        raw_deserializer.on_response(request, response)
    assert err.value.response is response.http_response

    response = build_response(b'{{gibberish}}', content_type="application/xml")
    with pytest.raises(DecodeError) as err:
        raw_deserializer.on_response(request, response)
    assert err.value.response is response.http_response

    # Simple JSON
    response = build_response(b'{"success": true}',
                              content_type="application/json")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["success"] is True

    # Simple JSON with BOM
    response = build_response(b'\xef\xbb\xbf{"success": true}',
                              content_type="application/json")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["success"] is True

    # Simple JSON with complex content_type
    response = build_response(
        b'{"success": true}',
        content_type="application/vnd.microsoft.appconfig.kv.v1+json")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["success"] is True

    # Simple JSON with complex content_type, v2
    response = build_response(
        b'{"success": true}',
        content_type="text/vnd.microsoft.appconfig.kv.v1+json")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["success"] is True

    # For compat, if no content-type, decode JSON
    response = build_response(b'"data"')
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == "data"

    # Let text/plain let through
    response = build_response(b'I am groot', content_type="text/plain")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == "I am groot"

    # Let text/plain let through + BOM
    response = build_response(b'\xef\xbb\xbfI am groot',
                              content_type="text/plain")
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == "I am groot"

    # Try with a mock of requests

    req_response = requests.Response()
    req_response.headers["content-type"] = "application/json"
    req_response._content = b'{"success": true}'
    req_response._content_consumed = True
    response = PipelineResponse(
        None,
        create_transport_response(requests_transport_response, None,
                                  req_response),
        PipelineContext(None, stream=False))

    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result["success"] is True

    # I can enable it per request
    request.context.options['response_encoding'] = 'utf-8'
    response = build_response(b'\xc3\xa9', content_type="text/plain")
    raw_deserializer.on_request(request)
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == u"é"
    assert response.context["response_encoding"] == "utf-8"
    del request.context['response_encoding']

    # I can enable it globally
    raw_deserializer = ContentDecodePolicy(response_encoding="utf-8")
    response = build_response(b'\xc3\xa9', content_type="text/plain")
    raw_deserializer.on_request(request)
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == u"é"
    assert response.context["response_encoding"] == "utf-8"
    del request.context['response_encoding']

    # Per request is more important
    request.context.options['response_encoding'] = 'utf-8-sig'
    response = build_response(b'\xc3\xa9', content_type="text/plain")
    raw_deserializer.on_request(request)
    raw_deserializer.on_response(request, response)
    result = response.context["deserialized_data"]
    assert result == u"é"
    assert response.context["response_encoding"] == "utf-8-sig"
    del request.context['response_encoding']
def test_distributed_tracing_policy_with_user_agent():
    """Test policy working with user agent."""
    settings.tracing_implementation.set_value(FakeSpan)
    with mock.patch.dict('os.environ', {"AZURE_HTTP_USER_AGENT": "mytools"}):
        with FakeSpan(name="parent") as root_span:
            policy = DistributedTracingPolicy()

            request = HttpRequest("GET", "http://127.0.0.1")
            request.headers[
                "x-ms-client-request-id"] = "some client request id"

            pipeline_request = PipelineRequest(request, PipelineContext(None))

            user_agent = UserAgentPolicy()
            user_agent.on_request(pipeline_request)
            policy.on_request(pipeline_request)

            response = HttpResponse(request, None)
            response.headers = request.headers
            response.status_code = 202
            response.headers["x-ms-request-id"] = "some request id"
            pipeline_response = PipelineResponse(request, response,
                                                 PipelineContext(None))

            assert request.headers.get("traceparent") == '123456789'

            policy.on_response(pipeline_request, pipeline_response)

            time.sleep(0.001)
            policy.on_request(pipeline_request)
            try:
                raise ValueError("Transport trouble")
            except:
                policy.on_exception(pipeline_request)

            user_agent.on_response(pipeline_request, pipeline_response)

        network_span = root_span.children[0]
        assert network_span.name == "/"
        assert network_span.attributes.get("http.method") == "GET"
        assert network_span.attributes.get("component") == "http"
        assert network_span.attributes.get("http.url") == "http://127.0.0.1"
        assert network_span.attributes.get("http.user_agent").endswith(
            "mytools")
        assert network_span.attributes.get(
            "x-ms-request-id") == "some request id"
        assert network_span.attributes.get(
            "x-ms-client-request-id") == "some client request id"
        assert network_span.attributes.get("http.status_code") == 202

        network_span = root_span.children[1]
        assert network_span.name == "/"
        assert network_span.attributes.get("http.method") == "GET"
        assert network_span.attributes.get("component") == "http"
        assert network_span.attributes.get("http.url") == "http://127.0.0.1"
        assert network_span.attributes.get("http.user_agent").endswith(
            "mytools")
        assert network_span.attributes.get(
            "x-ms-client-request-id") == "some client request id"
        assert network_span.attributes.get("x-ms-request-id") is None
        assert network_span.attributes.get("http.status_code") == 504
        # Exception should propagate status for Opencensus
        assert network_span.status == 'Transport trouble'
 async def prepare_requests(req):
     context = PipelineContext(None)
     pipeline_request = PipelineRequest(req, context)
     for policy in policies:
         await _await_result(policy.on_request, pipeline_request)