From c2f1ff7b2639873078f44d0df266c372c304b40e Mon Sep 17 00:00:00 2001 From: Alc-Alc Date: Wed, 4 Nov 2026 15:58:02 +0530 Subject: [PATCH 1/2] fix(api): serve the v1 API index as JSON only --- pydotorg/urls_api.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pydotorg/urls_api.py b/pydotorg/urls_api.py index 06ffc11ad..54527719e 100644 --- a/pydotorg/urls_api.py +++ b/pydotorg/urls_api.py @@ -3,6 +3,7 @@ from django.urls import re_path from rest_framework import routers from tastypie.api import Api +from tastypie.serializers import Serializer from apps.downloads.api import ( OSResource, @@ -15,7 +16,14 @@ from apps.pages.api import PageResource, PageViewSet from apps.sponsors.api import LogoPlacementeAPIList, SponsorshipAssetsAPIList -v1_api = Api(api_name="v1") + +class JSONOnlySerializer(Serializer): + """JSON-only serializer for the v1 API index.""" + + formats = ("json",) + + +v1_api = Api(api_name="v1", serializer_class=JSONOnlySerializer) v1_api.register(PageResource()) v1_api.register(OSResource()) v1_api.register(ReleaseResource()) From be0105587d6ac96ae758bff4642bb06937c61601 Mon Sep 17 00:00:00 2001 From: Alc-Alc Date: Wed, 4 Nov 2026 15:58:19 +0530 Subject: [PATCH 2/2] test(api): cover the v1 API index with a browser Accept header --- pydotorg/tests/test_views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pydotorg/tests/test_views.py b/pydotorg/tests/test_views.py index 1fc1bed50..2661a0fc5 100644 --- a/pydotorg/tests/test_views.py +++ b/pydotorg/tests/test_views.py @@ -60,3 +60,13 @@ def test_security_txt(self): response = self.client.get("/security.txt") self.assertRedirects(response, "/.well-known/security.txt", status_code=301, fetch_redirect_response=False) + + def test_api_v1_root_ignores_browser_accept_header(self): + url = reverse("api_v1_top_level", kwargs={"api_name": "v1"}) + browser_accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + + response = self.client.get(url, headers={"accept": browser_accept}) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response["Content-Type"], "application/json") + self.assertIn("pages/page", response.json())