Skip to content

Return JSON for 404s, matching the rest of the API#444

Open
c-tonneslan wants to merge 2 commits into
mysociety:masterfrom
c-tonneslan:fix/json-404-handler
Open

Return JSON for 404s, matching the rest of the API#444
c-tonneslan wants to merge 2 commits into
mysociety:masterfrom
c-tonneslan:fix/json-404-handler

Conversation

@c-tonneslan
Copy link
Copy Markdown

Per #421 and @dracos' comment there, hitting a URL the router doesn't recognise currently falls through to Django's HTML 404 page even though the docs say the API always returns JSON. handler500 is already wired up to mapit.shortcuts.json_500; just mirror the pattern with a json_404 and register it as handler404.

get_object_or_404 still goes through ViewException so endpoint-level 404s are unchanged.

Closes #421.

handler500 already routes 500s through output_json so API clients
get a real error dict back. handler404 was the Django default,
so any request that didn't match a URL pattern got the framework's
HTML page back instead, even though the docs say MapIt always
returns JSON.

Mirror the pattern: add json_404 alongside json_500 and register
it as handler404 in project/urls.py.

Closes mysociety#421.

Signed-off-by: Charlie Tonneslan <cst0520@gmail.com>
@dracos
Copy link
Copy Markdown
Member

dracos commented May 18, 2026

Thanks for your contribution, but I'm afraid this is too broad - we would still want people coming to the website and going to a page that doesn't exist (for whatever reason) to get a normal HTML 404 page, not a JSON response, which would only be for the API endpoints. Perhaps the solution is to allow more things through the url handler, and then have them dealt with there.

Drop the global handler404 and instead match catch-all patterns for
the API URL prefixes (postcode, area, areas, point, nearest, code,
generations, types) at the end of mapit/urls.py. Non-API URLs keep
falling through to the project-level HTML 404 page.

Signed-off-by: Charlie Tonneslan <cst0520@gmail.com>
@c-tonneslan
Copy link
Copy Markdown
Author

Good point, thanks. I dropped the global handler404 and added catch-all patterns at the end of mapit/urls.py for the API URL prefixes (postcode, area, areas, point, nearest, code, generations, types). Anything not matching one of those prefixes still falls through to the project-level HTML 404.

Spot-checked with the regexes locally:

  • /postcode/F-54110 (the one from API returns HTML for 404s #421) → JSON 404
  • /postcode/SW1A1AA → unchanged
  • /postcode/ → still the HTML form page
  • /generations.xml → JSON 404
  • /generations.json → unchanged
  • /random-path → HTML 404

Let me know if you'd rather inline the catch-all view instead of keeping json_404 next to json_500 in shortcuts.

@dracos
Copy link
Copy Markdown
Member

dracos commented May 18, 2026

I like the idea of fixing this one, thanks, hope to be able to take a look at it soon.

@dracos dracos reopened this May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API returns HTML for 404s

2 participants