@@ -40,6 +40,24 @@ async def http_app_with_custom_headers(scope, receive, send):
40
40
await send ({"type" : "http.response.body" , "body" : b"*" })
41
41
42
42
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
+
43
61
async def websocket_app_with_custom_headers (scope , receive , send ):
44
62
assert scope ["type" ] == "websocket"
45
63
while True :
@@ -121,6 +139,25 @@ def test_http_custom_request_headers_in_span_attributes(self):
121
139
if span .kind == SpanKind .SERVER :
122
140
self .assertSpanHasAttributes (span , expected )
123
141
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
+
124
161
def test_http_custom_request_headers_not_in_span_attributes (self ):
125
162
self .scope ["headers" ].extend (
126
163
[
@@ -176,6 +213,24 @@ def test_http_custom_response_headers_in_span_attributes(self):
176
213
if span .kind == SpanKind .SERVER :
177
214
self .assertSpanHasAttributes (span , expected )
178
215
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
+
179
234
def test_http_custom_response_headers_not_in_span_attributes (self ):
180
235
self .app = otel_asgi .OpenTelemetryMiddleware (
181
236
http_app_with_custom_headers ,
0 commit comments