This repository contains a lightweight, educational web framework built in plain Java. It turns a raw TCP socket server into a tiny framework capable of:
- Defining REST endpoints with lambdas (GET/POST/PUT/PATCH/DELETE)
- Parsing requests (method, path, HTTP version, headers, query params, and optional JSON body)
- Serving static files from a configurable folder with basic MIME type support
Project by Tomas Felipe Panqueva for the TDSE course at the Escuela Colombiana de Ingeniería, under Professor Luis Daniel Benavides.
Repository URL: https://github.com/T-hash06/native-web-server
Prerequisites:
- Java 17+
- Maven 3.8+
- Linux/macOS/Windows shell
Commands:
- Clone the repository
- Build the project
- Run the app
git clone https://github.com/T-hash06/native-web-server
cd native-web-server
mvn clean package
mvn exec:java
By default, the server starts on port 8080 and serves static files from src/main/resources/static
(as configured in web/App.java
).
Try it:
- Static file: http://localhost:8080/hello.txt
- REST examples (implemented in
App.java
):GET /ping
→ "GET pong"POST /ping
→ "POST pong"PATCH /ping
→ "PATCH pong"
.
├─ pom.xml # Maven project descriptor (deps, plugins, Java 17)
├─ src/
│ ├─ main/
│ │ ├─ java/
│ │ │ └─ web/
│ │ │ ├─ App.java # Application entrypoint (configures server, routes, and starts it)
│ │ │ └─ server/
│ │ │ ├─ WebServer.java # Core HTTP server, router, and static file handler
│ │ │ ├─ Handler.java # Functional interface for endpoint lambdas
│ │ │ ├─ HttpMethod.java # HTTP verb enum
│ │ │ ├─ Request.java # HTTP request parser (start line, headers, query, JSON body)
│ │ │ └─ Response.java # HTTP response holder (status, headers, body)
│ │ └─ resources/
│ │ └─ static/
│ │ └─ hello.txt # Example static asset served at /hello.txt
│ └─ test/
│ └─ java/ # JUnit test sources (AppTest placeholder)
└─ target/ # Maven build output
This project favors a small, readable design over frameworks or containers. The pieces fit together as follows:
-
WebServer (core)
- Listens on a TCP port with
ServerSocket
- Parses incoming HTTP requests into a
Request
object - Routes requests to registered handlers using an in-memory router
- Router structure:
Map<String, Map<HttpMethod, Handler>>
- First key: path (e.g., "/ping")
- Second key: HTTP method (GET/POST/…)
- Value: a
Handler
lambda to run
- Router structure:
- If no handler matches, attempts to serve a static file from
STATIC_PATH + requestPath
- Determines Content-Type with a small MIME type helper
- Serializes a
Response
to the client (status line, headers, body)
- Listens on a TCP port with
-
Handler (functional interface)
- Signature:
void handle(Request request, Response response)
- Enables concise lambdas when registering routes, e.g.:
server.get("/ping", (req, res) -> res.setBody("GET pong"));
- Signature:
-
Request (parser and accessors)
- Extracts:
- HTTP method, path, and version from the request line
- Headers into a
Map<String, String>
- Query parameters into a
Map<String, String>
viaparseQueryParams
- Optional JSON body (if present) parsed with Jackson into
Map<String, ?>
- Factory methods:
fromBufferedReader(...)
reads the raw HTTP message from the socketfromString(...)
builds aRequest
object from the raw message
- Extracts:
-
Response (builder-like data holder)
- Defaults to
200 OK
- Supports setting status, headers, and body
- Convenience overloads for
setBody(String)
andsetBody(byte[])
- Defaults to
-
Static files
STATIC_PATH
points to the folder containing static assets- If there’s no matching route, the server looks for a file at
STATIC_PATH + path
- A basic set of MIME types is supported (html, css, js, png, jpg/jpeg, gif, svg, ico, mp4, json, plain text)
The assignment’s spirit is captured, with a few personal touches in the API shape:
-
GET method for REST services
- Implemented as instance methods on
WebServer
:get
,post
,put
,patch
,delete
- Usage in
App.java
:WebServer server = new WebServer(8080, "src/main/resources/static"); server.get("/ping", (req, res) -> res.setBody("GET pong")); server.post("/ping", (req, res) -> res.setBody("POST pong")); server.patch("/ping", (req, res) -> res.setBody("PATCH pong")); server.start();
- Implemented as instance methods on
-
Query value extraction mechanism
- Available via
Request#getQueryParams()
- Example:
server.get("/hello", (req, res) -> { String name = req.getQueryParams().getOrDefault("name", "world"); res.setBody("Hello " + name); });
- Available via
-
Static file location specification
- Can be set via constructor or fluent builder:
new WebServer(8080, "src/main/resources/static"); // or new WebServer().port(8080).staticPath("src/main/resources/static");
- Place assets under that folder (e.g.,
src/main/resources/static/index.html
) and access them directly:GET /index.html
- Can be set via constructor or fluent builder:
-
Example routes from the assignment
- With this framework you can implement:
server.get("/hello", (req, res) -> { res.setBody("Hello " + req.getQueryParams().get("name")); }); server.get("/pi", (req, res) -> { res.setBody(String.valueOf(Math.PI)); });
- Then call:
- With this framework you can implement:
- Maven (
pom.xml
)- Java 17 compilation
- Exec plugin configured to run
web.App
- Dependency: Jackson Databind for JSON parsing
- Static resources
- During development, the example uses
src/main/resources/static
directly - Alternatively, you may point
STATIC_PATH
totarget/classes/static
to serve the compiled classpath resources aftermvn package
- During development, the example uses
- The HTTP parser is intentionally minimal and assumes well-formed requests. Hardening (timeouts, partial reads, chunked encoding, invalid lines) would improve robustness.
- The router currently matches exact paths. Pattern matching and path parameters (e.g.,
/users/:id
) can be added. - Add content negotiation helpers and more MIME types.
- Add unit tests for parsing and routing, plus integration tests for static files.
- Consider concurrency (thread-per-connection or a small thread pool) for higher throughput.
Created by Tomas Felipe Panqueva for the TDSE course at Escuela Colombiana de Ingeniería. Instructor: Professor Luis Daniel Benavides.