Skip to content

fix(gateway): serve pre-rendered directories before SPA fallback#32

Merged
olamide226 merged 1 commit intomainfrom
fix/gateway-spa-try-files
Mar 15, 2026
Merged

fix(gateway): serve pre-rendered directories before SPA fallback#32
olamide226 merged 1 commit intomainfrom
fix/gateway-spa-try-files

Conversation

@olamide226
Copy link
Copy Markdown
Contributor

Summary

  • The embedded-mode file server previously rewrote all extension-less paths to /, so only the root index.html was ever served — regardless of URL
  • Frameworks that emit per-route directories with index.html (Next.js with trailingSlash, Gatsby, Hugo, etc.) were broken: users always saw the landing page
  • Apply a try_files-style lookup (equivalent to nginx try_files $uri $uri/ /index.html): check whether the requested path maps to a directory containing index.html on disk before falling back to root
  • Pure-SPA fallback (Vite, CRA, etc.) remains fully intact — only extension-less paths with a matching dir/index.html on disk are served directly

How it works

Request Disk state Before After
/signin/ signin/index.html exists Root index.html (wrong) signin/index.html
/signin signin/index.html exists Root index.html 301 → /signin/signin/index.html
/dashboard No dir on disk (pure SPA) Root index.html Root index.html (unchanged)
/app.js Static asset Served directly Served directly (unchanged)
/missing.js Doesn't exist 404 404 (unchanged)

Test plan

  • TestFileServer_RootServesIndexHTML — root serves index.html
  • TestFileServer_StaticAssetServedDirectly — files with extensions served as-is
  • TestFileServer_PrerenderedDirWithTrailingSlash/signin/ serves signin/index.html
  • TestFileServer_PrerenderedDirWithoutTrailingSlash/signin redirects to /signin/
  • TestFileServer_SPAFallbackForUnknownRoute — unknown routes fall back to root
  • TestFileServer_SPAFallbackForTrailingSlashNoDir — trailing slash with no dir falls back (pure SPA)
  • TestFileServer_MissingStaticAsset404 — missing assets with extensions return 404
  • TestFileServer_DirWithoutIndexHTMLFallsBack — dir without index.html falls back to root (no dir listing)
  • Full go test ./... passes

The embedded-mode file server previously rewrote all extension-less
paths to / unconditionally, so only root index.html was ever served.
This broke frameworks that emit per-route directories with index.html
(Next.js with trailingSlash, Gatsby, Hugo, etc.) — users always saw
the landing page regardless of the URL.

Apply a try_files-style lookup (equivalent to nginx try_files $uri
$uri/ /index.html): check whether the requested path maps to a
directory containing index.html on disk before falling back to the
root. This keeps pure-SPA fallback intact (Vite, CRA) while correctly
serving pre-rendered pages for SSG frameworks.
Copilot AI review requested due to automatic review settings March 15, 2026 01:21
@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 15, 2026

Analyzing 200 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 15, 2026

❌ Analysis Failed

`Invalid request.

"sha" wasn't supplied. - https://docs.github.com/rest/repos/contents#create-or-update-file-contents`

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes the embedded-mode file server to support pre-rendered per-route directories (e.g., from Next.js with trailingSlash, Gatsby, Hugo) by implementing a try_files-style lookup before falling back to the SPA root index.html. Previously, all extension-less paths were unconditionally rewritten to /, breaking frameworks that emit dir/index.html for each route.

Changes:

  • Added a filesystem check in createFileServer to detect directories with index.html and serve them directly, falling back to root index.html only when no matching directory exists
  • Added comprehensive tests covering pre-rendered directories, SPA fallback, static assets, 404s, and directory listing prevention
  • Added test fixture files (signin/index.html, style.css) to support the new tests

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
gateway/internal/server/server.go Added try_files-style directory check before SPA fallback in the file server handler
gateway/internal/server/server_test.go Added 8 tests covering all routing scenarios for the SPA-aware file server
gateway/testdata/static/signin/index.html Test fixture: pre-rendered page for /signin/ route
gateway/testdata/static/style.css Test fixture: static CSS asset

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gateway/internal/server/server_test.go
@olamide226 olamide226 merged commit b448534 into main Mar 15, 2026
13 checks passed
@olamide226 olamide226 deleted the fix/gateway-spa-try-files branch March 15, 2026 01:33
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.

2 participants