|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
| 15 | +from os import environ |
15 | 16 | from sys import modules
|
16 | 17 | from unittest.mock import Mock, patch
|
17 | 18 |
|
|
30 | 31 | from opentelemetry.test.test_base import TestBase
|
31 | 32 | from opentelemetry.test.wsgitestutil import WsgiTestBase
|
32 | 33 | from opentelemetry.trace import SpanKind, StatusCode
|
33 |
| -from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs |
| 34 | +from opentelemetry.util.http import ( |
| 35 | + ENV_HTTP_TRACE_RESPONSE_HEADER, |
| 36 | + get_excluded_urls, |
| 37 | + get_trace_response_headers, |
| 38 | + get_traced_request_attrs, |
| 39 | +) |
34 | 40 |
|
35 | 41 | # pylint: disable=import-error
|
36 | 42 | from .views import (
|
|
41 | 47 | route_span_name,
|
42 | 48 | traced,
|
43 | 49 | traced_template,
|
| 50 | + with_response_header, |
44 | 51 | )
|
45 | 52 |
|
46 | 53 | DJANGO_2_2 = VERSION >= (2, 2)
|
|
52 | 59 | url(r"^excluded_arg/", excluded),
|
53 | 60 | url(r"^excluded_noarg/", excluded_noarg),
|
54 | 61 | url(r"^excluded_noarg2/", excluded_noarg2),
|
| 62 | + url(r"^response_header/", with_response_header), |
55 | 63 | url(r"^span_name/([0-9]{4})/$", route_span_name),
|
56 | 64 | ]
|
57 | 65 | _django_instrumentor = DjangoInstrumentor()
|
@@ -309,3 +317,76 @@ def response_hook(span, request, response):
|
309 | 317 | self.assertIsInstance(response_hook_args[1], HttpRequest)
|
310 | 318 | self.assertIsInstance(response_hook_args[2], HttpResponse)
|
311 | 319 | self.assertEqual(response_hook_args[2], response)
|
| 320 | + |
| 321 | + def test_trace_response_header(self): |
| 322 | + original_env_var = environ.pop(ENV_HTTP_TRACE_RESPONSE_HEADER, None) |
| 323 | + response = Client().get("/span_name/1234/") |
| 324 | + self.assertNotIn("Server-Timing", response._headers) |
| 325 | + self.memory_exporter.clear() |
| 326 | + |
| 327 | + for header in ["Server-Timing", "traceresponse"]: |
| 328 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = header |
| 329 | + |
| 330 | + response = Client().get("/span_name/1234/") |
| 331 | + span = self.memory_exporter.get_finished_spans()[0] |
| 332 | + headers = get_trace_response_headers(span) |
| 333 | + self.assertEqual(len(headers), 2) |
| 334 | + |
| 335 | + access_control_header = headers[0] |
| 336 | + response_header = headers[1] |
| 337 | + |
| 338 | + self.assertIn(header.lower(), response._headers) |
| 339 | + self.assertEqual( |
| 340 | + response._headers["access-control-expose-headers"][0], |
| 341 | + access_control_header[0], |
| 342 | + ) |
| 343 | + self.assertEqual( |
| 344 | + response._headers["access-control-expose-headers"][1], |
| 345 | + access_control_header[1], |
| 346 | + ) |
| 347 | + self.assertEqual( |
| 348 | + response._headers[header.lower()][0], response_header[0] |
| 349 | + ) |
| 350 | + self.assertEqual( |
| 351 | + response._headers[header.lower()][1], response_header[1] |
| 352 | + ) |
| 353 | + |
| 354 | + self.memory_exporter.clear() |
| 355 | + del environ[ENV_HTTP_TRACE_RESPONSE_HEADER] |
| 356 | + |
| 357 | + if original_env_var: |
| 358 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = original_env_var |
| 359 | + |
| 360 | + def test_trace_response_header_pre_existing_header(self): |
| 361 | + original_env_var = environ.pop(ENV_HTTP_TRACE_RESPONSE_HEADER, None) |
| 362 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = "Server-Timing" |
| 363 | + response = Client().get("/response_header/") |
| 364 | + |
| 365 | + span = self.memory_exporter.get_finished_spans()[0] |
| 366 | + headers = get_trace_response_headers(span) |
| 367 | + self.assertEqual(len(headers), 2) |
| 368 | + access_control_header = headers[0] |
| 369 | + response_header = headers[1] |
| 370 | + |
| 371 | + self.assertIn("server-timing", response._headers) |
| 372 | + self.assertEqual( |
| 373 | + response._headers["access-control-expose-headers"][0], |
| 374 | + access_control_header[0], |
| 375 | + ) |
| 376 | + self.assertEqual( |
| 377 | + response._headers["access-control-expose-headers"][1], |
| 378 | + "X-Test-Header, Server-Timing", |
| 379 | + ) |
| 380 | + self.assertEqual( |
| 381 | + response._headers["server-timing"][0], response_header[0] |
| 382 | + ) |
| 383 | + self.assertEqual( |
| 384 | + response._headers["server-timing"][1], |
| 385 | + "abc; val=1, " + response_header[1], |
| 386 | + ) |
| 387 | + |
| 388 | + self.memory_exporter.clear() |
| 389 | + del environ[ENV_HTTP_TRACE_RESPONSE_HEADER] |
| 390 | + |
| 391 | + if original_env_var: |
| 392 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = original_env_var |
0 commit comments