Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

9 Commits

Repository files navigation

⚡ Lambda REST Microframework

A lightweight Java web microframework that enables developers to build REST services using lambda functions, extract query parameters, and serve static files — all powered by raw Java sockets with zero external dependencies.

JavaMavenTestsLicense

📸 Screenshots

Server Startup

Server StartupServer starting with registered routes and configuration details

Static File Serving (index.html)

Static FilesInteractive web page served from the static files directory

REST API - Hello Service

Hello ServiceHello Service WebPageGET /App/hello?name=Pedro returning a personalized greeting

REST API - PI Service

PI ServicePI Service WebPageGET /App/pi returning the value of Math.PI

REST API - Greeting Page

GreetingGreeting WebPageGET /App/greeting?name=Pedro returning an HTML greeting page

REST API - Time Server

Time ServerGET /App/time returning the current time server

Unit Tests Results

TestsAll 101 unit tests passing with BUILD SUCCESS


✨ Key Features

FeatureDescription
🔧 Lambda REST ServicesDefine GET endpoints with get("/path", (req, resp) -> "response")
🔍 Query Parameter ExtractionAccess query values with req.getValues("name")
📁 Static File ServingConfigure static directory with staticfiles("/webroot")
Zero DependenciesBuilt with pure Java sockets — no Spring, no Jetty, no external libs
🧪 Fully Tested101 unit tests covering all framework components
📄 Multi-format Static FilesServes .html, .css, .js, .png, .jpg, .gif, .svg, .ico, .json

🚀 Getting Started

These instructions will give you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

Requirements for running the project:

RequirementDescription
Java 17+JDK for compiling and running
Maven 3.9+Build automation tool
GitVersion control

Installing

A step-by-step guide to get the development environment running:

  1. Clone the repository

    git clone https://github.com/AnderssonProgramming/lambda-rest-microframework.git
    cd lambda-rest-microframework
  2. Build the project

    mvn clean compile
  3. Run the tests

    mvn test
  4. Start the server

    mvn exec:java
  5. Open your browser and test

    URLDescription
    http://localhost:8080/index.htmlStatic HTML page with interactive demo
    http://localhost:8080/App/hello?name=PedroREST greeting service
    http://localhost:8080/App/piREST service returning PI
    http://localhost:8080/App/greeting?name=WorldHTML greeting page
    http://localhost:8080/App/timeServer time service
    http://localhost:8080/App/echo?msg=test&from=userEcho query parameters

📖 Introduction and Motivation

This project enhances a basic Java HTTP server into a fully functional web microframework that supports REST service development through lambda functions. The framework is inspired by lightweight frameworks like Spark Java, providing a minimal but powerful API for building web applications.

What is a Web Microframework?

A microframework provides the essential tools for web development without the overhead of full-featured frameworks:

📝 Request → 🔀 Router → ⚡ Lambda Handler → 📦 Response
↓
📁 Static Files
  1. Routing — Maps URL paths to handler functions
  2. Request Parsing — Extracts HTTP method, path, query parameters, and headers
  3. Static File Serving — Delivers HTML, CSS, JS, and images from a configured directory
  4. Response Generation — Builds proper HTTP responses with status codes and content types

Why This Approach?

ComponentTechnologyWhy?
LanguageJava 17Modern features, lambda support, strong typing
NetworkingRaw Sockets (java.net)Deep understanding of HTTP protocol
BuildMavenIndustry-standard Java build tool
TestingJUnit 4Reliable, widely-adopted test framework
DependenciesNone (runtime)Minimal footprint, educational value

Learning Objectives

By studying this project, you will understand:

  1. ✅ How HTTP protocol works at the socket level
  2. ✅ How to parse HTTP requests (method, URI, query parameters, headers)
  3. ✅ How to implement a routing system with lambda functions
  4. ✅ How to serve static files with proper MIME type detection
  5. ✅ How to apply clean code principles and design patterns (Singleton, Functional Interface)
  6. ✅ The architecture of web frameworks and distributed applications

🏗️ Architecture

┌─────────────────────────────────────────────────────────┐
│ HTTP Client (Browser) │
└─────────────────────┬───────────────────────────────────┘
│ HTTP Request
▼
┌─────────────────────────────────────────────────────────┐
│ MicroServer (Socket Listener) │
│ Listens on port 8080 for connections │
└─────────────────────┬───────────────────────────────────┘
│ Parse Request
▼
┌─────────────────────────────────────────────────────────┐
│ Request Parser │
│ Extracts: method, path, query params, headers │
└─────────────────────┬───────────────────────────────────┘
│ Route Decision
▼
┌───────────┴───────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ /App/* prefix │ │ Static File Request │
│ REST Router │ │ (*.html, *.css, ...) │
│ │ │ │
│ RouteHandler │ │ StaticFileHandler │
│ finds matching │ │ reads from classpath│
│ lambda handler │ │ /webroot directory │
└────────┬─────────┘ └──────────┬───────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ RestHandler │ │ File Bytes + │
│ (req, resp) -> │ │ MIME Content-Type │
│ Lambda executes │ │ Detection │
└────────┬─────────┘ └──────────┬───────────┘
│ │
└───────────┬────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ HTTP Response Builder │
│ Status line + Headers + Body → Output Stream │
└─────────────────────────────────────────────────────────┘

Request Flow

  1. Client sends an HTTP request to localhost:8080
  2. MicroServer accepts the socket connection and reads the raw HTTP request
  3. Request Parser extracts the method, URI, query string, and headers
  4. Router decides:
    • If path starts with /App/ → delegate to RouteHandler (REST)
    • Otherwise → delegate to StaticFileHandler (static files)
  5. Handler produces the response body
  6. Response Builder sends proper HTTP response with headers back to client

📁 Repository Structure

lambda-rest-microframework/
├── 📄 README.md # Project documentation
├── 📄 LICENSE # MIT License
├── 📄 pom.xml # Maven build configuration
├── 📄 .gitignore # Git ignore rules
├── 📁 images/ # Screenshots for README
├── 📁 src/
│ ├── 📁 main/
│ │ ├── 📁 java/co/edu/escuelaing/microframework/
│ │ │ ├── 🔷 RestHandler.java # @FunctionalInterface for lambda handlers
│ │ │ ├── 🔷 Request.java # HTTP request wrapper with getValues()
│ │ │ ├── 🔷 Response.java # HTTP response with fluent API
│ │ │ ├── 🔷 RouteHandler.java # Route registration and lookup
│ │ │ ├── 🔷 StaticFileHandler.java # Static file serving + MIME detection
│ │ │ ├── 🔷 MicroServer.java # Main server: get(), staticfiles(), start()
│ │ │ └── 📁 demo/
│ │ │ └── 🔷 WebApplication.java # Example application
│ │ └── 📁 resources/
│ │ └── 📁 webroot/ # Static web files
│ │ ├── 📄 index.html # Main page with API demo
│ │ ├── 📄 style.css # Dark theme stylesheet
│ │ └── 📄 app.js # Client-side API caller
│ └── 📁 test/
│ └── 📁 java/co/edu/escuelaing/microframework/
│ ├── 🧪 RequestTest.java # 22 tests
│ ├── 🧪 ResponseTest.java # 17 tests
│ ├── 🧪 RouteHandlerTest.java # 18 tests
│ ├── 🧪 StaticFileHandlerTest.java # 32 tests
│ └── 🧪 MicroServerTest.java # 12 tests

🔧 Components

1. RestHandler — Functional Interface

The @FunctionalInterface that enables lambda-based REST service definition:

@FunctionalInterfacepublicinterfaceRestHandler {
Stringhandle(Requestrequest, Responseresponse);
}

This is the core abstraction that allows developers to write:

get("/hello", (req, resp) -> "Hello " + req.getValues("name"));

2. Request — HTTP Request Wrapper

Wraps the raw HTTP request and provides clean access to query parameters:

// Inside a handler, access query parameters easily:get("/search", (req, resp) -> {
Stringquery = req.getValues("q"); // Extract "q" parameterStringpage = req.getValues("page"); // Extract "page" parameterreturn"Searching for: " + query + " (page " + page + ")";
});
// URL: /App/search?q=java&page=1

Key method:req.getValues(String key) — Returns the query parameter value or empty string if not present.

The Request.parseQueryString() method handles URL-encoded query strings:

  • name=Pedro&age=25{name: "Pedro", age: "25"}
  • greeting=Hello+World{greeting: "Hello World"}
  • email=user%40example.com{email: "user@example.com"}

3. Response — HTTP Response Object

Provides a fluent API for response configuration:

Responseresponse = newResponse()
.setStatusCode(200)
.setContentType("application/json")
.setBody("{\"message\": \"OK\"}");

4. RouteHandler — Route Registry

Manages the mapping between URL paths and lambda handlers:

RouteHandlerrouter = newRouteHandler();
router.addGetRoute("/hello", (req, resp) -> "Hello!");
router.addGetRoute("/pi", (req, resp) -> String.valueOf(Math.PI));
RestHandlerhandler = router.findHandler("GET", "/hello");
// handler.handle(req, resp) → "Hello!"

Features path normalization: /hello, hello, and /hello/ all map to the same route.

5. StaticFileHandler — Static File Server

Serves files from a configurable directory with automatic MIME type detection:

StaticFileHandlerhandler = newStaticFileHandler("/webroot");
byte[] fileBytes = handler.getFileBytes("/index.html");
StringmimeType = StaticFileHandler.getContentType("style.css"); // "text/css"

Supported MIME types:

ExtensionMIME Type
.html, .htmtext/html
.csstext/css
.jsapplication/javascript
.jsonapplication/json
.pngimage/png
.jpg, .jpegimage/jpeg
.gifimage/gif
.svgimage/svg+xml
.icoimage/x-icon

6. MicroServer — The Framework Core

The main server class providing the public API:

publicstaticvoidmain(String[] args) {
// 1. Configure static file locationstaticfiles("/webroot");
// 2. Define REST services with lambda functionsget("/hello", (req, resp) -> "Hello " + req.getValues("name"));
get("/pi", (req, resp) -> String.valueOf(Math.PI));
// 3. Start the serverstart(); // Listens on port 8080
}

REST Prefix: All REST services are accessed under the /App prefix:

  • get("/hello", ...) → accessible at http://localhost:8080/App/hello
  • get("/pi", ...) → accessible at http://localhost:8080/App/pi

Static Files: Served from the root:

  • http://localhost:8080/index.html → reads from /webroot/index.html
  • http://localhost:8080/style.css → reads from /webroot/style.css

🧪 Tests

The project includes 101 unit tests covering all framework components:

Test ClassTestsCoverage Areas
RequestTest22Query params, URL decoding, constructors, immutability
ResponseTest17Status codes, fluent API, defaults, headers
RouteHandlerTest18Route registration, lookup, path normalization, lambdas
StaticFileHandlerTest32MIME types, file detection, folder config
MicroServerTest12Singleton, route registration, static config

Running Tests

mvn test

Expected output:

[INFO] Tests run: 101, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

Test Examples

// Test: query parameter extraction@TestpublicvoidtestGetValuesReturnsCorrectValue() {
Requestreq = newRequest("GET", "/hello",
Map.of("name", "Pedro"), null, "");
assertEquals("Pedro", req.getValues("name"));
}
// Test: lambda handler with computation@TestpublicvoidtestLambdaWithComputation() {
routeHandler.addGetRoute("/pi", (req, resp) -> String.valueOf(Math.PI));
RestHandlerhandler = routeHandler.findHandler("GET", "/pi");
assertEquals(String.valueOf(Math.PI), handler.handle(null, null));
}
// Test: MIME type detection@TestpublicvoidtestContentTypeCss() {
assertEquals("text/css", StaticFileHandler.getContentType("style.css"));
}

💡 Example: How Developers Use the Framework

importstaticco.edu.escuelaing.microframework.MicroServer.*;
publicclassMyApp {
publicstaticvoidmain(String[] args) {
// Set static files directorystaticfiles("/webroot");
// Simple greeting endpointget("/hello", (req, resp) -> "Hello " + req.getValues("name"));
// Mathematical computationget("/pi", (req, resp) -> String.valueOf(Math.PI));
// Multi-line handler with logicget("/greeting", (req, resp) -> {
Stringname = req.getValues("name");
if (name.isEmpty()) name = "World";
return"<h1>Hello, " + name + "!</h1>";
});
// Start serverstart();
}
}

Available URLs after starting:

  • http://localhost:8080/index.html — Static web page
  • http://localhost:8080/App/hello?name=Pedro — Returns "Hello Pedro"
  • http://localhost:8080/App/pi — Returns "3.141592653589793"
  • http://localhost:8080/App/greeting?name=Pedro — Returns HTML greeting

🛠️ Built With

TechnologyPurpose
Java 17Programming language with lambda support
MavenBuild automation and dependency management
JUnit 4Unit testing framework
Java Sockets (java.net)HTTP server implementation

📊 Design Patterns Used

PatternWherePurpose
SingletonMicroServerSingle server instance with global access
Functional InterfaceRestHandlerLambda-based REST handler definition
StrategyRouteHandlerPluggable route-to-handler mapping
Builder (Fluent)ResponseChainable response configuration

📚 References


👤 Author


📄 License

This project is licensed under the MIT License — see the LICENSE file for details.


🙏 Acknowledgments

  • Escuela Colombiana de Ingeniería Julio Garavito — Academic institution
  • Prof. Luis Daniel Benavides Navarro — Course material on networking and web services
  • Spark Java framework — Inspiration for the lambda-based API design
  • Java documentation team — Comprehensive networking tutorials

About

Zero-dependency Java web microframework for the Enterprise Architecture (AREP) course. Implements lambda-based REST services and static file serving using raw Java sockets. Features a modular architecture with Singleton and Strategy patterns, validated by 100+ unit tests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages