@@ -40,6 +40,24 @@ async def http_app_with_custom_headers(scope, receive, send):
4040 await send ({"type" : "http.response.body" , "body" : b"*" })
4141
4242
43+ async def http_app_with_repeat_headers (scope , receive , send ):
44+ message = await receive ()
45+ assert scope ["type" ] == "http"
46+ if message .get ("type" ) == "http.request" :
47+ await send (
48+ {
49+ "type" : "http.response.start" ,
50+ "status" : 200 ,
51+ "headers" : [
52+ (b"Content-Type" , b"text/plain" ),
53+ (b"custom-test-header-1" , b"test-header-value-1" ),
54+ (b"custom-test-header-1" , b"test-header-value-2" ),
55+ ],
56+ }
57+ )
58+ await send ({"type" : "http.response.body" , "body" : b"*" })
59+
60+
4361async def websocket_app_with_custom_headers (scope , receive , send ):
4462 assert scope ["type" ] == "websocket"
4563 while True :
@@ -121,6 +139,25 @@ def test_http_custom_request_headers_in_span_attributes(self):
121139 if span .kind == SpanKind .SERVER :
122140 self .assertSpanHasAttributes (span , expected )
123141
142+ def test_http_repeat_request_headers_in_span_attributes (self ):
143+ self .scope ["headers" ].extend (
144+ [
145+ (b"custom-test-header-1" , b"test-header-value-1" ),
146+ (b"custom-test-header-1" , b"test-header-value-2" ),
147+ ]
148+ )
149+ self .seed_app (self .app )
150+ self .send_default_request ()
151+ self .get_all_output ()
152+ span_list = self .exporter .get_finished_spans ()
153+ expected = {
154+ "http.request.header.custom_test_header_1" : (
155+ "test-header-value-1,test-header-value-2" ,
156+ ),
157+ }
158+ span = next (span for span in span_list if span .kind == SpanKind .SERVER )
159+ self .assertSpanHasAttributes (span , expected )
160+
124161 def test_http_custom_request_headers_not_in_span_attributes (self ):
125162 self .scope ["headers" ].extend (
126163 [
@@ -176,6 +213,24 @@ def test_http_custom_response_headers_in_span_attributes(self):
176213 if span .kind == SpanKind .SERVER :
177214 self .assertSpanHasAttributes (span , expected )
178215
216+ def test_http_repeat_response_headers_in_span_attributes (self ):
217+ self .app = otel_asgi .OpenTelemetryMiddleware (
218+ http_app_with_repeat_headers ,
219+ tracer_provider = self .tracer_provider ,
220+ ** self .constructor_params ,
221+ )
222+ self .seed_app (self .app )
223+ self .send_default_request ()
224+ self .get_all_output ()
225+ span_list = self .exporter .get_finished_spans ()
226+ expected = {
227+ "http.response.header.custom_test_header_1" : (
228+ "test-header-value-1,test-header-value-2" ,
229+ ),
230+ }
231+ span = next (span for span in span_list if span .kind == SpanKind .SERVER )
232+ self .assertSpanHasAttributes (span , expected )
233+
179234 def test_http_custom_response_headers_not_in_span_attributes (self ):
180235 self .app = otel_asgi .OpenTelemetryMiddleware (
181236 http_app_with_custom_headers ,
0 commit comments