Skip to content

T-hash06/native-web-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Native Web Server – Minimal Java Web Framework for REST + Static Files

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


How to run

Prerequisites:

  • Java 17+
  • Maven 3.8+
  • Linux/macOS/Windows shell

Commands:

  1. Clone the repository
  2. Build the project
  3. 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"

Folder structure

.
├─ 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

Architecture overview

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
    • 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)
  • 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"));
  • 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> via parseQueryParams
      • Optional JSON body (if present) parsed with Jackson into Map<String, ?>
    • Factory methods:
      • fromBufferedReader(...) reads the raw HTTP message from the socket
      • fromString(...) builds a Request object from the raw message
  • Response (builder-like data holder)

    • Defaults to 200 OK
    • Supports setting status, headers, and body
    • Convenience overloads for setBody(String) and setBody(byte[])
  • 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)

How it maps to the assignment

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();
  • 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);
      });
  • 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
  • Example routes from the assignment


Configuration and build

  • 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 to target/classes/static to serve the compiled classpath resources after mvn package

Notes and future improvements

  • 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.

Credits

Created by Tomas Felipe Panqueva for the TDSE course at Escuela Colombiana de Ingeniería. Instructor: Professor Luis Daniel Benavides.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages