Dartfrog is a high-performance and scalable HTTP/1.1 server implementation written in pure Java with no external dependencies. It's designed for performance and clarity, featuring asynchronous request handling via a thread pool.
Dartfrog implements core HTTP/1.1 functionality:
- Persistent Connections: Keep TCP connections alive for multiple requests, improving performance.
- Asynchronous Request Handling: Utilizes a thread pool for efficient handling of concurrent client connections.
- Content Compression (gzip): Automatically compresses responses when supported by clients, with content negotiation via
Accept-Encoding. - Versatile File Management: Provides efficient file serving capabilities (GET) with automatic Content-Type detection and allows for file creation/modification (POST) via request bodies.
- Content Negotiation: Honors client preferences for compression via the
Accept-Encodingheader. - Standards Compliant: Adheres to HTTP/1.1 standards for status codes, headers, and response formats.
- Robust Error Handling: Includes comprehensive error handling and logging.
- Clear, Modular Design: Promotes maintainability and extensibility through well-organized code.
Dartfrog uses a multi-threaded architecture with the following key components:
- Main Server Thread: Accepts incoming TCP connections and delegates them to worker threads from the thread pool.
- Worker Threads (Thread Pool): A pool of threads that concurrently handle multiple client requests, improving responsiveness.
- Request Parser: Parses the HTTP request line and headers into a structured
HttpRequestobject. - Route Handler: Maps incoming request paths to specific handler logic.
- Response Formatter: Constructs
HttpResponseobjects with appropriate headers and body, including handling content compression.
The server maintains connection persistence where requested and ensures thread safety through the design of request handling.
- Java 11 or higher
- Maven (if building from source)
# Run the server on the default port (4221)
java -jar dartfrog.jar
# Run with a specific file directory
java -jar dartfrog.jar --directory /path/to/files
# Run with custom port (using JVM arguments)
java -Dport=8080 -jar dartfrog.jar# Clone the repository
git clone https://github.com/trentonallan/dartfrog-java.git
cd dartfrog-java
# Build the JAR
javac -d build Main.java
jar cvfe dartfrog.jar Main -C build .
# Run the server
java -jar dartfrog.jarDartfrog supports the following endpoints:
GET /
Returns a 200 OK response with an empty body.
GET /echo/{string}
Returns the {string} value as plain text.
Supports gzip compression when requested via Accept-Encoding header.
GET /user-agent
Returns the User-Agent header value as plain text.
GET /files/{filename}
Returns the contents of the specified file from the configured directory.
POST /files/{filename}
Creates or overwrites a file with the specified name, using the request body as content.
Dartfrog implements core HTTP/1.1 features such as:
- Robust request parsing of the request line and headers.
- Structured
HttpRequestandHttpResponseobjects for managing request and response data. - Proper construction of response status lines and headers.
- Handling of
Content-Lengthfor request and response bodies. - Support for persistent connections (
Connection: keep-aliveandConnection: close).
The server utilizes a thread pool for efficient handling of concurrent connections:
- A fixed-size thread pool (
THREAD_POOL_SIZEequal to the number of available processors) manages worker threads. - Incoming client connections are submitted to the thread pool for asynchronous processing.
Dartfrog implements gzip compression with content negotiation:
- Uses Java's
GZIPOutputStreamfor compressing response bodies. - Compression is only applied if the client explicitly indicates support for
gzipin theAccept-Encodingrequest header. - The
Content-Encoding: gzipheader is included in compressed responses.
File operations are implemented using Java NIO for efficiency:
Files.readAllBytesis used for reading file content for GET requests.Files.probeContentTypeattempts to automatically determine the correctContent-Typefor served files.Files.writewithStandardOpenOption.CREATEandStandardOpenOption.TRUNCATE_EXISTINGis used for creating or overwriting files in POST requests.- Parent directories are automatically created if they don't exist during POST requests.
This HTTP/1.1 server implementation is an educational project for me to familiarize myself with fundamental networking concepts and HTTP request/response handling. It currently has several limitations compared to actual production-ready web servers. Future versions of Dartfrog may explore:
- HTTP/2 Support: Implementing multiplexing, server push, and header compression for improved performance.
- WebSocket Protocol: Enabling real-time bidirectional communication capabilities.
- Enhanced Thread Management: Further optimization of thread pool management and potential exploration of non-blocking I/O (NIO) for
- Admin Dashboard: Providing runtime metrics and configuration options.
Thank you for checking out Dartfrog! Feel free to reach out at [email protected].