Introduction

Quarkus, the Kubernetes-native Java framework, provides powerful mechanisms to manage HTTP requests and responses efficiently. One of these mechanisms is filters, which allow developers to intercept and manipulate incoming requests and outgoing responses. Filters in Quarkus are commonly used for logging, authentication, authorization, compression, and other cross-cutting concerns.

In this article, we will explore the concept of filters in Quarkus, how to implement them, and use cases where they can be beneficial.

What Are Filters in Quarkus?

Filters in Quarkus are components that allow developers to pre-process and post-process HTTP requests and responses. These filters operate on both inbound and outbound traffic, making them ideal for applying generic behaviors such as logging, security enforcement, and response modification.

Types of Filters in Quarkus

  1. ContainerRequestFilter: Intercepts incoming requests before they reach the resource method.
  2. ContainerResponseFilter: Modifies the response before it is sent to the client.

Both types of filters are implemented using Java EE’s JAX-RS API, making them easy to integrate into Quarkus applications.

Implementing Filters in Quarkus

1. Creating a Request Filter

A ContainerRequestFilter allows us to intercept and process requests before they reach the application logic.

import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.logging.Logger;

@Provider
public class LoggingRequestFilter implements ContainerRequestFilter {
    private static final Logger LOGGER = Logger.getLogger(LoggingRequestFilter.class.getName());

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        LOGGER.info("Incoming request: " + requestContext.getUriInfo().getRequestUri());
    }
}

2. Creating a Response Filter

A ContainerResponseFilter is useful for modifying response headers, compressing data, or adding common response attributes.

import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class CustomResponseFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        responseContext.getHeaders().add("X-Custom-Header", "QuarkusFilter");
    }
}

Use Cases of Filters in Quarkus

  1. Logging Requests and Responses – Tracking API requests for debugging and monitoring.
  2. Security Enforcement – Implementing authentication and authorization logic.
  3. Data Compression – Reducing response size for better performance.
  4. Rate Limiting – Controlling access to APIs based on predefined thresholds.
  5. Header Manipulation – Adding custom headers for security or tracking purposes.

Best Practices for Using Filters in Quarkus

  • Keep Filters Lightweight: Heavy operations in filters can slow down request processing.
  • Use CDI Beans for Dependency Injection: Leverage Quarkus CDI capabilities to inject required services.
  • Order Filters Properly: Ensure execution order does not conflict with other application logic.
  • Avoid Business Logic in Filters: Filters should only be used for generic concerns like security and logging.

External Resources

FAQs

1. What is the purpose of filters in Quarkus?

Filters in Quarkus allow developers to intercept and manipulate HTTP requests and responses, making them useful for logging, authentication, and response modification.

2. How do you register a filter in Quarkus?

Filters in Quarkus are automatically discovered when annotated with @Provider and placed in the classpath.

3. Can I use multiple filters in a Quarkus application?

Yes, you can define multiple request and response filters, and they will be executed in the order they are registered.

4. What is the difference between a filter and an interceptor in Quarkus?

Filters operate on HTTP requests and responses, while interceptors work at the CDI level to intercept method calls.

5. How can I modify request headers in Quarkus?

Using ContainerRequestFilter, you can modify request headers using requestContext.getHeaders().putSingle("Header-Name", "value");

6. How can I add a custom header to a response in Quarkus?

You can use ContainerResponseFilter and modify the response headers using responseContext.getHeaders().add("Header-Name", "value");

7. Do filters impact performance in Quarkus?

Filters introduce minimal overhead but should be optimized to avoid unnecessary processing.

8. Can filters be used for CORS handling in Quarkus?

Yes, you can create a response filter to add the necessary CORS headers.

9. How do I ensure filters execute in a specific order?

You can define filter priorities using the @Priority annotation.

10. Is it possible to disable filters conditionally?

Yes, you can use configuration properties or environment variables to enable or disable filters dynamically.

Conclusion

Filters in Quarkus are powerful tools for managing HTTP request and response lifecycle events. By leveraging ContainerRequestFilter and ContainerResponseFilter, developers can enhance security, logging, and other cross-cutting concerns efficiently. Following best practices will ensure optimal performance and maintainability in Quarkus applications.