Skip to content

fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for root directory. (fixes #1011; fixes #1014).#1015

Merged
junhaoliao merged 3 commits into
y-scope:mainfrom
junhaoliao:static-routes-fix
Jun 16, 2025
Merged

Conversation

@junhaoliao

@junhaoliao junhaoliao commented Jun 15, 2025

Copy link
Copy Markdown
Member

Description

  1. Revert changes done in server/settings.json in refactor(new-webui): Enhance server implementation with Fastify toolchain. #899 .
  2. Fix path resolution for rootDirname.
  3. Register React SPA routes in Fastify server.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  1. Start CLP package. Then ./stop-clp.sh log_viewer_webui.
  2. cd clp-package/var/data/streams; touch hello
  3. cd components/log-viewer-webui/client; npm run build
  4. cd components/log-viewer-webui/yscope-log-viewer; npm run build
  5. cd components/log-viewer-webui/server; cp .env .env.local. Then modified value of CLP_DB_PASS in .env.local to match clp-package/etc/credentials.yml. (need the fix in feat(new-webui): Enable configuration override in Fastify dotenv settings (fixes #1010). #1013 for values to be correctly overridden)
  6. npm run start
  7. Then accessed these paths in the browser and observed no 404 errors:

Summary by CodeRabbit

  • Bug Fixes

    • Improved support for single-page application (SPA) routing, ensuring all unmatched routes correctly serve the main page.
    • Adjusted static file serving behaviour for greater reliability and compatibility.
  • Chores

    • Updated directory configuration paths for better alignment with the current project structure.

@junhaoliao junhaoliao requested a review from a team as a code owner June 15, 2025 21:56
@coderabbitai

coderabbitai Bot commented Jun 15, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

The changes update directory paths in the server configuration and modify the static file serving logic in the server's routing. The static route handling now includes a broader catch-all for SPA routing, adjusts directory resolution, and changes the decorateReply behaviour for certain routes. No exported functions or types were altered.

Changes

File(s) Change Summary
components/log-viewer-webui/server/settings.json Updated directory paths for ClientDir, LogViewerDir, and StreamFilesDir to be one level closer.
components/log-viewer-webui/server/src/routes/static.ts Changed root dir resolution, adjusted decorateReply for static routes, replaced /streamFile GET with catch-all.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server
    participant FileSystem

    Client->>Server: Request static file (e.g., /streams/...)
    Server->>FileSystem: Resolve file path (new root resolution)
    FileSystem-->>Server: Return file
    Server-->>Client: Serve static file

    Client->>Server: Request unknown route (e.g., /some/spa/route)
    Server->>FileSystem: Read index.html
    FileSystem-->>Server: Return index.html
    Server-->>Client: Serve index.html (SPA fallback)
Loading

Possibly related PRs


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 369b391 and b7da097.

📒 Files selected for processing (1)
  • components/log-viewer-webui/server/src/routes/static.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/server/src/routes/static.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: davemarco
PR: y-scope/clp#1015
File: components/log-viewer-webui/server/src/routes/static.ts:65-70
Timestamp: 2025-06-16T13:05:27.337Z
Learning: In components/log-viewer-webui/server/src/routes/static.ts, when decorateReply is set to true in fastifyStatic configuration, the reply.sendFile() method automatically uses the root directory configured in the static plugin registration, eliminating the need to pass the root directory as a second parameter.
components/log-viewer-webui/server/src/routes/static.ts (1)
Learnt from: davemarco
PR: y-scope/clp#1015
File: components/log-viewer-webui/server/src/routes/static.ts:65-70
Timestamp: 2025-06-16T13:05:27.337Z
Learning: In components/log-viewer-webui/server/src/routes/static.ts, when decorateReply is set to true in fastifyStatic configuration, the reply.sendFile() method automatically uses the root directory configured in the static plugin registration, eliminating the need to pass the root directory as a second parameter.
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: lint-check (ubuntu-latest)
  • GitHub Check: lint-check (macos-latest)
🔇 Additional comments (2)
components/log-viewer-webui/server/src/routes/static.ts (2)

18-20: Verify new rootDirname resolution – four-level ascent may break packaged paths

Switching to path.resolve(dirname, "../../../..") jumps up four directories instead of the previous three. If any relative paths in settings.json were authored assuming the old base, they will now resolve one level higher and could 404 in production packages or Docker images.

Please confirm with an end-to-end build (server + web UI) that:

  1. StreamFilesDir, LogViewerDir, and ClientDir still point to existing folders at runtime.
  2. No absolute paths are accidentally constructed outside the repository.

56-59: Catch-all route looks good – ensure it stays after every other handler

Registering fastify.get("/*") after the static plugin correctly forwards unknown routes to index.html, enabling deep-linking in the SPA. No issues spotted here. 👍

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
components/log-viewer-webui/server/src/fastify-v2/plugins/external/env.ts (1)

62-69: 🧹 Nitpick (assertive)

override: true may unexpectedly clobber real env vars

Setting override: true means values in .env* files will always win over variables already present in the process environment (e.g., those injected by Kubernetes / Docker secrets).
If that is not explicitly required, consider keeping the default (false) or driving it off a separate flag so operators can opt-in.

-        override: true,
+        override: process.env.CLP_DOTENV_OVERRIDE === "1",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c9f373 and 369b391.

📒 Files selected for processing (3)
  • components/log-viewer-webui/server/settings.json (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/external/env.ts (1 hunks)
  • components/log-viewer-webui/server/src/routes/static.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/server/src/fastify-v2/plugins/external/env.ts
  • components/log-viewer-webui/server/src/routes/static.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: lint-check (macos-latest)
  • GitHub Check: lint-check (ubuntu-latest)
🔇 Additional comments (2)
components/log-viewer-webui/server/settings.json (1)

13-16: Confirm new path hierarchy is still valid after the rootDirname jump

ClientDir, LogViewerDir, and StreamFilesDir were each pulled one level closer, while rootDirname in static.ts moved two levels up. Please double-check that the resulting path.resolve(rootDirname, <dir>) still points to the intended folders once the server is started from the production bundle – an off-by-one here will silently 404 every static asset.

components/log-viewer-webui/server/src/routes/static.ts (1)

29-34: Root directory changed from “server” to “components” – verify packaging scripts

Jumping four levels up (../../../..) means rootDirname is now <repo>/components, not <repo>/components/log-viewer-webui/server.
This is fine as long as all paths in settings.json were re-based accordingly, but it will break if any other module still resolves paths relative to the old location.

Comment thread components/log-viewer-webui/server/src/routes/static.ts Outdated
Comment on lines 59 to 63
await fastify.register(fastifyStatic, {
prefix: "/",
root: clientDir,
decorateReply: false,
decorateReply: true,
wildcard: false,

@coderabbitai coderabbitai Bot Jun 15, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

wildcard: false blocks JS/CSS asset delivery

With prefix: "/" and wildcard: false the plugin only serves the root path /.
Requests like /assets/index-1234.js (generated by Vite/React) will bypass the static handler and fall straight to 404.
Unless another plugin serves those files, flip the flag back:

-            wildcard: false,
+            // allow hashed asset files under /
+            wildcard: true,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await fastify.register(fastifyStatic, {
prefix: "/",
root: clientDir,
decorateReply: false,
decorateReply: true,
wildcard: false,
await fastify.register(fastifyStatic, {
prefix: "/",
root: clientDir,
decorateReply: true,
// allow hashed asset files under /
wildcard: true,
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/routes/static.ts around lines 59 to
63, the fastifyStatic plugin is configured with wildcard: false and prefix: "/",
which causes requests for JS/CSS assets under paths like /assets/index-1234.js
to bypass the static handler and result in 404 errors. To fix this, change
wildcard to true so that all asset requests under the prefix are properly served
by the static plugin.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@davemarco why we had it disabled? and do you know why the assets were still getting served even with it disabeld?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

when i was looking how to get the log viewer connector served under streamFile, it seemed like u had to disable it to have SPA fallback. I think it still serves other files in the directory, as long as they are there at build time.

https://github.com/fastify/fastify-static?tab=readme-ov-file#wildcard

@davemarco davemarco Jun 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If false, it globs the filesystem for all defined files in the served folder (${root}//) and creates the necessary routes, but will not serve newly added files.

if i understand correctly, this means the routes to serve all static files are created at init time which makes the serving deterministic for assets files

now we are adding a catch all route to serve index.html on any misses

all seems good then

@junhaoliao junhaoliao requested a review from davemarco June 15, 2025 22:02
@davemarco

Copy link
Copy Markdown
Contributor

Is there a specific reason to modify path resolution for rootDirname? was it not working in the package?

@davemarco

Copy link
Copy Markdown
Contributor

@junhaoliao

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what is the purpose of the decorate reply change?

@junhaoliao junhaoliao Jun 16, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

https://github.com/fastify/fastify-static?tab=readme-ov-file#disabling-reply-decorator

decorateReply is by default true in the fastify-static plugin; however, when we register the plugin multiple times to serve static files on different routes from different paths, only one instance of the registration can specify decorateReply.

since we will only be calling sendFile to send files on / to serve the React SPA client, we should set decorateReply on the / fastify-static registration instance. the previous decoration on the /streams registration instance was unnecessary and unused anyways.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are we not also sending files on the /streams directory?

@davemarco davemarco Jun 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

like i understand what it does, but not why we are changing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh is it related to removing the client_dir change u made before?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Are we not also sending files on the /streams directory?

we are

Oh is it related to removing the client_dir change u made before?

right. see below

like i understand what it does, but not why we are changing

we need to call reply.sendFile() to serve the index.html file for all requests on /*. we can only set decorateReply: true on a single registration of the fastify-static plugin, and this should be done only with

        await fastify.register(fastifyStatic, {
            prefix: "/",
            root: clientDir,
            decorateReply: true,
            wildcard: false,
        });

@junhaoliao

Copy link
Copy Markdown
Member Author

Is there a specific reason to modify path resolution for rootDirname? was it not working in the package?

the paths were not resolving as expected in debug mode when i directly run npm run start. for the package, since we specify absolute paths in settings.json, how we change the rootDirname resolution should not impact the behaviour in the package.

see #1014 for the context

…t routes; Serve index.html for all unmatched routes.
@junhaoliao junhaoliao requested a review from davemarco June 16, 2025 16:18
@davemarco

davemarco commented Jun 16, 2025

Copy link
Copy Markdown
Contributor

fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for root directory. (fixes #1011; fixes #1014).

@junhaoliao junhaoliao changed the title fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for rootDirname (fixes #1011; fixes #1014). fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for root directory. (fixes #1011; fixes #1014). Jun 16, 2025
@junhaoliao junhaoliao changed the title fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for root directory. (fixes #1011; fixes #1014). fix(new-webui): Register React SPA routes in Fastify server; Fix path resolution for root directory. (fixes #1011; fixes #1014). Jun 16, 2025
@junhaoliao junhaoliao merged commit b67d048 into y-scope:main Jun 16, 2025
9 of 10 checks passed
@junhaoliao junhaoliao deleted the static-routes-fix branch June 16, 2025 16:37
junhaoliao added a commit to junhaoliao/clp that referenced this pull request May 17, 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.

2 participants