A production-ready, multi-protocol HTTP server built with Java 21+ Virtual Threads, featuring HTTP/2, WebSocket, Server-Sent Events, and enterprise-grade performance.
- Overview
- Key Features
- Architecture
- Performance
- Installation
- Configuration
- Usage
- Security
- Testing
- Deployment
- API Documentation
- Contributing
- License
This is a modern HTTP server implementation showcasing Java 21's Virtual Threads (Project Loom) for massive concurrency. The server implements multiple protocols and modern web standards while maintaining high performance and security.
Built for:
- High-concurrency applications (50,000+ concurrent connections)
- Real-time web applications (WebSocket, SSE)
- Modern HTTP/2 clients
- Performance benchmarking (TechEmpower-ready)
- Educational purposes (clean, well-tested codebase)
- ✅ HTTP/1.1 - Full RFC 2616/7230 compliance
- ✅ HTTP/2 - Binary framing, HPACK compression, stream multiplexing (RFC 7540/7541)
- ✅ WebSocket - Full-duplex communication (RFC 6455)
- ✅ Server-Sent Events - W3C-compliant server push
- ✅ TLS 1.2/1.3 - ALPN negotiation, modern cipher suites only
- 🚀 Virtual Threads - Java 21+ lightweight concurrency (50,000+ connections)
- ⚡ Zero-Copy File Transfer - FileChannel.transferTo() for large files
- 💾 ETag Caching - 2.54µs cache hit vs 4.59ms uncached (1,806x faster)
- 🗜️ Compression Caching - 0.007ms cache hit vs 4.64ms uncached (663x faster)
- 🔄 Buffer Pooling - 80% GC reduction (5 → 1 GC per 10K requests)
- 🔥 HTTP Keep-Alive - Connection reuse
- 🔒 TLS/SSL - Modern cipher suites, TLS 1.2+ only
- 🔑 Authentication - API Key, HTTP Basic Auth
- 🛡️ Rate Limiting - Token bucket algorithm
- 🔐 OWASP Headers - HSTS, CSP, X-Frame-Options
- 🚫 Input Validation - Path traversal protection, XSS prevention
- 📊 Security Logging - Structured JSON logs
- 📈 Prometheus Metrics - Request counts, latencies, cache stats
- 🔍 W3C Trace Context - Distributed tracing support
- 📝 Structured Logging - JSON-formatted logs
- ❤️ Health Checks - Liveness and readiness endpoints
- 🎯 Graceful Shutdown - Kubernetes-compatible
- 🔄 Virtual Hosting - Name-based virtual hosts
- 🔀 URL Routing - Redirects, rewrites, pattern matching
- 🗄️ Database Pooling - HikariCP connection pooling
- 🎭 Compression - Gzip and Brotli support
- 📦 Content Negotiation - Accept-Encoding, MIME types
┌─────────────────────────────────────────────────────────┐
│ HTTP Server (Servlet) │
│ Virtual Thread Executor │
└───────────────────────┬─────────────────────────────────┘
│
▼
┌───────────────────────┐
│ ProcessRequest │
│ (Request Handler) │
└───────────┬───────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ HTTP/1.1│ │ HTTP/2 │ │ WebSocket│
└─────────┘ └──────────┘ └──────────┘
│ │ │
└──────────────┼───────────────┘
▼
┌─────────────────────────────┐
│ Core Components │
├─────────────────────────────┤
│ • CacheManager (ETag) │
│ • CompressionHandler │
│ • RateLimiter │
│ • AuthenticationManager │
│ • MetricsCollector │
│ • BufferPool │
│ • SecurityHeadersHandler │
│ • TraceContextHandler │
└─────────────────────────────┘
Core Server:
Servlet.java- Main server entry point, socket listenerProcessRequest.java- Request routing and protocol handlingServerConfig.java- Configuration managementTLSManager.java- TLS/SSL with ALPN support
HTTP/2 Implementation:
HTTP2Handler.java- Connection and stream managementHTTP2FrameParser.java- Binary frame encoding/decodingHPACKEncoder/Decoder.java- Header compression (RFC 7541)HTTP2Stream.java- Stream state machine and flow control
WebSocket Implementation:
WebSocketConnection.java- Connection lifecycleWebSocketFrame.java- Frame parsing and maskingWebSocketHandler.java- Application callback interface
SSE Implementation:
SSEManager.java- Topic-based broadcastingSSEConnection.java- Event streamingSSEEvent.java- W3C event formatting
These are performance characteristics of this server's features:
| Feature | Performance | Notes |
|---|---|---|
| ETag Cache Hit | 2.54µs | Cached vs 4.59ms uncached (1MB files) |
| Compression Cache Hit | 0.007ms | Cached vs 4.64ms uncached |
| Buffer Pool | 80% GC reduction | 5 → 1 GC per 10K requests |
| Virtual Threads | 50,000+ connections | vs 1,000-2,000 with platform threads |
| Thread Memory | 1KB per thread | vs 1MB per platform thread |
| Rate Limiter | 2.4M checks/sec | Token bucket with LRU eviction |
| Test Type | Target | Description |
|---|---|---|
| Plaintext | 1-5M req/sec | Raw server performance |
| JSON | 500K-2M req/sec | Serialization overhead |
| Single Query | 20-50K req/sec | Database driver efficiency |
| Multiple Queries | 5-15K req/sec | Connection pooling (20 queries) |
| Updates | 3-10K req/sec | Transaction handling (20 updates) |
| Fortunes | 10-30K req/sec | Server-side rendering |
From performance profiling, identified improvements:
- HPACK encoding - 30-40% faster with HashMap lookups
- Buffer allocation - 20-30% improvement with ThreadLocal pools
- Frame parsing - 20-30% faster with ByteBuffer.slice()
See HTTP2_PERFORMANCE_ANALYSIS.md for details.
- Java 21+ (for Virtual Threads support)
- Maven 3.8+ (for dependency management)
- PostgreSQL 12+ (for TechEmpower benchmarks, optional)
# Clone repository
git clone https://github.com/yourusername/http_server.git
cd http_server
# Compile
mvn clean compile
# Or compile manually
javac -d . HTTPServer/*.javaThe server uses minimal dependencies:
<!-- pom.xml -->
<dependencies>
<!-- PostgreSQL JDBC Driver (for TechEmpower) -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.0</version>
</dependency>
<!-- HikariCP Connection Pool -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
<!-- Brotli Compression -->
<dependency>
<groupId>com.aayushatharva.brotli4j</groupId>
<artifactId>brotli4j</artifactId>
<version>1.12.0</version>
</dependency>
<!-- JUnit 5 (testing) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>Authentication (Required):
# HTTP Basic Auth - Format: "user1:pass1,user2:pass2"
export HTTP_BASIC_AUTH="admin:securepassword,user:anotherpassword"
# API Keys - Format: "key1,key2,key3"
export HTTP_API_KEYS="sk_live_abc123,sk_test_xyz789"Database (Optional - for TechEmpower):
export DB_HOST="localhost"
export DB_PORT="5432"
export DB_NAME="benchmark"
export DB_USER="benchmarkdbuser"
export DB_PASSWORD="securedbpassword"Server Configuration:
export SERVER_PORT="8080"
export SERVER_WEBROOT="./public"
export SERVER_TLS_ENABLED="true"
export SERVER_TLS_KEYSTORE="./keystore.jks"
export SERVER_TLS_KEYSTORE_PASSWORD="changeit"Configure programmatically:
ServerConfig config = new ServerConfig();
config.setPort(8443);
config.setWebroot("./public");
config.setTlsEnabled(true);
config.setTlsKeystorePath("./certs/keystore.jks");
config.setTlsKeystorePassword("changeit");
Servlet server = new Servlet(config);
server.start();// Simple HTTP server
public static void main(String[] args) {
ServerConfig config = new ServerConfig();
config.setPort(8080);
config.setWebroot("./public");
Servlet server = new Servlet(config);
server.start();
}Access at: http://localhost:8080/
HTTP/2 is automatically negotiated via ALPN when using HTTPS:
# Start with TLS
export SERVER_TLS_ENABLED=true
java HTTPServer.Servlet
# Test with curl
curl --http2 https://localhost:8443/Features:
- Binary framing with 10 frame types
- HPACK header compression (4KB dynamic table)
- Stream multiplexing (up to 2^31-1 concurrent streams)
- Flow control (connection and stream level)
- Server push capability
Server-side handler:
public class ChatHandler implements WebSocketHandler {
@Override
public void onOpen(WebSocketConnection conn) {
System.out.println("Client connected: " + conn.getId());
}
@Override
public void onMessage(WebSocketConnection conn, String message) {
// Echo message back
conn.sendText("Echo: " + message);
}
@Override
public void onClose(WebSocketConnection conn, int code, String reason) {
System.out.println("Client disconnected: " + reason);
}
@Override
public void onError(WebSocketConnection conn, Throwable error) {
error.printStackTrace();
}
}
// Register handler
request.setWebSocketHandler(new ChatHandler());Client-side JavaScript:
const ws = new WebSocket('ws://localhost:8080/chat');
ws.onopen = () => {
console.log('Connected');
ws.send('Hello Server!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
ws.onclose = () => {
console.log('Disconnected');
};Server-side:
// Clock handler - sends time every second
public class ClockHandler implements SSEHandler {
@Override
public void onOpen(SSEConnection conn) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> {
SSEEvent event = new SSEEvent();
event.setEvent("time");
event.setData(new Date().toString());
conn.sendEvent(event);
}, 0, 1, TimeUnit.SECONDS);
}
}
// Register handler
request.setSSEHandler(new ClockHandler());Client-side JavaScript:
const eventSource = new EventSource('/events/clock');
eventSource.addEventListener('time', (event) => {
console.log('Current time:', event.data);
});
eventSource.onerror = () => {
console.error('Connection error');
eventSource.close();
};Endpoints:
# JSON serialization
curl http://localhost:8080/json
# {"message":"Hello, World!"}
# Single database query
curl http://localhost:8080/db
# {"id":123,"randomNumber":456}
# Multiple queries
curl http://localhost:8080/queries?queries=20
# [{"id":1,"randomNumber":234},...]
# Database updates
curl http://localhost:8080/updates?queries=10
# [{"id":5,"randomNumber":789},...]
# Plaintext
curl http://localhost:8080/plaintext
# Hello, World!
# Fortunes (HTML)
curl http://localhost:8080/fortunes
# <html>...</html>Setup database:
# Run setup script
./setup_postgresql.sh
# Or manually
psql -U postgres -f schema.sql-
Input Validation
- URL decoding with path traversal protection
- Request size limits (16KB headers, configurable body)
- HPACK bomb protection (8KB decompressed header limit)
-
Authentication
- HTTP Basic Auth (environment-configured)
- API Key authentication (Bearer token)
- No hardcoded credentials
-
TLS/SSL
- TLS 1.2+ only (1.0/1.1 disabled)
- Modern cipher suites only
- ALPN for HTTP/2 negotiation
-
OWASP Headers
- Strict-Transport-Security (HSTS)
- Content-Security-Policy (CSP)
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Referrer-Policy
- Permissions-Policy
-
Rate Limiting
- Token bucket algorithm (configurable)
- Per-IP tracking with LRU eviction
- Whitelist support
-
XSS Protection
- HTML entity escaping
- CSP headers
- Input sanitization
Production Checklist:
- Set
HTTP_BASIC_AUTHenvironment variable (never hardcode) - Set
DB_PASSWORDenvironment variable - Use TLS in production (
SERVER_TLS_ENABLED=true) - Configure rate limiting thresholds
- Review and customize OWASP headers
- Enable structured logging
- Monitor security logs for attacks
- Keep dependencies updated
- Run security audit regularly
Vulnerability Reporting:
Found a security issue? Email: security@example.com
- 400+ total tests across all components
- 100% pass rate on HTTP/2 test suite (283/283)
- Unit tests for all core components
- Integration tests for end-to-end scenarios
- Security tests for XSS, path traversal, etc.
# Compile tests
javac -d . -cp ".:lib/*" HTTPServer/tests/*.java
# Run all tests
java -cp ".:lib/*" org.junit.platform.console.ConsoleLauncher --scan-classpath
# Run specific test class
java -cp ".:lib/*" org.junit.platform.console.ConsoleLauncher -c HTTPServer.tests.HTTP2FrameParserTest
# Run with profiling
java -cp ".:lib/*" HTTPServer.utils.ProfiledTestRunnerHTTPServer/tests/
├── HTTP2FrameParserTest.java (11 tests)
├── HTTP2HPACKTest.java (13 tests)
├── HTTP2StreamTest.java (14 tests)
├── HTTP2IntegrationTest.java (16 tests)
├── HTTP2FrameEdgeCasesTest.java (30 tests)
├── HTTP2HPACKComprehensiveTest.java (38 tests)
├── HTTP2FlowControlTest.java (53 tests)
├── HTTP2ConcurrentStreamsTest.java (20 tests)
├── HTTP2ConnectionLifecycleTest.java (35 tests)
├── HTTP2ProtocolErrorsTest.java (33 tests)
├── HTTP2FullIntegrationTest.java (20 tests)
├── WebSocketFrameTest.java (25 tests)
├── WebSocketHandshakeTest.java (19 tests)
├── WebSocketConnectionTest.java (9 tests)
├── WebSocketSecurityTest.java (19 tests)
├── WebSocketIntegrationTest.java (12 tests)
├── SSEEventTest.java (9 tests)
├── SSEManagerTest.java (9 tests)
├── SSEIntegrationTest.java (5 tests)
├── SSESecurityTest.java (5 tests)
├── TechEmpowerHandlerTest.java (17 tests)
├── XSSProtectionTest.java (5 tests)
└── ...
FROM openjdk:21-slim
WORKDIR /app
# Copy application
COPY HTTPServer/ ./HTTPServer/
COPY lib/ ./lib/
# Compile
RUN javac -d . HTTPServer/*.java
# Environment
ENV SERVER_PORT=8080
ENV HTTP_BASIC_AUTH=""
ENV DB_PASSWORD=""
# Expose ports
EXPOSE 8080 8443
# Run
CMD ["java", "HTTPServer.Servlet"]Build and run:
docker build -t http-server .
docker run -p 8080:8080 \
-e HTTP_BASIC_AUTH="admin:password" \
-e SERVER_TLS_ENABLED=false \
http-serverapiVersion: apps/v1
kind: Deployment
metadata:
name: http-server
spec:
replicas: 3
selector:
matchLabels:
app: http-server
template:
metadata:
labels:
app: http-server
spec:
containers:
- name: http-server
image: http-server:latest
ports:
- containerPort: 8080
- containerPort: 8443
env:
- name: HTTP_BASIC_AUTH
valueFrom:
secretKeyRef:
name: http-server-secrets
key: basic-auth
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: http-server-secrets
key: db-password
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
---
apiVersion: v1
kind: Service
metadata:
name: http-server
spec:
selector:
app: http-server
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
type: LoadBalancer-
Resource Limits
- Virtual Threads scale well, but set reasonable limits
- Monitor memory usage (especially buffer pools)
- Set JVM heap size:
-Xmx2G -Xms2G
-
Monitoring
- Export Prometheus metrics:
/metrics - Health checks:
/health(liveness),/health/ready(readiness) - Structured logs to stdout (JSON format)
- Distributed tracing with W3C Trace Context
- Export Prometheus metrics:
-
Scaling
- Horizontal scaling works out of the box
- Stateless design (no session affinity needed)
- Database connection pooling handles load
-
Security
- Always use TLS in production
- Keep secrets in environment variables or secret managers
- Regular security audits
- Update dependencies for patches
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Serve static files from webroot |
/json |
GET | JSON serialization test |
/plaintext |
GET | Plaintext response |
/db |
GET | Single database query |
/queries |
GET | Multiple database queries (?queries=N) |
/updates |
GET | Database updates (?queries=N) |
/fortunes |
GET | HTML server-side rendering |
/health |
GET | Health check (liveness) |
/health/ready |
GET | Readiness check |
/metrics |
GET | Prometheus metrics |
| Endpoint | Protocol | Description |
|---|---|---|
/ws/echo |
WebSocket | Echo server |
/ws/chat |
WebSocket | Chat room |
| Endpoint | Protocol | Description |
|---|---|---|
/events/clock |
SSE | Server time every second |
/events/stocks |
SSE | Stock ticker simulation |
/events/notifications |
SSE | Notification stream |
Request Headers:
Authorization: Bearer token or Basic authUpgrade: websocket (for WebSocket upgrade)Sec-WebSocket-Key: WebSocket handshake keyAccept: text/event-stream (for SSE)Accept-Encoding: gzip, br (compression)If-None-Match: ETag for conditional requests
Response Headers:
Content-Type: MIME typeContent-Encoding: Compression algorithmETag: Resource identifier for cachingCache-Control: Caching directivesStrict-Transport-Security: HSTS headerContent-Security-Policy: CSP header- All OWASP security headers
Contributions welcome! Please follow these guidelines:
# Clone
git clone https://github.com/yourusername/http_server.git
cd http_server
# Create branch
git checkout -b feature/your-feature-name
# Make changes and test
javac -d . HTTPServer/*.java HTTPServer/tests/*.java
java -cp ".:lib/*" org.junit.platform.console.ConsoleLauncher --scan-classpath
# Commit
git commit -m "Add feature: your feature description"
# Push
git push origin feature/your-feature-name- Follow existing code conventions
- Use descriptive variable names
- Add JavaDoc for public APIs
- Write tests for new features
- Keep methods under 50 lines when possible
- Use Java 21+ features (Virtual Threads, pattern matching, etc.)
- All tests must pass:
mvn test - Add unit tests for new components
- Add integration tests for new protocols
- Security tests for input validation
- Update README.md with new features
- Add tests with 100% pass rate
- Update CHANGES.md with your changes
- Ensure no hardcoded credentials or secrets
- Follow commit message format: "Add/Fix/Update: description"
MIT License
Copyright (c) 2024
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Java 21 Project Loom - Virtual Threads foundation
- TechEmpower - Performance benchmarking framework
- RFC Authors - HTTP/2 (7540/7541), WebSocket (6455), SSE specs
- OWASP - Security best practices
- Prometheus - Metrics format
Built with ❤️ using Java 21 Virtual Threads