Skip to content

Return JSON 404 for unknown API routes#14

Merged
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/add-json-404-handler-for-unknown-api-routes
May 4, 2026
Merged

Return JSON 404 for unknown API routes#14
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/add-json-404-handler-for-unknown-api-routes

Conversation

@ChrisAdamsdevelopment
Copy link
Copy Markdown
Owner

@ChrisAdamsdevelopment ChrisAdamsdevelopment commented May 4, 2026

Motivation

  • Ensure API clients never receive HTML 404s for unknown /api/* paths by adding an explicit JSON 404 handler because GET /api/nonexistent previously fell through to the SPA/static handlers and returned HTML.

Description

  • Added a targeted catch-all app.use('/api', ...) in server.js (inserted after existing API endpoints, including app.get('/api/health'), and before the static SPA fallback) that returns 404 with JSON {"error":"API route not found","path":req.originalUrl} and only touches server.js, leaving auth, Stripe, usage, SEO generation, cleanse logic, Docker, metadata utilities, and frontend UI unchanged.

Testing

  • Ran npm install and npm run build, started the server with NODE_ENV=development JWT_SECRET=dev_jwt_secret_change_me ENABLE_MOCK_CHECKOUT=true DB_PATH=./spectra.db FRONTEND_URL=http://localhost:5173 PORT=3001 npm start, and verified with curl that GET /api/health returned 200 JSON, GET /api/me without a token returned 401 JSON, GET /api/nonexistent returned 404 JSON with {"error":"API route not found","path":"/api/nonexistent"}, and GET /nonexistent-frontend-route still served index.html (SPA fallback) — all checks passed.

Codex Task

Summary by Sourcery

Bug Fixes:

  • Return a JSON 404 payload for unmatched /api routes to prevent HTML responses for API clients.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 4, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds a JSON 404 catch-all handler for unknown /api routes so API clients never receive HTML responses for missing endpoints, while leaving SPA/static routing behavior unchanged.

Sequence diagram for JSON 404 handling of unknown API routes

sequenceDiagram
    actor ApiClient
    participant ExpressApp
    participant ApiRoutes
    participant Api404Middleware
    participant SpaFallback

    ApiClient->>ExpressApp: HTTP GET /api/nonexistent
    ExpressApp->>ApiRoutes: Match registered /api routes
    ApiRoutes-->>ExpressApp: No matching route
    ExpressApp->>Api404Middleware: Invoke app.use('/api', ...)
    Api404Middleware-->>ApiClient: 404 JSON { error: API route not found, path: /api/nonexistent }

    %% Non API path still goes to SPA
    ApiClient->>ExpressApp: HTTP GET /nonexistent-frontend-route
    ExpressApp->>SpaFallback: Static SPA fallback
    SpaFallback-->>ApiClient: 200 HTML index.html
Loading

Flow diagram for routing between API JSON 404 and SPA fallback

flowchart TD
    A[Incoming HTTP request] --> B{Path starts with /api?}
    B -->|Yes| C{Matches existing /api route?}
    C -->|Yes| D[Handle with specific API route
status: 2xx/4xx/5xx JSON]
    C -->|No| E[API 404 middleware
status: 404 JSON
error: API route not found]
    B -->|No| F{Static file or SPA route?}
    F -->|Static asset| G[Serve static file]
    F -->|SPA route| H[Serve index.html
SPA fallback]
    F -->|No match| H
Loading

File-Level Changes

Change Details Files
Introduce a JSON 404 catch-all middleware for unknown /api routes after existing API endpoints and before SPA/static fallback.
  • Add app.use('/api', ...) middleware that matches any unmatched /api route.
  • Return HTTP 404 with JSON body containing an error message and the original request URL.
  • Place the middleware after existing API routes such as /api/health and before the distPath/static SPA fallback initialization to avoid altering current valid API or frontend routes.
server.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ChrisAdamsdevelopment ChrisAdamsdevelopment merged commit 056d6c5 into main May 4, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant