Core server component of Eclipse Jetty web server providing HTTP server functionality, request handling, and connection management
—
Utility handlers provide specialized functionality for common web server needs including GZIP compression, CORS support, statistics collection, error handling, and request processing utilities.
Compresses response content using GZIP encoding to reduce bandwidth usage.
public class GzipHandler extends Handler.Wrapper implements GzipFactory {
// Constructors
public GzipHandler();
// Compression configuration
public int getMinGzipSize();
public void setMinGzipSize(int minGzipSize);
public int getCompressionLevel();
public void setCompressionLevel(int compressionLevel);
// Content type filtering
public Set<String> getIncludedMimeTypes();
public void setIncludedMimeTypes(String... types);
public Set<String> getExcludedMimeTypes();
public void setExcludedMimeTypes(String... types);
public Set<String> getIncludedMethods();
public void setIncludedMethods(String... methods);
public Set<String> getExcludedMethods();
public void setExcludedMethods(String... methods);
// Path filtering
public PathMappings<Boolean> getIncludedPaths();
public void addIncludedPaths(String... pathspecs);
public PathMappings<Boolean> getExcludedPaths();
public void addExcludedPaths(String... pathspecs);
// User agent filtering
public Set<String> getIncludedAgentPatterns();
public void setIncludedAgentPatterns(String... patterns);
public Set<String> getExcludedAgentPatterns();
public void setExcludedAgentPatterns(String... patterns);
// Deflater configuration
public boolean isCheckGzExists();
public void setCheckGzExists(boolean checkGzExists);
public boolean isSyncFlush();
public void setSyncFlush(boolean syncFlush);
public int getInflateBufferSize();
public void setInflateBufferSize(int size);
}public class GzipConfiguration {
public void setupGzipHandler(Server server) {
// Create GZIP handler
GzipHandler gzipHandler = new GzipHandler();
// Configure minimum size for compression (1KB)
gzipHandler.setMinGzipSize(1024);
// Set compression level (6 = default, good balance of speed/compression)
gzipHandler.setCompressionLevel(6);
// Include text-based content types
gzipHandler.setIncludedMimeTypes(
"text/html",
"text/plain",
"text/xml",
"text/css",
"application/javascript",
"application/json",
"application/xml"
);
// Exclude already compressed content
gzipHandler.setExcludedMimeTypes(
"image/jpeg",
"image/png",
"image/gif",
"application/zip",
"application/gzip"
);
// Only compress GET and POST requests
gzipHandler.setIncludedMethods("GET", "POST");
// Exclude paths that shouldn't be compressed
gzipHandler.addExcludedPaths("/api/binary/*", "/downloads/*");
// Set application handler as child
gzipHandler.setHandler(new ApplicationHandler());
server.setHandler(gzipHandler);
}
}Handles Cross-Origin Resource Sharing (CORS) for browser security.
public class CrossOriginHandler extends Handler.Wrapper {
// Origin configuration
public Set<String> getAllowedOriginPatterns();
public void setAllowedOriginPatterns(Set<String> allowedOriginPatterns);
public void addAllowedOrigin(String origin);
// Method configuration
public Set<String> getAllowedMethods();
public void setAllowedMethods(Set<String> allowedMethods);
public void addAllowedMethod(String method);
// Header configuration
public Set<String> getAllowedHeaders();
public void setAllowedHeaders(Set<String> allowedHeaders);
public void addAllowedHeader(String header);
public Set<String> getExposedHeaders();
public void setExposedHeaders(Set<String> exposedHeaders);
public void addExposedHeader(String header);
// Preflight configuration
public boolean isAllowCredentials();
public void setAllowCredentials(boolean allowCredentials);
public int getPreflightMaxAge();
public void setPreflightMaxAge(int preflightMaxAge);
// Chain configuration
public boolean isChainPreflight();
public void setChainPreflight(boolean chainPreflight);
}public class CORSConfiguration {
public void setupCORSHandler(Server server) {
CrossOriginHandler corsHandler = new CrossOriginHandler();
// Allow specific origins
corsHandler.setAllowedOriginPatterns(Set.of(
"https://example.com",
"https://*.example.com",
"http://localhost:*"
));
// Allow specific HTTP methods
corsHandler.setAllowedMethods(Set.of(
"GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"
));
// Allow specific headers
corsHandler.setAllowedHeaders(Set.of(
"Content-Type",
"Authorization",
"X-Requested-With",
"Accept",
"Origin"
));
// Expose custom headers to client
corsHandler.setExposedHeaders(Set.of(
"X-Total-Count",
"X-Page-Count"
));
// Allow credentials (cookies, authorization headers)
corsHandler.setAllowCredentials(true);
// Cache preflight requests for 1 hour
corsHandler.setPreflightMaxAge(3600);
corsHandler.setHandler(new ApiHandler());
server.setHandler(corsHandler);
}
public void setupDevelopmentCORS(Server server) {
// Permissive CORS for development
CrossOriginHandler corsHandler = new CrossOriginHandler();
corsHandler.setAllowedOriginPatterns(Set.of("*"));
corsHandler.setAllowedMethods(Set.of("*"));
corsHandler.setAllowedHeaders(Set.of("*"));
corsHandler.setAllowCredentials(false); // Can't use * origins with credentials
corsHandler.setHandler(new DevelopmentHandler());
server.setHandler(corsHandler);
}
}Collects comprehensive request and response statistics.
public class StatisticsHandler extends EventsHandler {
// Request statistics
public int getRequests();
public int getRequestsActive();
public int getRequestsActiveMax();
// Timing statistics
public long getStatsOnMs();
public long getRequestTimeTotal();
public long getRequestTimeMax();
public long getRequestTimeMean();
public long getRequestTimeStdDev();
// Response statistics by status
public int getResponses1xx();
public int getResponses2xx();
public int getResponses3xx();
public int getResponses4xx();
public int getResponses5xx();
// Byte statistics
public long getBytesReceived();
public long getBytesSent();
// Error statistics
public int getErrors();
public int getTimeouts();
// Async statistics
public int getAsyncRequests();
public int getAsyncRequestsWaiting();
public int getAsyncRequestsWaitingMax();
// Connection statistics
public int getConnections();
public int getConnectionsOpen();
public int getConnectionsOpenMax();
public Duration getConnectionsOpenMax();
// Statistics control
public void statsReset();
public String toStatsHTML();
}public class StatisticsConfiguration {
public void setupStatisticsHandler(Server server) {
StatisticsHandler statsHandler = new StatisticsHandler();
// Set up statistics collection
statsHandler.setHandler(new ApplicationHandler());
// Add statistics reporting endpoint
Handler.Sequence rootHandler = new Handler.Sequence();
rootHandler.addHandler(new StatsReportingHandler(statsHandler));
rootHandler.addHandler(statsHandler);
server.setHandler(rootHandler);
// Start periodic statistics logging
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
logStatistics(statsHandler);
}, 60, 60, TimeUnit.SECONDS);
}
private void logStatistics(StatisticsHandler stats) {
System.out.println("=== Server Statistics ===");
System.out.println("Active Requests: " + stats.getRequestsActive());
System.out.println("Total Requests: " + stats.getRequests());
System.out.println("2xx Responses: " + stats.getResponses2xx());
System.out.println("4xx Responses: " + stats.getResponses4xx());
System.out.println("5xx Responses: " + stats.getResponses5xx());
System.out.println("Bytes Sent: " + stats.getBytesSent());
System.out.println("Mean Response Time: " + stats.getRequestTimeMean() + "ms");
System.out.println("Errors: " + stats.getErrors());
}
}
// Handler to expose statistics via HTTP
public class StatsReportingHandler extends Handler.Abstract {
private final StatisticsHandler statisticsHandler;
public StatsReportingHandler(StatisticsHandler statisticsHandler) {
this.statisticsHandler = statisticsHandler;
}
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
if ("/stats".equals(request.getHttpURI().getPath())) {
response.setStatus(200);
response.getHeaders().put("Content-Type", "application/json");
String statsJson = createStatsJson(statisticsHandler);
response.write(true, ByteBuffer.wrap(statsJson.getBytes()), callback);
return true;
}
return false; // Not handled
}
private String createStatsJson(StatisticsHandler stats) {
Map<String, Object> statsMap = new HashMap<>();
statsMap.put("requests", stats.getRequests());
statsMap.put("requestsActive", stats.getRequestsActive());
statsMap.put("responses2xx", stats.getResponses2xx());
statsMap.put("responses4xx", stats.getResponses4xx());
statsMap.put("responses5xx", stats.getResponses5xx());
statsMap.put("bytesSent", stats.getBytesSent());
statsMap.put("bytesReceived", stats.getBytesReceived());
statsMap.put("meanResponseTime", stats.getRequestTimeMean());
statsMap.put("maxResponseTime", stats.getRequestTimeMax());
statsMap.put("errors", stats.getErrors());
statsMap.put("uptime", stats.getStatsOnMs());
// Convert to JSON (simplified)
return toJson(statsMap);
}
}Implements quality of service controls with request limiting and prioritization.
public class QoSHandler extends ConditionalHandler.Abstract {
// Request limiting
public int getMaxRequests();
public void setMaxRequests(int maxRequests);
// Suspend configuration
public long getMaxSuspend();
public void setMaxSuspend(long maxSuspend);
// Current state
public int getRequests();
public int getSuspended();
// Priority configuration
public int getPriority(Request request);
public void setPriority(Request request, int priority);
}Limits the number of threads processing requests.
public class ThreadLimitHandler extends ConditionalHandler.Abstract {
// Thread limiting
public int getThreadLimit();
public void setThreadLimit(int threadLimit);
// Current state
public int getThreads();
public boolean isForwardedIdleTimeout();
public void setForwardedIdleTimeout(boolean forwardedIdleTimeout);
}public class QoSConfiguration {
public void setupQoSHandlers(Server server) {
// Thread limiting handler
ThreadLimitHandler threadLimit = new ThreadLimitHandler();
threadLimit.setThreadLimit(50); // Max 50 concurrent processing threads
// Request limiting handler
QoSHandler qosHandler = new QoSHandler() {
@Override
protected boolean shouldHandle(Request request) {
// Apply QoS only to API requests
return request.getHttpURI().getPath().startsWith("/api/");
}
};
qosHandler.setMaxRequests(100); // Max 100 concurrent API requests
qosHandler.setMaxSuspend(30000); // Wait up to 30 seconds
// Chain handlers
threadLimit.setHandler(qosHandler);
qosHandler.setHandler(new ApplicationHandler());
server.setHandler(threadLimit);
}
public void setupPriorityQoS(Server server) {
QoSHandler priorityQoS = new QoSHandler() {
@Override
public int getPriority(Request request) {
// Prioritize authenticated users
if (request.getHeaders().get("Authorization") != null) {
return 0; // High priority
}
// Lower priority for anonymous users
return 1;
}
};
priorityQoS.setMaxRequests(50);
priorityQoS.setHandler(new ApplicationHandler());
server.setHandler(priorityQoS);
}
}Generates error pages for HTTP error responses.
public class ErrorHandler implements Request.Handler {
// Error page generation
public void handle(Request request, Response response, Callback callback) throws Exception;
public String getErrorPage(Request request, int code, String message);
public void writeErrorPage(Request request, Response response, Callback callback,
int code, String message, boolean showStacks);
// Configuration
public boolean isShowStacks();
public void setShowStacks(boolean showStacks);
public boolean isShowMessageInTitle();
public void setShowMessageInTitle(boolean showMessageInTitle);
// Caching
public String getCacheControl();
public void setCacheControl(String cacheControl);
}public class CustomErrorHandler extends ErrorHandler {
@Override
public void writeErrorPage(Request request, Response response, Callback callback,
int code, String message, boolean showStacks) {
response.getHeaders().put("Content-Type", "text/html; charset=utf-8");
String errorPage = generateCustomErrorPage(code, message, request);
response.write(true, ByteBuffer.wrap(errorPage.getBytes()), callback);
}
private String generateCustomErrorPage(int code, String message, Request request) {
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html>\n");
html.append("<html>\n<head>\n");
html.append("<title>Error ").append(code).append("</title>\n");
html.append("<style>\n");
html.append("body { font-family: Arial, sans-serif; margin: 40px; }\n");
html.append(".error-container { max-width: 600px; margin: 0 auto; }\n");
html.append(".error-code { font-size: 72px; color: #dc3545; margin: 0; }\n");
html.append(".error-message { font-size: 24px; color: #6c757d; margin: 10px 0; }\n");
html.append("</style>\n");
html.append("</head>\n<body>\n");
html.append("<div class='error-container'>\n");
html.append("<h1 class='error-code'>").append(code).append("</h1>\n");
html.append("<p class='error-message'>").append(escapeHtml(message)).append("</p>\n");
if (code == 404) {
html.append("<p>The requested resource was not found on this server.</p>\n");
} else if (code >= 500) {
html.append("<p>An internal server error occurred. Please try again later.</p>\n");
}
html.append("<hr>\n");
html.append("<p><small>Request ID: ").append(request.getId()).append("</small></p>\n");
html.append("</div>\n</body>\n</html>");
return html.toString();
}
private String escapeHtml(String text) {
return text.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
}Limits request and response sizes to prevent resource exhaustion.
public class SizeLimitHandler extends Handler.Wrapper {
// Request size limiting
public long getRequestLimit();
public void setRequestLimit(long requestLimit);
// Response size limiting
public long getResponseLimit();
public void setResponseLimit(long responseLimit);
// Limit exceeded behavior
public String getLimitExceededMessage();
public void setLimitExceededMessage(String limitExceededMessage);
}public class SizeLimitConfiguration {
public void setupSizeLimits(Server server) {
SizeLimitHandler sizeLimitHandler = new SizeLimitHandler();
// Limit request size to 10MB
sizeLimitHandler.setRequestLimit(10 * 1024 * 1024);
// Limit response size to 50MB
sizeLimitHandler.setResponseLimit(50 * 1024 * 1024);
// Custom error message
sizeLimitHandler.setLimitExceededMessage("Content size limit exceeded");
sizeLimitHandler.setHandler(new ApplicationHandler());
server.setHandler(sizeLimitHandler);
}
}Sets idle timeout for individual requests.
public class IdleTimeoutHandler extends Handler.Wrapper {
// Timeout configuration
public long getIdleTimeout();
public void setIdleTimeout(long idleTimeout);
// Apply timeout conditions
public boolean apply(String pathInContext, Request request, Response response);
}Adds artificial delay to request processing for testing or rate limiting.
public class DelayedHandler extends Handler.Wrapper {
// Delay configuration
public long getDelayMs();
public void setDelayMs(long delayMs);
}public class UtilityHandlerChain {
public Handler createUtilityChain() {
// Statistics collection (outermost)
StatisticsHandler statsHandler = new StatisticsHandler();
// GZIP compression
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setMinGzipSize(1024);
gzipHandler.setIncludedMimeTypes("text/html", "text/css", "application/javascript", "application/json");
// CORS support
CrossOriginHandler corsHandler = new CrossOriginHandler();
corsHandler.setAllowedOriginPatterns(Set.of("https://*.example.com"));
corsHandler.setAllowedMethods(Set.of("GET", "POST", "PUT", "DELETE"));
// Size limiting
SizeLimitHandler sizeLimitHandler = new SizeLimitHandler();
sizeLimitHandler.setRequestLimit(10 * 1024 * 1024); // 10MB
// QoS limiting
QoSHandler qosHandler = new QoSHandler();
qosHandler.setMaxRequests(200);
// Application handler
Handler applicationHandler = new ApplicationHandler();
// Chain them together
statsHandler.setHandler(gzipHandler);
gzipHandler.setHandler(corsHandler);
corsHandler.setHandler(sizeLimitHandler);
sizeLimitHandler.setHandler(qosHandler);
qosHandler.setHandler(applicationHandler);
return statsHandler;
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-server