Skip to content

A lightweight, HTTP/1.1-compliant web server implementation in Java built from scratch using non-blocking I/O.

Notifications You must be signed in to change notification settings

aminehabchi/Local-Server

Repository files navigation

Local Server

A lightweight, HTTP/1.1-compliant web server implementation in Java built from scratch using non-blocking I/O. This project demonstrates understanding of network protocols, socket programming, and event-driven architecture without relying on established frameworks.

Overview

This is a custom HTTP server designed to be:

  • Crash-proof: Robust error handling ensures the server never crashes
  • High-performance: Event-driven, non-blocking I/O using Java NIO for optimal resource usage
  • Single-threaded: Efficient handling of multiple connections in a single thread
  • HTTP/1.1 compliant: Proper handling of chunked/unchunked requests and responses
  • Production-ready: Tested with siege achieving 100% availability under stress

Features

  • Multi-Server Support: Run multiple virtual servers on different ports with host-based routing
  • Static File Serving: Serve static files with automatic MIME type detection
  • CGI Support: Execute Python and Node.js scripts via CGI
  • Flexible Routing: YAML-based route configuration with pattern matching
  • HTTP Methods: Support for GET, POST, DELETE methods
  • Session Management: Built-in session handling with cookies
  • Custom Error Pages: Configure custom error pages per server (400, 403, 404, 405, 413, 500)
  • HTTP Redirects: Support for 301/302 redirects
  • Directory Listing: Optional directory browsing
  • Request Size Limits: Configurable client body size limits
  • Virtual Hosts: Host-based request routing
  • File Uploads: Handle file uploads with body size validation
  • Chunked Encoding: Support for both chunked and unchunked transfer encoding
  • Request Timeouts: Automatic timeout for long-running requests

Installation

Requirements

  • Java 17 or higher
  • Maven 3.6+ (optional, falls back to javac if not available)
  • Python 3 (optional, for CGI scripts)
  • Node.js (optional, for CGI scripts)

Quick Start

  1. Clone the repository:
git clone <repository-url>
cd JAVA-LOCALSERVER
  1. Run the server:
./run.sh

The server will compile and start automatically, listening on the ports configured in application.yml.

Configuration

The server is configured via src/main/resources/application.yml. The configuration file uses YAML format to define servers, routes, and behavior.

Configuration Structure

servers:
  - name: server1
    hosts: [localhost]
    ports: [8080, 8443]
    default: true
    clientMaxBodySize: 5MB
    sessionId: session-id  # Optional
    errorPages:
      403: /errors/403.html
      404: /errors/404.html
      500: /errors/500.html
    routes:
      - name: static-files
        path: /files
        methods: [GET]
        root: /files
        indexFile: index.html
        directoryListing: true

Server Configuration Options

Option Type Description
name String Server identifier
hosts Array Virtual host names (e.g., localhost, example.com)
ports Array Port numbers to listen on
default Boolean Whether this is the default server for its ports
clientMaxBodySize String Maximum request body size (e.g., 5MB, 10GB)
sessionId String Optional session ID validation
errorPages Map Custom error pages mapping status codes to paths
routes Array Route configurations

Route Configuration Options

Option Type Description
name String Route identifier
path String URL path pattern
methods Array Allowed HTTP methods
root String Root directory for static files (relative to resources)
indexFile String Default file to serve for directories
directoryListing Boolean Enable/disable directory browsing
redirect Object Redirect configuration (status, to)
cgi Object CGI interpreter mapping (extension: path)

Route Types

1. Static File Serving

- name: static-files
  path: /files
  methods: [GET]
  root: /files
  indexFile: index.html
  directoryListing: true

2. CGI Execution

- name: python-scripts
  path: /cgi-bin
  methods: [GET, POST]
  root: /scripts
  cgi:
    py: /usr/bin/python3
    js: /usr/bin/node

3. HTTP Redirect

- name: old-path
  path: /old-files
  methods: [GET]
  redirect:
    status: 301
    to: /new-files

Usage Examples

Accessing Static Files

With the default configuration:

# Access files in /images directory
curl http://localhost:8080/images/photo.jpg

# Access files with directory listing
curl http://localhost:8080/files/

Executing CGI Scripts

Place your scripts in src/main/resources/scripts/:

# Execute Python CGI script
curl http://localhost:8081/python/script.py

# Execute Node.js CGI script
curl http://localhost:8081/nodejs/app.js

# POST request to CGI
curl -X POST -d "data=value" http://localhost:8081/cgi-bin/process.py

Testing Different Servers

# Server 1 (default server)
curl http://localhost:8080/gallery/

# Server 2 with specific host
curl -H "Host: test2.com" http://localhost:8081/python/

# Server 3 with redirect
curl -L http://localhost:8888/

Project Structure

JAVA-LOCALSERVER/
 src/main/java/com/http/
    Main.java                           # Entry point
    application/
       Application.java                # Main application class
       configuration/                  # Configuration parsing
       connectors/                     # Network I/O handling
       router/                         # Request routing
       session/                        # Session management
    http/
       request/                        # HTTP request parsing
       response/                       # HTTP response generation
       enums/                          # HTTP enums (methods, status)
       cookie/                         # Cookie handling
       url/                            # URL parsing
    utils/                              # Utilities (MIME types, etc.)
 src/main/resources/
    application.yml                     # Server configuration

How It Works

  1. Server Initialization: The Application class parses application.yml and initializes connectors and routers
  2. Connection Handling: The Connector uses Java NIO for non-blocking I/O
  3. Request Processing: Incoming requests are parsed and routed based on host/port/path
  4. Route Matching: The Router matches requests to configured routes
  5. Response Generation: Responses are generated based on route type (static, CGI, redirect)
  6. Session Management: Sessions are tracked via cookies
  7. Error Handling: Custom error pages are served based on configuration

Architecture

Single-Threaded Event Loop

The server uses a single thread with Java NIO's Selector to handle multiple connections concurrently:

  • Non-blocking I/O: All socket operations are non-blocking, preventing any single connection from blocking others
  • Event-driven: The selector monitors multiple channels for readiness (accept, read, write)
  • Efficient: Handles thousands of concurrent connections with minimal resource overhead
  • Scalable: No thread-per-connection overhead

Request Processing Pipeline

Client Connection → Read Handler → Header Parser → Chunk Parser →
Request Parser → Router → Response Generation → Write Handler

Key Components

  • Connector (src/main/java/com/http/application/connectors/Connector.java:24): Main event loop using Selector
  • HeaderParser: Parses HTTP headers from incoming byte streams
  • ChunkParser: Handles chunked transfer encoding
  • RequestParser: Constructs HttpRequest objects
  • Router (src/main/java/com/http/application/router/Router.java:29): Routes requests to appropriate handlers
  • CgiHandler: Executes CGI scripts using ProcessBuilder
  • StaticResourceResolver: Serves static files with proper MIME types

Performance & Testing

Stress Testing with Siege

The server has been tested using siege benchmark tool and achieves excellent performance:

Test Results

Test 1: 50 concurrent users, 100 repetitions each (5000 transactions)

Transactions:               10000 hits
Availability:               100.00 %
Elapsed time:               6.34 secs
Response time:              31.48 ms
Transaction rate:           1577.29 trans/sec
Throughput:                 0.66 MB/sec
Concurrency:                49.65
Failed transactions:        0

Test 2: 100 concurrent users, 200 repetitions each (20000 transactions)

Transactions:               20000 hits
Availability:               100.00 %
Elapsed time:               13.79 secs
Response time:              51.87 ms
Transaction rate:           1450.33 trans/sec
Throughput:                 1.22 MB/sec
Concurrency:                75.23
Failed transactions:        0

Key Metrics

  • Availability: 100% (exceeds 99.5% target)
  • Zero failures: No crashed connections or errors
  • High throughput: 1400+ requests/second
  • Low latency: Average response time under 52ms
  • Handles high concurrency: 100+ concurrent users without degradation

Running Your Own Tests

# Basic benchmark test
siege -b -c 50 -r 100 http://localhost:8080/

# High concurrency stress test
siege -b -c 100 -r 200 http://localhost:8080/

# Timed test (30 seconds)
siege -b -t30s -c 50 http://localhost:8080/

HTTP/1.1 Compliance

This server implements key HTTP/1.1 features:

  • Chunked Transfer Encoding: Both sending and receiving
  • Persistent Connections: Keep-alive support
  • Virtual Hosting: Host header-based routing
  • Method Support: GET, POST, DELETE
  • Status Codes: Proper HTTP status codes (200, 301, 302, 400, 403, 404, 405, 413, 500)
  • Content Negotiation: MIME type detection and Content-Type headers
  • Request/Response Headers: Full header parsing and generation
  • Error Handling: Graceful error responses with custom error pages

Advanced Features

Session Management

Sessions are automatically managed via cookies. Configure per-server:

sessionId: my-session-id

Body Size Limits

Prevent large uploads by setting limits:

clientMaxBodySize: 5MB  # Supports KB, MB, GB

Virtual Hosts

Multiple servers can share ports with host-based routing:

servers:
  - name: site1
    hosts: [example.com]
    ports: [80]
  - name: site2
    hosts: [test.com]
    ports: [80]

CGI Environment Variables

CGI scripts receive standard environment variables:

  • REQUEST_METHOD
  • QUERY_STRING
  • CONTENT_TYPE
  • CONTENT_LENGTH
  • PATH_INFO
  • SERVER_PROTOCOL

Troubleshooting

Port Already in Use

Change the port in application.yml or stop the conflicting service.

CGI Scripts Not Executing

  • Verify interpreter path in configuration
  • Check script permissions
  • Ensure scripts are in the configured root directory

404 Not Found

  • Check that the route path matches the request URL
  • Verify the root directory exists
  • Ensure HTTP method is allowed

About

A lightweight, HTTP/1.1-compliant web server implementation in Java built from scratch using non-blocking I/O.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •