Skip to content

Make a nicer homescreen with improved design and health page#121

Open
alicewersen-rgb wants to merge 1 commit intomainfrom
feature-84-nicer-homescreen
Open

Make a nicer homescreen with improved design and health page#121
alicewersen-rgb wants to merge 1 commit intomainfrom
feature-84-nicer-homescreen

Conversation

@alicewersen-rgb
Copy link

@alicewersen-rgb alicewersen-rgb commented Mar 2, 2026

Improved the default homepage UI. Added modern styling with centered layout, card design, gradient background and a styled action button. Also ensured the health endpoint works correctly from the homepage.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added server health check endpoint accessible from the homepage
    • Redesigned homepage with improved layout and modern styling
  • Style

    • Implemented gradient background and centered card-based design
    • Added responsive styling with hover effects for better user experience

@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

The PR introduces HTTP request handling infrastructure by modifying StaticFileHandler to make handleGetRequest package-private, adding public getter methods, and implementing root path normalization. A new StaticFileHttpHandler class implements HttpHandler to delegate GET requests and return 405 for others. A TestServer startup class is added for local testing. Web UI files are introduced: health.html and an updated index.html with styled card layout.

Changes

Cohort / File(s) Summary
Static File Handler Core
src/main/java/org/example/StaticFileHandler.java
Changed handleGetRequest from private to package-private, added normalization of empty/"/" URIs to "index.html", and introduced public accessor methods getFileBytes() and getStatusCode() for exposing internal state.
HTTP Request Handler
src/main/java/org/example/StaticFileHttpHandler.java
New class implementing HttpHandler that normalizes request paths, rejects non-GET requests with 405 status, delegates GET handling to StaticFileHandler, and returns appropriate responses with file bytes or fallback 500 status.
Test Infrastructure
src/test/java/org/example/TestServer.java
New test server class with main entry point that starts an HTTP server on port 8080, registers StaticFileHttpHandler at root context, and enables local testing.
Web Content
www/index.html, www/health.html
New health.html with simple status message; index.html completely restyled with gradient background, centered card layout, responsive design, and "Check Server Health" button linking to /health.html.

Sequence Diagram

sequenceDiagram
    participant Client
    participant HttpServer as HttpServer<br/>(Context Handler)
    participant Handler as StaticFileHttpHandler
    participant FileHandler as StaticFileHandler
    participant FileSystem as FileSystem

    Client->>HttpServer: GET /health.html
    HttpServer->>Handler: handle(exchange)
    Handler->>Handler: Normalize path<br/>("/" → "index.html")
    Handler->>Handler: Check method == GET
    Handler->>FileHandler: handleGetRequest(uri)
    FileHandler->>FileSystem: Read file bytes
    FileSystem-->>FileHandler: byte[] or IOException
    FileHandler->>FileHandler: Set status & bytes
    Handler->>Handler: Retrieve getFileBytes()<br/>& getStatusCode()
    Handler->>HttpServer: sendResponseHeaders(status)
    HttpServer->>Client: HTTP Response<br/>(status + bytes)
    Handler->>HttpServer: close exchange
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • Return status code 500 #79: Modifies StaticFileHandler to replace literal HTTP status codes with HttpResponseBuilder constants, complementing this PR's access level changes and getter additions.
  • Add support for serving static files #42: Extends StaticFileHandler by adding state and internal methods; this PR's new public accessors directly expose that added state.
  • Issue/69 remove html concat #73: Implements root path normalization ("/" to "index.html"), mirroring the same normalization logic introduced here in StaticFileHttpHandler.

Suggested Reviewers

  • codebyNorthsteep
  • apaegs
  • eeebbaandersson

Poem

🐰 A handler hops in to serve files with glee,
Root paths normalize—so "/" becomes index.html, you see!
Health checks and styled cards, a server so clean,
The smoothest web request we've ever seen! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main UI/design changes in www/index.html and www/health.html, which are the primary focus of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-84-nicer-homescreen

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/main/java/org/example/StaticFileHttpHandler.java (1)

37-44: Response body output stream should be closed explicitly.

The getResponseBody() output stream should be closed before calling exchange.close(). While exchange.close() typically handles this, explicitly closing the stream ensures the response is fully flushed and follows best practices for resource management.

♻️ Suggested fix
-            exchange.sendResponseHeaders(statusCode, fileBytes.length);
-            exchange.getResponseBody().write(fileBytes);
+            exchange.sendResponseHeaders(statusCode, fileBytes.length);
+            try (var os = exchange.getResponseBody()) {
+                os.write(fileBytes);
+            }
         } else {
             fileBytes = "405 Method Not Allowed".getBytes();
             statusCode = 405;
-            exchange.sendResponseHeaders(statusCode, fileBytes.length);
-            exchange.getResponseBody().write(fileBytes);
+            exchange.sendResponseHeaders(statusCode, fileBytes.length);
+            try (var os = exchange.getResponseBody()) {
+                os.write(fileBytes);
+            }
         }
-
-        exchange.close();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/StaticFileHttpHandler.java` around lines 37 - 44,
In StaticFileHttpHandler (the method handling the HttpExchange), after writing
fileBytes to exchange.getResponseBody() in both the success and 405 branches,
explicitly close the OutputStream returned by exchange.getResponseBody() (e.g.,
call close() on it) before calling exchange.close(); ensure this is done in all
code paths (including error branches) so the response is flushed and the stream
is properly released.
www/health.html (1)

1-1: Consider using a complete HTML document structure.

This health page is just an HTML snippet while index.html is a full HTML5 document. For consistency and proper browser rendering, consider adding the standard document structure (<!DOCTYPE html>, <html>, <head>, <body> tags). This also helps with accessibility and consistent character encoding.

💡 Suggested structure
-<h1>Server is healthy! &#128522; </h1>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Health Check</title>
+</head>
+<body>
+    <h1>Server is healthy! &#128522;</h1>
+</body>
+</html>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@www/health.html` at line 1, The health page currently contains only an H1
snippet; update the file to be a complete HTML5 document by adding <!DOCTYPE
html>, wrapping content in <html> and <body> tags, and include a <head> with a
<meta charset="utf-8"> and a <title> (e.g., "Health") so the existing <h1>Server
is healthy! 😊</h1> is placed inside the body; ensure the structure mirrors
index.html for consistency and proper rendering/accessibility.
src/main/java/org/example/StaticFileHandler.java (1)

27-31: Duplicate normalization logic exists in StaticFileHttpHandler.

The path normalization for empty/root paths to index.html is implemented here (lines 29-31) and also duplicated in StaticFileHttpHandler (lines 21-25). This redundancy could lead to maintenance issues if the logic diverges.

Consider keeping the normalization in one place only.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/StaticFileHandler.java` around lines 27 - 31, The
root/empty-path normalization to "index.html" is duplicated between
StaticFileHandler.handleGetRequest and StaticFileHttpHandler; refactor to a
single implementation and call it instead of duplicating logic. Extract the
normalization into a shared method (e.g., StaticFileHandler.normalizePath or a
new util like StaticFileUtils.normalizeIndexPath) or move the logic into
StaticFileHttpHandler and have StaticFileHandler.handleGetRequest call that
shared method; then remove the duplicate conditional in handleGetRequest so only
the single referenced function performs the "/" -> "index.html" mapping. Ensure
both classes reference the exact shared method name so future changes remain
centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/org/example/StaticFileHandler.java`:
- Around line 13-14: The instance fields fileBytes and statusCode in
StaticFileHandler are not thread-safe; refactor handleGetRequest to return an
immutable result object (e.g., FileResponse with byte[] bytes and int status)
instead of writing to instance fields, remove or deprecate
getFileBytes()/getStatusCode() so no shared mutable state is used, and update
StaticFileHttpHandler to call StaticFileHandler.handleGetRequest(...) and use
the returned FileResponse to form the HTTP response. Ensure FileResponse is
immutable (final fields) and contains all data previously held in the instance
fields.

In `@src/main/java/org/example/StaticFileHttpHandler.java`:
- Around line 11-13: The current StaticFileHttpHandler stores a single
StaticFileHandler instance (created in the StaticFileHttpHandler() constructor)
which leads to race conditions because StaticFileHandler mutates
fileBytes/statusCode across requests; fix by instantiating a new
StaticFileHandler for each incoming request instead of reusing the shared
handler—update the code paths that call handler.handleGetRequest(...) to
construct new StaticFileHandler() locally (or alternatively change
handleGetRequest to return an immutable result object containing fileBytes and
statusCode and remove mutable fields), referencing the StaticFileHttpHandler
constructor, the handler field, StaticFileHandler, and handleGetRequest when
making the change.

---

Nitpick comments:
In `@src/main/java/org/example/StaticFileHandler.java`:
- Around line 27-31: The root/empty-path normalization to "index.html" is
duplicated between StaticFileHandler.handleGetRequest and StaticFileHttpHandler;
refactor to a single implementation and call it instead of duplicating logic.
Extract the normalization into a shared method (e.g.,
StaticFileHandler.normalizePath or a new util like
StaticFileUtils.normalizeIndexPath) or move the logic into StaticFileHttpHandler
and have StaticFileHandler.handleGetRequest call that shared method; then remove
the duplicate conditional in handleGetRequest so only the single referenced
function performs the "/" -> "index.html" mapping. Ensure both classes reference
the exact shared method name so future changes remain centralized.

In `@src/main/java/org/example/StaticFileHttpHandler.java`:
- Around line 37-44: In StaticFileHttpHandler (the method handling the
HttpExchange), after writing fileBytes to exchange.getResponseBody() in both the
success and 405 branches, explicitly close the OutputStream returned by
exchange.getResponseBody() (e.g., call close() on it) before calling
exchange.close(); ensure this is done in all code paths (including error
branches) so the response is flushed and the stream is properly released.

In `@www/health.html`:
- Line 1: The health page currently contains only an H1 snippet; update the file
to be a complete HTML5 document by adding <!DOCTYPE html>, wrapping content in
<html> and <body> tags, and include a <head> with a <meta charset="utf-8"> and a
<title> (e.g., "Health") so the existing <h1>Server is healthy! 😊</h1> is
placed inside the body; ensure the structure mirrors index.html for consistency
and proper rendering/accessibility.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9c69a4 and a88d957.

📒 Files selected for processing (5)
  • src/main/java/org/example/StaticFileHandler.java
  • src/main/java/org/example/StaticFileHttpHandler.java
  • src/test/java/org/example/TestServer.java
  • www/health.html
  • www/index.html

Comment on lines 13 to 14
private byte[] fileBytes;
private int statusCode;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Thread-safety issue: instance state is not safe for concurrent requests.

The fileBytes and statusCode fields are instance variables that are written in handleGetRequest and read via getters. If a single StaticFileHandler instance is shared across concurrent requests (which happens in StaticFileHttpHandler), a race condition occurs:

  1. Thread A calls handleGetRequest, sets fileBytes/statusCode
  2. Thread B calls handleGetRequest, overwrites the fields
  3. Thread A calls getFileBytes()/getStatusCode() — reads Thread B's values

Since com.sun.net.httpserver.HttpServer handles requests concurrently, this will cause incorrect responses.

🔒 Recommended fix: return a result object instead of using instance state
+record FileResponse(byte[] fileBytes, int statusCode) {}

-    private byte[] fileBytes;
-    private int statusCode;
...
-    void handleGetRequest(String uri) throws IOException {
+    FileResponse handleGetRequest(String uri) throws IOException {
+        byte[] fileBytes;
+        int statusCode;
...
-            return;
+            return new FileResponse(fileBytes, statusCode);
         }
...
-        }
+        return new FileResponse(fileBytes, statusCode);
     }

-    public byte[] getFileBytes() { return fileBytes; }
-    public int getStatusCode() { return statusCode; }

Then update StaticFileHttpHandler to use the returned FileResponse.

Based on learnings: thread-safe patterns are required for shared state accessed by multiple request threads.

Also applies to: 75-76

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/StaticFileHandler.java` around lines 13 - 14, The
instance fields fileBytes and statusCode in StaticFileHandler are not
thread-safe; refactor handleGetRequest to return an immutable result object
(e.g., FileResponse with byte[] bytes and int status) instead of writing to
instance fields, remove or deprecate getFileBytes()/getStatusCode() so no shared
mutable state is used, and update StaticFileHttpHandler to call
StaticFileHandler.handleGetRequest(...) and use the returned FileResponse to
form the HTTP response. Ensure FileResponse is immutable (final fields) and
contains all data previously held in the instance fields.

Comment on lines +11 to +13
public StaticFileHttpHandler() {
this.handler = new StaticFileHandler();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Shared handler instance causes thread-safety issues.

The StaticFileHandler instance is created once and reused for all requests. As noted in the StaticFileHandler review, this causes race conditions when concurrent requests access the shared fileBytes/statusCode state.

Either create a new StaticFileHandler per request, or refactor handleGetRequest to return a result object.

🔒 Quick fix: create handler per request
-    private final StaticFileHandler handler;
-
-    public StaticFileHttpHandler() {
-        this.handler = new StaticFileHandler();
-    }
+    public StaticFileHttpHandler() {
+    }

     `@Override`
     public void handle(HttpExchange exchange) throws IOException {
+        StaticFileHandler handler = new StaticFileHandler();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/StaticFileHttpHandler.java` around lines 11 - 13,
The current StaticFileHttpHandler stores a single StaticFileHandler instance
(created in the StaticFileHttpHandler() constructor) which leads to race
conditions because StaticFileHandler mutates fileBytes/statusCode across
requests; fix by instantiating a new StaticFileHandler for each incoming request
instead of reusing the shared handler—update the code paths that call
handler.handleGetRequest(...) to construct new StaticFileHandler() locally (or
alternatively change handleGetRequest to return an immutable result object
containing fileBytes and statusCode and remove mutable fields), referencing the
StaticFileHttpHandler constructor, the handler field, StaticFileHandler, and
handleGetRequest when making the change.

@Kathify Kathify self-requested a review March 8, 2026 11:49
Copy link

@Kathify Kathify left a comment

Choose a reason for hiding this comment

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

Snyggt jobbat!
En tanke: just nu gör både StaticFileHandler och StaticFileHttpHandler samma (t.ex. index.html och /). Det vore kanske snyggare att flytta allt till StaticFileHandler så vi slipper dubbelkod

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