CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty-ee10--jetty-ee10-servlets

Collection of utility servlets and filters for Jakarta EE 10 web applications including CORS, DoS protection, QoS management, header manipulation, and server-sent events.

Pending
Overview
Eval results
Files

base-filtering.mddocs/

Base Filtering Patterns

Abstract base class for filters that need path, MIME type, or HTTP method-based filtering capabilities. The IncludeExcludeBasedFilter provides a foundation for creating custom filters with flexible request matching criteria.

Capabilities

IncludeExcludeBasedFilter

Abstract base class providing common filtering patterns for servlet filters.

/**
 * Abstract base filter for include/exclude filtering based on paths, MIME types, and HTTP methods.
 * Provides common functionality for filters that need to selectively process requests.
 */
public abstract class IncludeExcludeBasedFilter implements Filter {
    /**
     * Initialize the filter with include/exclude configuration parameters
     * @param filterConfig Filter configuration containing include/exclude parameters
     * @throws ServletException if configuration is invalid
     */
    public void init(FilterConfig filterConfig) throws ServletException;
    
    /**
     * Clean up filter resources
     */
    public void destroy();
    
    /**
     * Get string representation of the filter configuration
     * @return String describing the include/exclude patterns
     */
    public String toString();
    
    /**
     * Determine if the request should be filtered based on configured patterns
     * @param httpRequest The HTTP request
     * @param httpResponse The HTTP response  
     * @return true if the request should be processed by this filter
     */
    protected boolean shouldFilter(HttpServletRequest httpRequest, HttpServletResponse httpResponse);
    
    /**
     * Guess the MIME type of the response for filtering decisions
     * @param httpRequest The HTTP request
     * @param httpResponse The HTTP response
     * @return The guessed MIME type or null if cannot be determined
     */
    protected String guessMimeType(HttpServletRequest httpRequest, HttpServletResponse httpResponse);
}

Configuration Parameters

Path Filtering

includedPaths: Comma-separated list of path specifications to include excludedPaths: Comma-separated list of path specifications to exclude

Path specifications support three formats:

  • Regex patterns: Start with ^ (e.g., ^/api/v\d+/.*)
  • Servlet patterns: Start with / for exact or prefix matching (e.g., /admin/*, /api/users)
  • Suffix patterns: Start with *. for extension matching (e.g., *.jsp, *.html)

MIME Type Filtering

includedMimeTypes: Comma-separated list of MIME types to include excludedMimeTypes: Comma-separated list of MIME types to exclude

MIME type patterns support:

  • Exact matching: text/html, application/json
  • Wildcard matching: text/*, image/*, application/*

HTTP Method Filtering

includedHttpMethods: Comma-separated list of HTTP methods to include excludedHttpMethods: Comma-separated list of HTTP methods to exclude

Standard HTTP methods: GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, TRACE

Usage Examples

Custom Security Filter

import org.eclipse.jetty.ee10.servlets.IncludeExcludeBasedFilter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * Custom security filter that adds security headers to specific paths
 */
public class SecurityHeaderFilter extends IncludeExcludeBasedFilter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        // Check if this request should be filtered
        if (shouldFilter(httpRequest, httpResponse)) {
            // Add security headers
            httpResponse.setHeader("X-Frame-Options", "DENY");
            httpResponse.setHeader("X-Content-Type-Options", "nosniff");
            httpResponse.setHeader("X-XSS-Protection", "1; mode=block");
        }
        
        // Continue with the filter chain
        chain.doFilter(request, response);
    }
}

Configuration:

<filter>
    <filter-name>SecurityHeaderFilter</filter-name>
    <filter-class>com.example.SecurityHeaderFilter</filter-class>
    <!-- Only apply to HTML pages -->
    <init-param>
        <param-name>includedMimeTypes</param-name>
        <param-value>text/html</param-value>
    </init-param>
    <!-- Skip admin pages (they have their own security) -->
    <init-param>
        <param-name>excludedPaths</param-name>
        <param-value>/admin/*</param-value>
    </init-param>
</filter>

Custom Logging Filter

/**
 * Logging filter that logs specific types of requests
 */
public class ApiLogFilter extends IncludeExcludeBasedFilter {
    private static final Logger logger = LoggerFactory.getLogger(ApiLogFilter.class);
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        long startTime = System.currentTimeMillis();
        
        try {
            chain.doFilter(request, response);
        } finally {
            // Log if this request should be filtered
            if (shouldFilter(httpRequest, httpResponse)) {
                long duration = System.currentTimeMillis() - startTime;
                logger.info("API Request: {} {} - Status: {} - Duration: {}ms",
                           httpRequest.getMethod(),
                           httpRequest.getRequestURI(),
                           httpResponse.getStatus(),
                           duration);
            }
        }
    }
}

Configuration:

<filter>
    <filter-name>ApiLogFilter</filter-name>
    <filter-class>com.example.ApiLogFilter</filter-class>
    <!-- Only log API endpoints -->
    <init-param>
        <param-name>includedPaths</param-name>
        <param-value>/api/*</param-value>
    </init-param>
    <!-- Only log POST, PUT, DELETE (not GET) -->
    <init-param>
        <param-name>includedHttpMethods</param-name>
        <param-value>POST,PUT,DELETE</param-value>
    </init-param>
</filter>

Custom Compression Filter

/**
 * Simple compression filter that compresses specific content types
 */
public class CompressionFilter extends IncludeExcludeBasedFilter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        // Check if client accepts gzip
        String acceptEncoding = httpRequest.getHeader("Accept-Encoding");
        boolean clientSupportsGzip = acceptEncoding != null && 
                                   acceptEncoding.toLowerCase().contains("gzip");
        
        if (clientSupportsGzip && shouldFilter(httpRequest, httpResponse)) {
            // Wrap response with compression
            GzipResponseWrapper wrappedResponse = new GzipResponseWrapper(httpResponse);
            chain.doFilter(request, wrappedResponse);
            wrappedResponse.finish();
        } else {
            chain.doFilter(request, response);
        }
    }
}

Configuration:

<filter>
    <filter-name>CompressionFilter</filter-name>
    <filter-class>com.example.CompressionFilter</filter-class>
    <!-- Compress text content -->
    <init-param>
        <param-name>includedMimeTypes</param-name>
        <param-value>text/html,text/css,text/javascript,application/json,application/xml</param-value>
    </init-param>
    <!-- Don't compress images -->
    <init-param>
        <param-name>excludedMimeTypes</param-name>
        <param-value>image/*</param-value>
    </init-param>
    <!-- Only compress larger files -->
    <init-param>
        <param-name>excludedPaths</param-name>
        <param-value>*.ico,/favicon.ico</param-value>
    </init-param>
</filter>

Custom Authentication Filter

/**
 * Authentication filter that checks tokens for specific endpoints
 */
public class TokenAuthFilter extends IncludeExcludeBasedFilter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        if (shouldFilter(httpRequest, httpResponse)) {
            String authHeader = httpRequest.getHeader("Authorization");
            
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, 
                                     "Missing or invalid authorization header");
                return;
            }
            
            String token = authHeader.substring(7);
            if (!validateToken(token)) {
                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, 
                                     "Invalid token");
                return;
            }
        }
        
        chain.doFilter(request, response);
    }
    
    private boolean validateToken(String token) {
        // Implementation-specific token validation
        return TokenService.isValid(token);
    }
}

Configuration:

<filter>
    <filter-name>TokenAuthFilter</filter-name>
    <filter-class>com.example.TokenAuthFilter</filter-class>
    <!-- Only protect API endpoints -->
    <init-param>
        <param-name>includedPaths</param-name>
        <param-value>/api/*</param-value>
    </init-param>
    <!-- Skip authentication endpoints -->
    <init-param>
        <param-name>excludedPaths</param-name>
        <param-value>/api/auth/*,/api/public/*</param-value>
    </init-param>
    <!-- Only for operations that modify data -->
    <init-param>
        <param-name>includedHttpMethods</param-name>
        <param-value>POST,PUT,DELETE,PATCH</param-value>
    </init-param>
</filter>

Path Specification Patterns

Exact Match

/admin/users

Matches only the exact path /admin/users.

Prefix Match

/api/*

Matches any path starting with /api/ including:

  • /api/users
  • /api/products/123
  • /api/v1/search

Suffix Match

*.jsp
*.html
*.css

Matches any path ending with the specified extension.

Regex Match

^/user/\d+$
^/api/v\d+/.*

Matches paths using regular expression patterns. Must start with ^.

MIME Type Patterns

Exact MIME Type

text/html
application/json
application/pdf

Wildcard MIME Type

text/*        # All text types
image/*       # All image types
application/* # All application types

Multiple MIME Types

text/html,text/css,text/javascript

Advanced Configuration Examples

Complex Path Filtering

<filter>
    <filter-name>ComplexPathFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
    <!-- Include API and admin paths -->
    <init-param>
        <param-name>includedPaths</param-name>
        <param-value>/api/*,/admin/*</param-value>
    </init-param>
    <!-- Exclude specific admin and API paths -->
    <init-param>
        <param-name>excludedPaths</param-name>
        <param-value>/admin/login,/api/health,/api/public/*</param-value>
    </init-param>
</filter>

Content-Type Based Filtering

<filter>
    <filter-name>ContentTypeFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
    <!-- Include JSON and XML responses -->
    <init-param>
        <param-name>includedMimeTypes</param-name>  
        <param-value>application/json,application/xml,text/xml</param-value>
    </init-param>
    <!-- Exclude binary content -->
    <init-param>
        <param-name>excludedMimeTypes</param-name>
        <param-value>image/*,video/*,application/octet-stream</param-value>
    </init-param>
</filter>

Method-Specific Filtering

<filter>
    <filter-name>WriteOperationFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
    <!-- Only filter write operations -->
    <init-param>
        <param-name>includedHttpMethods</param-name>
        <param-value>POST,PUT,DELETE,PATCH</param-value>
    </init-param>
    <!-- Skip OPTIONS (preflight) -->
    <init-param>
        <param-name>excludedHttpMethods</param-name>
        <param-value>OPTIONS</param-value>
    </init-param>
</filter>

Combined Filtering Strategy

<filter>
    <filter-name>CombinedFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
    <!-- Filter API endpoints -->
    <init-param>
        <param-name>includedPaths</param-name>
        <param-value>/api/*</param-value>
    </init-param>
    <!-- Only JSON responses -->
    <init-param>
        <param-name>includedMimeTypes</param-name>
        <param-value>application/json</param-value>
    </init-param>
    <!-- Only write operations -->
    <init-param>
        <param-name>includedHttpMethods</param-name>
        <param-value>POST,PUT,DELETE</param-value>
    </init-param>
    <!-- Skip health checks -->
    <init-param>
        <param-name>excludedPaths</param-name>
        <param-value>/api/health,/api/status</param-value>
    </init-param>
</filter>

Implementation Guidelines

Filter Logic Pattern

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
    
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    
    // Check if this request should be processed
    if (shouldFilter(httpRequest, httpResponse)) {
        // Apply your filter logic here
        processRequest(httpRequest, httpResponse);
    }
    
    // Always continue the chain
    chain.doFilter(request, response);
}

MIME Type Detection

The base class provides MIME type detection through:

  • Response content type (if already set)
  • Request URI extension mapping
  • Servlet context MIME type mapping

Performance Considerations

  • Path matching is cached for performance
  • MIME type detection may require response buffering
  • Use specific patterns rather than broad wildcards when possible

Common Use Cases

Content Processing

Apply transformations only to specific content types (HTML, JSON, XML).

Security Filters

Add security headers or authentication checks to sensitive paths.

Performance Monitoring

Log or monitor specific API endpoints or operations.

Content Compression

Compress responses for text-based content types.

Caching Headers

Add cache control headers to static resources or API responses.

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty-ee10--jetty-ee10-servlets

docs

base-filtering.md

cors-filter.md

dos-protection.md

header-management.md

index.md

quality-of-service.md

server-sent-events.md

tile.json