diff --git a/README.md b/README.md
index 04cc3b80..86871819 100644
--- a/README.md
+++ b/README.md
@@ -131,7 +131,7 @@ docker pull ghcr.io/ithsjava25/project-webserver-juv25d:latest
## Step 3 – Run the container
```bash
-docker run -p 3000:3000 ghcr.io/ithsjava25/project-webserver-juv25d:latest
+docker run -p 8080:8080 ghcr.io/ithsjava25/project-webserver-juv25d:latest
```
---
@@ -139,10 +139,10 @@ docker run -p 3000:3000 ghcr.io/ithsjava25/project-webserver-juv25d:latest
## Step 4 – Open in browser
```
-http://localhost:3000
+http://localhost:8080
```
-The server runs on port **3000**.
+The server runs on port **8080**.
---
@@ -160,10 +160,10 @@ org.juv25d.App
3. Open:
```
-http://localhost:3000
+http://localhost:8080
```
-Note: Running the packaged JAR directly with `java -jar` is not supported, as the project is not built as a fat JAR (external dependencies such as SnakeYAML are not bundled).
+Note: The project is packaged as a fat JAR using the Maven Shade Plugin, so you can run it with `java -jar target/app.jar`.
---
@@ -327,7 +327,7 @@ Example:
```yaml
server:
- port: 3000
+ port: 8080
root-dir: static
logging:
diff --git a/pom.xml b/pom.xml
index f88056db..b87ce149 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
org.juv25d
JavaHttpServer
- 1.0.0-beta
+ 1.0-SNAPSHOT
25
@@ -58,19 +58,6 @@
maven-install-plugin
3.1.4
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.5.0
-
-
-
- true
- org.juv25d.App
-
-
-
-
org.apache.maven.plugins
maven-resources-plugin
@@ -171,6 +158,29 @@
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.1
+
+
+ package
+
+ shade
+
+
+ app
+ false
+ false
+
+
+ org.juv25d.App
+
+
+
+
+
+
diff --git a/src/main/java/org/juv25d/plugin/StaticFilesPlugin.java b/src/main/java/org/juv25d/plugin/StaticFilesPlugin.java
index 2fe3de15..00ae8012 100644
--- a/src/main/java/org/juv25d/plugin/StaticFilesPlugin.java
+++ b/src/main/java/org/juv25d/plugin/StaticFilesPlugin.java
@@ -29,3 +29,4 @@ public void handle(HttpRequest request, HttpResponse response) throws IOExceptio
response.setBody(staticResponse.body());
}
}
+
diff --git a/src/main/resources/static/README.md b/src/main/resources/static/README.md
index 2e895331..42b35656 100644
--- a/src/main/resources/static/README.md
+++ b/src/main/resources/static/README.md
@@ -1,47 +1,406 @@
-# PLACEHOLDER
+# 🚀 Java HTTP Server – Team juv25d
-# Creating a New Filter
+A lightweight, modular HTTP server built from scratch in Java.
-Filters allow you to intercept and modify HTTP requests *before* they reach the plugin, and modify responses *before* they are sent back to the client.
-They are executed in sequence through a `FilterChain`.
+This project demonstrates how web servers and backend frameworks work internally — without using Spring, Tomcat, or other high-level frameworks.
+
+The server is distributed as a Docker image via GitHub Container Registry (GHCR).
+
+---
+
+# 📌 Project Purpose
+
+The goal of this project is to deeply understand:
+
+- How HTTP works
+- How requests are parsed
+- How responses are constructed
+- How middleware (filters) operate
+- How backend frameworks structure request lifecycles
+- How static file serving works
+- How architectural decisions are documented (ADR)
+- How Java services are containerized with Docker
+
+This is an educational backend architecture project.
+
+---
+
+# ⚙ Requirements
+
+- Java 21+ (uses Virtual Threads via Project Loom)
+- Docker (for running the official container image)
+
+---
+
+# 🏗 Architecture Overview
+
+## Request Lifecycle
+
+```
+Client
+ ↓
+ServerSocket
+ ↓
+ConnectionHandler (Virtual Thread)
+ ↓
+Pipeline
+ ↓
+FilterChain
+ ↓
+Plugin
+ ↓
+HttpResponseWriter
+ ↓
+Client
+```
+
+---
+
+## 🧩 Core Components
+
+### Server
+- Listens on a configurable port
+- Accepts incoming socket connections
+- Spawns a virtual thread per request (`Thread.ofVirtual()`)
+
+### ConnectionHandler
+- Parses the HTTP request using `HttpParser`
+- Creates a default `HttpResponse`
+- Executes the `Pipeline`
+
+### Pipeline
+- Holds global filters
+- Holds route-specific filters
+- Creates and executes a `FilterChain`
+- Executes the active plugin
+
+### Filters
+Used for cross-cutting concerns such as:
+- Logging
+- Authentication
+- Rate limiting
+- Validation
+- Compression
+- Security headers
+
+### Plugin
+Responsible for generating the final HTTP response.
+
+### HttpParser
+Custom HTTP request parser that:
+- Parses request line
+- Parses headers
+- Handles `Content-Length`
+- Extracts path and query parameters
+
+### HttpResponseWriter
+Responsible for:
+- Writing status line
+- Writing headers
+- Automatically setting `Content-Length`
+- Writing response body
+
+---
+
+# 🐳 Running the Server (Official Method)
+
+The official way to run the server is via Docker using GitHub Container Registry.
+
+Docker must be installed and running.
+
+---
+
+## Step 1 – Login to GHCR
+
+```bash
+docker login ghcr.io -u
+```
+
+Use your GitHub Personal Access Token (classic) as password.
+
+---
+
+## Step 2 – Pull the latest image
+
+```bash
+docker pull ghcr.io/ithsjava25/project-webserver-juv25d:latest
+```
+
+---
+
+## Step 3 – Run the container
+
+```bash
+docker run -p 3000:3000 ghcr.io/ithsjava25/project-webserver-juv25d:latest
+```
+
+---
+
+## Step 4 – Open in browser
+
+```
+http://localhost:3000
+```
+
+The server runs on port **3000**.
+
+---
+
+# 🛠 Running in Development (IDE)
+
+For development purposes, you can run the server directly from your IDE:
+
+1. Open the project.
+2. Run the class:
+
+```
+org.juv25d.App
+```
+
+3. Open:
+
+```
+http://localhost:3000
+```
+
+Note: The project is packaged as a fat JAR using the Maven Shade Plugin, so you can run it with `java -jar target/JavaHttpServer-1.0.2-beta.jar`.
+
+---
+
+# 🌐 Static File Serving
+
+The `StaticFilesPlugin` serves files from:
+
+```
+src/main/resources/static/
+```
+
+### Example Mapping
+
+| File | URL |
+|------|------|
+| index.html | `/` |
+| css/styles.css | `/css/styles.css` |
+| js/app.js | `/js/app.js` |
+
+### Security Features
+
+- Path traversal prevention
+- MIME type detection
+- 404 handling
+- 403 handling
+- Clean URLs (no `/static/` prefix)
+
+For full architectural reasoning, see:
+
+➡ `docs/adr/ADR-001-static-file-serving-architecture.md`
+
+---
+
+# 🔄 Creating a Filter
+
+Filters intercept requests before they reach the plugin.
A filter can:
-- Inspect or modify the incoming `HttpRequest`
-- Inspect or modify the outgoing `HttpResponse`
-- Stop the chain (e.g., return a 403 or 429)
-- Allow the chain to continue by calling `chain.doFilter(req, res)`
+
+- Inspect or modify `HttpRequest`
+- Inspect or modify `HttpResponse`
+- Stop the chain (e.g., return 403)
+- Continue processing by calling `chain.doFilter(req, res)`
---
## Filter Interface
-All filters must implement:
-
```java
public interface Filter {
void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throws IOException;
}
```
-Example: LoggingFilter
-## Creating a filter
+---
+
+## Example: LoggingFilter
+
+```java
+public class LoggingFilter implements Filter {
+ @Override
+ public void doFilter(HttpRequest req, HttpResponse res, FilterChain chain) throws IOException {
+ System.out.println(req.method() + " " + req.path());
+ chain.doFilter(req, res);
+ }
+}
+```
+
+---
+
+## Registering a Global Filter
+
+```java
+pipeline.addGlobalFilter(new LoggingFilter(), 100);
+```
+
+Lower order values execute first.
+
+---
+
+# 🎯 Route-Specific Filters
+
+Route filters only execute when the request path matches a pattern.
+
+### Supported Patterns
+
+- `/api/*` → matches paths starting with `/api/`
+- `/login` → exact match
+- `/admin/*` → wildcard support (prefix-based)
+
+---
+
+## Example
+
+```java
+pipeline.addRouteFilter(new JwtAuthFilter(), 100, "/api/*");
+```
+
+---
+
+## Execution Flow
+
+```
+Client → Filter 1 → Filter 2 → ... → Plugin → Response → Client
+```
+
+---
+
+# 🧠 Creating a Plugin
+
+Plugins generate the final HTTP response.
+
+They run after all filters have completed.
+
+---
+
+## Plugin Interface
+
+```java
+public interface Plugin {
+ void handle(HttpRequest req, HttpResponse res) throws IOException;
+}
+```
+
+---
+
+## Example: HelloPlugin
+
+```java
+public class HelloPlugin implements Plugin {
+
+ @Override
+ public void handle(HttpRequest req, HttpResponse res) throws IOException {
+ res.setStatusCode(200);
+ res.setStatusText("OK");
+ res.setHeader("Content-Type", "text/plain");
+ res.setBody("Hello from juv25d server".getBytes());
+ }
+}
+```
+
+---
+
+## Registering a Plugin
+
+```java
+pipeline.setPlugin(new HelloPlugin());
+```
+
+---
+
+# ⚙ Configuration
+
+Configuration is loaded from:
+
+```
+application-properties.yml
+```
+
+Example:
+
+```yaml
+server:
+ port: 3000
+ root-dir: static
+
+logging:
+ level: INFO
+```
+
+---
+
+# 📦 Features
+
+- Custom HTTP request parser (`HttpParser`)
+- Custom HTTP response writer (`HttpResponseWriter`)
+- Mutable HTTP response model
+- Filter chain architecture
+- Plugin system
+- Static file serving
+- MIME type resolution
+- Path traversal protection
+- Virtual threads (Project Loom)
+- YAML configuration (SnakeYAML)
+- Dockerized distribution
+- Published container image (GHCR)
+
+---
+
+# 📚 Documentation & Architecture Decisions
+
+Additional technical documentation is available in the `docs/` directory.
+
+## Architecture Decision Records (ADR)
+
+Contains architectural decisions and their reasoning.
+
+```
+docs/adr/
+```
+
+Main index:
+
+```
+docs/adr/README.md
+```
-- Create a new class in src/main/java/.../filters/
-- Implement the Filter interface
-- Add your logic inside doFilter
-- Decide whether to continue the chain or stop it
+Includes:
-## Register your filter (src/org.example/App.java)
+- Static file serving architecture
+- ADR template
+- Future architecture decisions
+
+---
+
+## Technical Notes
+
+Advanced filter configuration examples:
-Register your filter using:
```
- Pipeline pipeline = new Pipeline();
- pipeline.addFilter(new LoggingFilter());
+docs/notes/
```
-## Filter execution flow
+---
+
+# 🎓 Educational Value
+
+This project demonstrates:
+
+- How web servers work internally
+- How middleware pipelines are implemented
+- How static file serving works
+- How architectural decisions are documented
+- How Java services are containerized and distributed
+
+---
+
+# 👥 Team juv25d
-Client →
- Filter 1 → Filter 2 → ... → Filter N →
- Plugin → Response →
- back through filters → Client
+Built as a learning project to deeply understand HTTP, backend systems, and modular server architecture.