@@ -300,7 +300,7 @@ def test_sub_app_fastapi_call(self):
300300        for  span  in  spans_with_http_attributes :
301301            self .assertEqual ("/sub/home" , span .attributes [HTTP_TARGET ])
302302        self .assertEqual (
303-             "https://testserver:443 /sub/home" ,
303+             "https://testserver/sub/home" ,
304304            span .attributes [HTTP_URL ],
305305        )
306306
@@ -1244,7 +1244,7 @@ def test_sub_app_fastapi_call(self):
12441244        for  span  in  spans_with_http_attributes :
12451245            self .assertEqual ("/sub/home" , span .attributes [HTTP_TARGET ])
12461246        self .assertEqual (
1247-             "https://testserver:443 /sub/home" ,
1247+             "https://testserver/sub/home" ,
12481248            span .attributes [HTTP_URL ],
12491249        )
12501250
@@ -1332,7 +1332,7 @@ def test_sub_app_fastapi_call(self):
13321332        for  span  in  spans_with_http_attributes :
13331333            self .assertEqual ("/sub/home" , span .attributes [HTTP_TARGET ])
13341334        self .assertEqual (
1335-             "https://testserver:443 /sub/home" ,
1335+             "https://testserver/sub/home" ,
13361336            span .attributes [HTTP_URL ],
13371337        )
13381338
@@ -1881,7 +1881,7 @@ def test_custom_header_not_present_in_non_recording_span(self):
18811881
18821882class  TestFastAPIHostHeaderURL (TestBaseManualFastAPI ):
18831883    """Test suite for Host header URL functionality in FastAPI instrumentation.""" 
1884-      
1884+ 
18851885    def  test_host_header_url_construction (self ):
18861886        """Test that URLs use Host header value instead of server IP when available.""" 
18871887        # Test with a custom Host header - should use the domain name 
@@ -1890,24 +1890,24 @@ def test_host_header_url_construction(self):
18901890            headers = {"host" : "api.mycompany.com" }
18911891        )
18921892        self .assertEqual (200 , resp .status_code )
1893-          
1893+ 
18941894        spans  =  self .memory_exporter .get_finished_spans ()
18951895        self .assertEqual (len (spans ), 3 )
1896-          
1896+ 
18971897        # Find the server span (the main span, not internal middleware spans) 
18981898        server_span  =  None 
18991899        for  span  in  spans :
19001900            if  HTTP_URL  in  span .attributes :
19011901                server_span  =  span 
19021902                break 
1903-          
1903+ 
19041904        self .assertIsNotNone (server_span , "Server span with HTTP_URL not found" )
1905-          
1905+ 
19061906        # Verify the URL uses the Host header domain instead of testserver 
1907-         expected_url  =  "https://api.mycompany.com:443 /foobar?param=value" 
1907+         expected_url  =  "https://api.mycompany.com/foobar?param=value" 
19081908        actual_url  =  server_span .attributes [HTTP_URL ]
19091909        self .assertEqual (expected_url , actual_url )
1910-          
1910+ 
19111911        # Also verify that the server name attribute is set correctly 
19121912        self .assertEqual ("api.mycompany.com" , server_span .attributes .get ("http.server_name" ))
19131913
@@ -1918,13 +1918,13 @@ def test_host_header_with_port_url_construction(self):
19181918            headers = {"host" : "staging.myapp.com:8443" }
19191919        )
19201920        self .assertEqual (200 , resp .status_code )
1921-          
1921+ 
19221922        spans  =  self .memory_exporter .get_finished_spans ()
19231923        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
19241924        self .assertIsNotNone (server_span )
1925-          
1925+ 
19261926        # Should use the host header value with non-standard port included 
1927-         expected_url  =  "https://staging.myapp.com:8443:443 /user/123" 
1927+         expected_url  =  "https://staging.myapp.com:8443/user/123" 
19281928        actual_url  =  server_span .attributes [HTTP_URL ]
19291929        self .assertEqual (expected_url , actual_url )
19301930
@@ -1933,13 +1933,13 @@ def test_no_host_header_fallback_behavior(self):
19331933        # Make request without custom Host header - should use testserver (default TestClient base) 
19341934        resp  =  self ._client .get ("/foobar" )
19351935        self .assertEqual (200 , resp .status_code )
1936-          
1936+ 
19371937        spans  =  self .memory_exporter .get_finished_spans ()
19381938        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
19391939        self .assertIsNotNone (server_span )
1940-          
1940+ 
19411941        # Should fallback to testserver (TestClient default, standard port stripped) 
1942-         expected_url  =  "https://testserver:443 /foobar" 
1942+         expected_url  =  "https://testserver/foobar" 
19431943        actual_url  =  server_span .attributes [HTTP_URL ]
19441944        self .assertEqual (expected_url , actual_url )
19451945
@@ -1954,16 +1954,16 @@ def test_production_scenario_host_header(self):
19541954            }
19551955        )
19561956        self .assertEqual (200 , resp .status_code )  # Valid route should return 200 
1957-          
1957+ 
19581958        spans  =  self .memory_exporter .get_finished_spans ()
19591959        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
19601960        self .assertIsNotNone (server_span )
1961-          
1961+ 
19621962        # URL should use the production domain from Host header (AS-IS, no default port) 
1963-         expected_url  =  "https://prod-api.example.com:443 /foobar?limit=10&offset=20" 
1963+         expected_url  =  "https://prod-api.example.com/foobar?limit=10&offset=20" 
19641964        actual_url  =  server_span .attributes [HTTP_URL ]
19651965        self .assertEqual (expected_url , actual_url )
1966-          
1966+ 
19671967        # Verify other attributes are still correct 
19681968        self .assertEqual ("GET" , server_span .attributes [HTTP_METHOD ])
19691969        self .assertEqual ("/foobar" , server_span .attributes [HTTP_TARGET ])
@@ -1972,12 +1972,12 @@ def test_production_scenario_host_header(self):
19721972    def  test_host_header_with_special_characters (self ):
19731973        """Test Host header handling with special characters and edge cases.""" 
19741974        test_cases  =  [
1975-             ("api-v2.test-domain.com" , "https://api-v2.test-domain.com:443 /foobar" ),
1976-             ("localhost" , "https://localhost:443 /foobar" ),
1977-             ("192.168.1.100" , "https://192.168.1.100:443 /foobar" ),  # IP address as host 
1978-             ("test.domain.co.uk" , "https://test.domain.co.uk:443 /foobar" ),  # Multiple dots 
1975+             ("api-v2.test-domain.com" , "https://api-v2.test-domain.com/foobar" ),
1976+             ("localhost" , "https://localhost/foobar" ),
1977+             ("192.168.1.100" , "https://192.168.1.100/foobar" ),  # IP address as host 
1978+             ("test.domain.co.uk" , "https://test.domain.co.uk/foobar" ),  # Multiple dots 
19791979        ]
1980-          
1980+ 
19811981        for  host_value , expected_url  in  test_cases :
19821982            with  self .subTest (host = host_value ):
19831983                # Clear previous spans 
@@ -1988,11 +1988,11 @@ def test_host_header_with_special_characters(self):
19881988                    headers = {"host" : host_value }
19891989                )
19901990                self .assertEqual (200 , resp .status_code )
1991-                  
1991+ 
19921992                spans  =  self .memory_exporter .get_finished_spans ()
19931993                server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
19941994                self .assertIsNotNone (server_span )
1995-                  
1995+ 
19961996                actual_url  =  server_span .attributes [HTTP_URL ]
19971997                self .assertEqual (expected_url , actual_url )
19981998
@@ -2004,13 +2004,13 @@ def test_host_header_bytes_handling(self):
20042004            headers = {"host" : "bytes-test.example.com" }
20052005        )
20062006        self .assertEqual (200 , resp .status_code )
2007-          
2007+ 
20082008        spans  =  self .memory_exporter .get_finished_spans ()
20092009        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
20102010        self .assertIsNotNone (server_span )
2011-          
2011+ 
20122012        # Should properly decode and use the host header 
2013-         expected_url  =  "https://bytes-test.example.com:443 /foobar" 
2013+         expected_url  =  "https://bytes-test.example.com/foobar" 
20142014        actual_url  =  server_span .attributes [HTTP_URL ]
20152015        self .assertEqual (expected_url , actual_url )
20162016
@@ -2024,33 +2024,33 @@ def test_host_header_maintains_span_attributes(self):
20242024            }
20252025        )
20262026        self .assertEqual (200 , resp .status_code )
2027-          
2027+ 
20282028        spans  =  self .memory_exporter .get_finished_spans ()
20292029        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
20302030        self .assertIsNotNone (server_span )
2031-          
2031+ 
20322032        # Verify URL uses Host header 
2033-         self .assertEqual ("https://api.testapp.com:443 /user/testuser?debug=true" , 
2033+         self .assertEqual ("https://api.testapp.com/user/testuser?debug=true" , 
20342034                        server_span .attributes [HTTP_URL ])
2035-          
2035+ 
20362036        # Verify all other attributes are still present and correct 
20372037        self .assertEqual ("GET" , server_span .attributes [HTTP_METHOD ])
20382038        self .assertEqual ("/user/testuser" , server_span .attributes [HTTP_TARGET ])
20392039        self .assertEqual ("https" , server_span .attributes [HTTP_SCHEME ])
20402040        self .assertEqual ("api.testapp.com" , server_span .attributes .get ("http.server_name" ))
20412041        self .assertEqual (200 , server_span .attributes [HTTP_STATUS_CODE ])
2042-          
2042+ 
20432043        # Check that route attribute is still set correctly 
20442044        if  HTTP_ROUTE  in  server_span .attributes :
20452045            self .assertEqual ("/user/{username}" , server_span .attributes [HTTP_ROUTE ])
20462046
20472047
20482048class  TestFastAPIHostHeaderURLNewSemconv (TestFastAPIHostHeaderURL ):
20492049    """Test Host header URL functionality with new semantic conventions.""" 
2050-      
2050+ 
20512051    def  test_host_header_url_new_semconv (self ):
20522052        """Test Host header URL construction with new semantic conventions. 
2053-          
2053+ 
20542054        Note: With new semantic conventions, the URL is split into components 
20552055        (url.scheme, server.address, url.path, etc.) rather than a single http.url. 
20562056        Host header support may work differently with new semantic conventions. 
@@ -2060,19 +2060,19 @@ def test_host_header_url_new_semconv(self):
20602060            headers = {"host" : "newapi.example.com" }
20612061        )
20622062        self .assertEqual (200 , resp .status_code )
2063-          
2063+ 
20642064        spans  =  self .memory_exporter .get_finished_spans ()
20652065        # With new semantic conventions, look for the main HTTP span with route information 
20662066        server_span  =  next ((span  for  span  in  spans  if  "http.route"  in  span .attributes ), None )
20672067        self .assertIsNotNone (server_span )
2068-          
2068+ 
20692069        # Verify we have the new semantic convention attributes 
20702070        self .assertIn ("url.scheme" , server_span .attributes )
20712071        self .assertIn ("server.address" , server_span .attributes )
20722072        self .assertIn ("url.path" , server_span .attributes )
20732073        self .assertEqual ("https" , server_span .attributes .get ("url.scheme" ))
20742074        self .assertEqual ("/foobar" , server_span .attributes .get ("url.path" ))
2075-          
2075+ 
20762076        # Current behavior: Host header may not affect server.address in new semantic conventions 
20772077        # This test documents the current behavior rather than enforcing Host header usage 
20782078        server_address  =  server_span .attributes .get ("server.address" , "" )
@@ -2081,21 +2081,20 @@ def test_host_header_url_new_semconv(self):
20812081
20822082class  TestFastAPIHostHeaderURLBothSemconv (TestFastAPIHostHeaderURL ):
20832083    """Test Host header URL functionality with both old and new semantic conventions.""" 
2084-     
20852084    def  test_host_header_url_both_semconv (self ):
20862085        """Test Host header URL construction with both semantic conventions enabled.""" 
20872086        resp  =  self ._client .get (
20882087            "/foobar?test=both_semconv" , 
20892088            headers = {"host" : "dual.example.com" }
20902089        )
20912090        self .assertEqual (200 , resp .status_code )
2092-          
2091+ 
20932092        spans  =  self .memory_exporter .get_finished_spans ()
20942093        server_span  =  next ((span  for  span  in  spans  if  HTTP_URL  in  span .attributes ), None )
20952094        self .assertIsNotNone (server_span )
2096-          
2095+ 
20972096        # Should use Host header for URL construction regardless of semantic convention mode 
2098-         expected_url  =  "https://dual.example.com:443 /foobar?test=both_semconv" 
2097+         expected_url  =  "https://dual.example.com/foobar?test=both_semconv" 
20992098        actual_url  =  server_span .attributes [HTTP_URL ]
21002099        self .assertEqual (expected_url , actual_url )
21012100
@@ -2121,15 +2120,14 @@ def test_fastapi_unhandled_exception_both_semconv(self):
21212120        # 2. ASGI receive span   
21222121        # 3. ASGI send span (for error response) 
21232122        self .assertEqual (len (spans ), 3 )
2124-          
2123+ 
21252124        # Find the server span (it should have HTTP attributes) 
21262125        server_spans  =  [span  for  span  in  spans  if  hasattr (span , 'attributes' ) and  span .attributes  and  HTTP_URL  in  span .attributes ]
2127-          
2126+ 
21282127        self .assertEqual (len (server_spans ), 1 , "Expected exactly one server span with HTTP_URL" )
21292128        server_span  =  server_spans [0 ]
2130-          
2129+ 
21312130        # Ensure server_span is not None 
21322131        assert  server_span  is  not   None 
2133-         
2134-         self .assertEqual (server_span .name , "GET /error" )
21352132
2133+         self .assertEqual (server_span .name , "GET /error" )
0 commit comments