A high-performance, single-threaded, non-blocking HTTP/1.1 web server built from scratch in Java using the java.nio library. This project demonstrates a robust event-loop architecture capable of handling multiple concurrent connections, CGI execution, session management, and complex configurations.
Java LocalServer is designed to be a lightweight but feature-rich web server. It avoids the overhead of traditional thread-per-connection models by utilizing Java NIO's Selector and non-blocking sockets. This allows the server to scale efficiently even with high numbers of idle or slow connections.
The server follows a classic Event-Loop pattern:
- Main Loop: Located in
BootstrapApp, it continuously polls theSelectorfor IO events (Accept, Read, Write). - ClientContext: Encapsulates the state of a single client connection, including the NIO channel, partial request data, and outgoing response buffers.
- RequestParser: A specialized parser that handles streaming HTTP requests, including chunked encoding and multipart/form-data.
- ResponseWriter: An asynchronous interface for sending responses. Specialized implementations exist for:
FileResponseWriter: Efficiently streams static files.CGIResponseWriter: Handles communication with external CGI scripts.MemoryResponseWriter: Serves dynamic content (like error pages or redirects) from memory.
- Router: Maps incoming request paths to specific location configurations.
graph TD
A[Selector Loop] -->|OP_ACCEPT| B[Accept New Connection]
A -->|OP_READ| C[Read Data & Parse Request]
A -->|OP_WRITE| D[Asynchronous Write Response]
C -->|Request Ready| E[Router]
E -->|Matches Route| F[Dispatch to ResponseWriter]
F -->|Register OP_WRITE| A
- Virtual Hosting: Support for multiple server blocks with different
server_names sharing the same or different ports. - Methods Support: Support for
GET,POST, andDELETE. - CGI Integration: Execute scripts (e.g., Python, Ruby) based on file extensions.
- Multipart Parsing: Built-in support for
multipart/form-data, enabling file uploads. - Directory Indexing: Optional
autoindexfeature that generates HTML listings for directories. - Session Management: Built-in session tracking with cookie support.
- Custom Error Pages: Define unique HTML pages for specific HTTP error codes (404, 500, etc.).
- Pipelining & Keep-Alive: Efficiently handles multiple requests over a single TCP connection.
The server is configured via a custom .conf file (default: config.conf).
The server block defines a virtual host.
| Directive | Description | Example |
|---|---|---|
host |
The IP address to bind to. | host 0.0.0.0; |
ports |
List of ports to listen on. | ports 8080 8081; |
server_name |
Domain name for virtual hosting. | server_name example.com; |
client_max_body_size |
Max allowed size for request body (bytes). | client_max_body_size 1048576; |
error_page |
Path to custom error page for a status code. | error_page 404 error_pages/404.html; |
Defines how specific request paths are handled.
| Directive | Description | Example |
|---|---|---|
root |
Directory where files are located. | root ./www; |
methods |
Allowed HTTP methods. | methods GET POST; |
index |
Default file to serve for directories. | index index.html; |
autoindex |
Enable/disable directory listing (on/off). |
autoindex on; |
cgi |
Map extension to interpreter. | cgi .py /usr/bin/python3; |
redirect |
Path redirection (status code + target). | redirect 301 /new-path; |
server {
host 0.0.0.0 ;
ports 8080;
server_name localhost;
client_max_body_size 10000000;
location / {
root ./www;
methods GET POST;
index index.html;
autoindex on;
}
location /cgi {
root ./cgi;
methods GET POST;
cgi .py /usr/bin/python3;
}
}- JDK 8 or higher.
make(optional, for convenience).
make build # Compiles the project
make run # Starts the server using config.conf
make clean # Removes build artifactsmkdir -p bin
find src/main/java -name "*.java" > sources.txt
javac -d bin @sources.txt
java -cp bin server.Main -c config.confThe project includes integration tests for routing, method handling, and keep-alive connections.
make testOr manually:
java -cp bin server.RoutingIntegrationTest
java -cp bin server.MethodHandlingTest
java -cp bin server.KeepAliveIntegrationTest