def test_distributed_tracing_policy_solo(): """Test policy with no other policy and happy path""" settings.tracing_implementation.set_value(FakeSpan) with FakeSpan(name="parent") as root_span: policy = DistributedTracingPolicy() request = HttpRequest("GET", "http://127.0.0.1/temp?query=query") request.headers["x-ms-client-request-id"] = "some client request id" pipeline_request = PipelineRequest(request, PipelineContext(None)) 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" assert request.headers.get("traceparent") == '123456789' policy.on_response( pipeline_request, PipelineResponse(request, response, PipelineContext(None))) time.sleep(0.001) policy.on_request(pipeline_request) try: raise ValueError("Transport trouble") except: policy.on_exception(pipeline_request) # Check on_response network_span = root_span.children[0] assert network_span.name == "/temp" 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/temp?query=query" assert network_span.attributes.get("http.user_agent") is None 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 # Check on_exception network_span = root_span.children[1] assert network_span.name == "/temp" 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/temp?query=query" assert network_span.attributes.get( "x-ms-client-request-id") == "some client request id" assert network_span.attributes.get("http.user_agent") is None assert network_span.attributes.get("x-ms-request-id") == None assert network_span.attributes.get("http.status_code") == 504
def parse_responses(response): http_request = response.request context = PipelineContext(None) pipeline_request = PipelineRequest(http_request, context) pipeline_response = PipelineResponse(http_request, response, context=context) for policy in policies: _await_result(policy.on_response, pipeline_request, pipeline_response)
def build_response(body, content_type=None): class MockResponse(HttpResponse): 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)
def send(self, request): """HTTP transport send method. :param request: The PipelineRequest object. :type request: ~azure.core.pipeline.PipelineRequest :return: The PipelineResponse object. :rtype: ~azure.core.pipeline.PipelineResponse """ return PipelineResponse(request.http_request, self._sender.send(request.http_request, **request.context.options), context=request.context)
def test_distributed_tracing_policy_solo(should_set_sdk_context): """Test policy with no other policy and happy path""" with ContextHelper(): exporter = MockExporter() trace = tracer_module.Tracer(sampler=AlwaysOnSampler(), exporter=exporter) with trace.span("parent"): if should_set_sdk_context: tracing_context.current_span.set(OpenCensusSpan(trace.current_span())) policy = DistributedTracingPolicy() request = HttpRequest("GET", "http://127.0.0.1/temp?query=query") request.headers["x-ms-client-request-id"] = "some client request id" pipeline_request = PipelineRequest(request, PipelineContext(None)) 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" ctx = trace.span_context header = trace.propagator.to_headers(ctx) assert request.headers.get("traceparent") == header.get("traceparent") policy.on_response(pipeline_request, PipelineResponse(request, response, PipelineContext(None))) time.sleep(0.001) policy.on_request(pipeline_request) policy.on_exception(pipeline_request) trace.finish() exporter.build_tree() parent = exporter.root network_span = parent.children[0] assert network_span.span_data.name == "/temp" assert network_span.span_data.attributes.get("http.method") == "GET" assert network_span.span_data.attributes.get("component") == "http" assert network_span.span_data.attributes.get("http.url") == "http://127.0.0.1/temp?query=query" assert network_span.span_data.attributes.get("http.user_agent") is None assert network_span.span_data.attributes.get("x-ms-request-id") == "some request id" assert network_span.span_data.attributes.get("x-ms-client-request-id") == "some client request id" assert network_span.span_data.attributes.get("http.status_code") == 202 network_span = parent.children[1] assert network_span.span_data.name == "/temp" assert network_span.span_data.attributes.get("http.method") == "GET" assert network_span.span_data.attributes.get("component") == "http" assert network_span.span_data.attributes.get("http.url") == "http://127.0.0.1/temp?query=query" assert network_span.span_data.attributes.get("x-ms-client-request-id") == "some client request id" assert network_span.span_data.attributes.get("http.user_agent") is None assert network_span.span_data.attributes.get("x-ms-request-id") == None assert network_span.span_data.attributes.get("http.status_code") == 504
def build_response(body, content_type=None): class MockResponse(HttpResponse): def __init__(self): super(MockResponse, self).__init__(None, None) self._body = 'test' def body(self): return self._body data = BytesIO(b"Lots of dataaaa") universal_request = HttpRequest('GET', 'http://127.0.0.1/', data=data) universal_request.set_streamed_data_body(data) return PipelineResponse(universal_request, MockResponse(), PipelineContext(None, stream=True))
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
def test_save_sync_token(): test_sync_token = "jtqGc1I4=MDoyOA==;sn=28" 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['jtqGc1I4'] assert sync_token.token_id == 'jtqGc1I4' assert sync_token.value == 'MDoyOA==' assert sync_token.sequence_number == 28
def test_set_sync_token(): test_sync_token = "jtqGc1I4=MDoyOA==;sn=28" 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) pipeline_request = PipelineRequest(request, None) sync_token_policy = SyncTokenPolicy() sync_token_policy.on_response(None, pipeline_response) sync_token_policy.on_request(pipeline_request) sync_token_header = pipeline_request.http_request.headers.get("Sync-Token") assert sync_token_header == 'jtqGc1I4=MDoyOA=='
def mock_send(http_request, http_response, method, status, headers=None, body=RESPONSE_BODY): if headers is None: headers = {} response = Response() response._content_consumed = True response._content = json.dumps(body).encode( 'ascii') if body is not None else None response.request = Request() response.request.method = method response.request.url = RESOURCE_URL response.request.headers = { 'x-ms-client-request-id': '67f4dd4e-6262-45e1-8bed-5c45cf23b6d9' } response.status_code = status response.headers = headers response.headers.update( {"content-type": "application/json; charset=utf8"}) response.reason = "OK" if is_rest(http_request): request = http_request( response.request.method, response.request.url, headers=response.request.headers, content=body, ) else: request = CLIENT._request( response.request.method, response.request.url, None, # params response.request.headers, body, None, # form_content None # stream_content ) response = create_transport_response( http_response, request, response, ) return PipelineResponse( request, response, None # context )
def mock_update(url, headers=None): response = Response() response._content_consumed = True response.request = mock.create_autospec(Request) response.request.method = 'GET' response.headers = headers or {} response.headers.update( {"content-type": "application/json; charset=utf8"}) response.reason = "OK" if url == ASYNC_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = ASYNC_BODY.encode('ascii') response.randomFieldFromPollAsyncOpHeader = None elif url == LOCATION_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = LOCATION_BODY.encode('ascii') response.randomFieldFromPollLocationHeader = None elif url == ERROR: raise BadEndpointError("boom") elif url == RESOURCE_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = RESOURCE_BODY.encode('ascii') else: raise Exception('URL does not match') request = CLIENT._request( response.request.method, response.request.url, None, # params {}, # request has no headers None, # Request has no body None, # form_content None # stream_content ) return PipelineResponse( request, AsyncioRequestsTransportResponse( request, response, ), None # context )
def build_response(body, content_type=None): class MockResponse(HttpResponse): def __init__(self, body, content_type): super(MockResponse, self).__init__(None, None) self._body = body self.content_type = None if content_type: self.content_type = [content_type] def body(self): return self._body return PipelineResponse(None, MockResponse(body, content_type), PipelineContext(None, stream=False))
def test_set_multi_sync_token(): test_sync_token = "syncToken1=val1;sn=6,syncToken2=val2;sn=10" 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) pipeline_request = PipelineRequest(request, None) sync_token_policy = SyncTokenPolicy() sync_token_policy.on_response(None, pipeline_response) sync_token_policy.on_request(pipeline_request) sync_token_header = pipeline_request.http_request.headers.get("Sync-Token") assert 'syncToken1=val1' in sync_token_header assert 'syncToken2=val2' in sync_token_header
def polling_response(): polling = LROBasePolling() headers = {} response = Response() response.headers = headers response.status_code = 200 polling._pipeline_response = PipelineResponse( None, RequestsTransportResponse( None, response, ), PipelineContext(None)) polling._initial_response = polling._pipeline_response return polling, headers
def test_x_ms_retry_after(retry_after_input): retry_policy = RetryPolicy() request = HttpRequest("GET", "https://bing.com") response = HttpResponse(request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) retry_after = retry_policy.get_retry_after(pipeline_response) seconds = float(retry_after_input) assert retry_after == seconds/1000.0 response.headers.pop("x-ms-retry-after-ms") response.headers["Retry-After"] = retry_after_input retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input) response.headers["x-ms-retry-after-ms"] = 500 retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input)
def test_x_ms_retry_after(retry_after_input, http_request, http_response): retry_policy = RetryPolicy() request = http_request("GET", "http://localhost") response = create_http_response(http_response, request, None) response.headers["x-ms-retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) retry_after = retry_policy.get_retry_after(pipeline_response) seconds = float(retry_after_input) assert retry_after == seconds / 1000.0 response.headers.pop("x-ms-retry-after-ms") response.headers["Retry-After"] = retry_after_input retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input) response.headers["x-ms-retry-after-ms"] = 500 retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input)
def test_retry_after(retry_after_input): retry_policy = AsyncRetryPolicy() request = HttpRequest("GET", "http://localhost") response = HttpResponse(request, None) response.headers["retry-after-ms"] = retry_after_input pipeline_response = PipelineResponse(request, response, None) retry_after = retry_policy.get_retry_after(pipeline_response) seconds = float(retry_after_input) assert retry_after == seconds / 1000.0 response.headers.pop("retry-after-ms") response.headers["Retry-After"] = retry_after_input retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input) response.headers["retry-after-ms"] = 500 retry_after = retry_policy.get_retry_after(pipeline_response) assert retry_after == float(retry_after_input)
def _callback(http_response, headers={}): polling = LROBasePolling() response = Response() response.headers = headers response.status_code = 200 response = create_transport_response( http_response, None, response, ) polling._pipeline_response = PipelineResponse(None, response, PipelineContext(None)) polling._initial_response = polling._pipeline_response return polling
def polling_response(): polling = LROBasePolling() headers = {} response = Response() response.headers = headers polling._pipeline_response = PipelineResponse( None, RequestsTransportResponse( None, response, ), None # context ) return polling, headers
def mock_update(http_request, http_response, url, headers=None): response = Response() response._content_consumed = True response.request = mock.create_autospec(Request) response.request.method = 'GET' response.headers = headers or {} response.headers.update({"content-type": "application/json; charset=utf8"}) response.reason = "OK" if url == ASYNC_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = ASYNC_BODY.encode('ascii') response.randomFieldFromPollAsyncOpHeader = None elif url == LOCATION_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = LOCATION_BODY.encode('ascii') response.randomFieldFromPollLocationHeader = None elif url == ERROR: raise BadEndpointError("boom") elif url == RESOURCE_URL: response.request.url = url response.status_code = POLLING_STATUS response._content = RESOURCE_BODY.encode('ascii') else: raise Exception('URL does not match') request = http_request( response.request.method, response.request.url, ) response = create_transport_response(http_response, request, response) if is_rest(http_response): response.body() return PipelineResponse( request, response, None # context )
def test_http_logger_with_generator_body(http_request, http_response): 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 = http_request('GET', 'http://localhost/') mock = Mock() mock.__class__ = types.AsyncGeneratorType universal_request.body = mock http_response = create_http_response(http_response, universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None)) 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) == 2 messages_request = mock_handler.messages[0].message.split("\n") messages_response = mock_handler.messages[1].message.split("\n") assert messages_request[0] == "Request URL: 'http://localhost/'" assert messages_request[1] == "Request method: 'GET'" assert messages_request[2] == 'Request headers:' assert messages_request[3] == 'File upload' assert messages_response[0] == 'Response status: 202' assert messages_response[1] == 'Response headers:' mock_handler.reset()
def test_http_logger_with_body(): 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/') universal_request.body = "testbody" http_response = HttpResponse(universal_request, None) http_response.status_code = 202 request = PipelineRequest(universal_request, PipelineContext(None)) 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) == 6 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 == 'A body is sent with the request' assert mock_handler.messages[4].message == 'Response status: 202' assert mock_handler.messages[5].message == 'Response headers:' mock_handler.reset()
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://localhost/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"
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)
def mock_send(method, status, headers=None, body=None): if headers is None: headers = {} response = mock.create_autospec(Response) response.request = mock.create_autospec(Request) response.request.method = method response.request.url = RESOURCE_URL response.request.headers = { 'x-ms-client-request-id': '67f4dd4e-6262-45e1-8bed-5c45cf23b6d9' } response.status_code = status response.headers = headers response.headers.update( {"content-type": "application/json; charset=utf8"}) response.reason = "OK" content = body if body is not None else RESPONSE_BODY response.text = json.dumps(content) response.json = lambda: json.loads(response.text) request = CLIENT._request( response.request.method, response.request.url, None, # params response.request.headers, content, None, # form_content None # stream_content ) return PipelineResponse( request, RequestsTransportResponse( request, response, ), None # context )
def test_distributed_tracing_policy_badurl(caplog, http_request, http_response): """Test policy with a bad url that will throw, and be sure policy ignores it""" settings.tracing_implementation.set_value(FakeSpan) with FakeSpan(name="parent") as root_span: policy = DistributedTracingPolicy() request = http_request("GET", "http://[[[") request.headers["x-ms-client-request-id"] = "some client request id" pipeline_request = PipelineRequest(request, PipelineContext(None)) with caplog.at_level( logging.WARNING, logger="azure.core.pipeline.policies.distributed_tracing"): policy.on_request(pipeline_request) assert "Unable to start network span" in caplog.text response = create_http_response(http_response, request, None) response.headers = request.headers response.status_code = 202 response.headers["x-ms-request-id"] = "some request id" assert request.headers.get( "traceparent") is None # Got not network trace policy.on_response( pipeline_request, PipelineResponse(request, response, PipelineContext(None))) time.sleep(0.001) policy.on_request(pipeline_request) try: raise ValueError("Transport trouble") except: policy.on_exception(pipeline_request) assert len(root_span.children) == 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
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()
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()
def test_raw_deserializer(): raw_deserializer = ContentDecodePolicy() context = PipelineContext(None, stream=False) universal_request = HttpRequest('GET', 'http://127.0.0.1/') request = PipelineRequest(universal_request, context) def build_response(body, content_type=None): class MockResponse(HttpResponse): 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, RequestsTransportResponse(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']