|
| 1 | +import asyncio |
| 2 | +from types import SimpleNamespace |
| 3 | + |
| 4 | +from tests.test_main_observability import MainModuleHarness |
| 5 | + |
| 6 | + |
| 7 | +class CatchAllResponseHeaderTests(MainModuleHarness): |
| 8 | + """The FastAPI catch-all must preserve route()'s response headers. |
| 9 | +
|
| 10 | + /sitemap.xml is served through the catch-all; wrapping every |
| 11 | + response in HTMLResponse would discard its XML Content-Type. |
| 12 | + """ |
| 13 | + |
| 14 | + def request(self, url): |
| 15 | + return SimpleNamespace(url=url) |
| 16 | + |
| 17 | + def test_sitemap_keeps_xml_content_type_through_the_catch_all(self): |
| 18 | + main = self.import_main() |
| 19 | + response = asyncio.run( |
| 20 | + main.not_found("sitemap.xml", self.request("https://example.test/sitemap.xml")) |
| 21 | + ) |
| 22 | + self.assertEqual(response.headers["Content-Type"], "application/xml; charset=utf-8") |
| 23 | + self.assertIn("<urlset", response.content) |
| 24 | + self.assertEqual(response.status_code, 200) |
| 25 | + |
| 26 | + def test_journey_pages_stay_html_through_the_catch_all(self): |
| 27 | + main = self.import_main() |
| 28 | + response = asyncio.run( |
| 29 | + main.not_found("journeys", self.request("https://example.test/journeys")) |
| 30 | + ) |
| 31 | + self.assertTrue(response.headers["Content-Type"].startswith("text/html")) |
| 32 | + self.assertEqual(response.status_code, 200) |
| 33 | + |
| 34 | + def test_unknown_paths_fall_back_to_html(self): |
| 35 | + main = self.import_main() |
| 36 | + response = asyncio.run( |
| 37 | + main.not_found("no-such-page", self.request("https://example.test/no-such-page")) |
| 38 | + ) |
| 39 | + self.assertEqual(response.status_code, 404) |
0 commit comments