Q17 of 40 · REST Assured

Explain filters in REST Assured. Give an example of a custom filter.

REST AssuredMidrest-assuredfiltersinterceptorsloggingapi-testing

Short answer

Short answer: Filters are pre/post-request interceptors — they implement the Filter interface and receive the FilterableRequestSpecification and FilterContext. Common uses: injecting auth headers centrally, logging to a custom sink, adding correlation IDs, or masking sensitive values in CI logs. Register with .filter() or RestAssured.filters().

Detail

A filter has one method: Response filter(FilterableRequestSpecification req, FilterableResponseSpecification res, FilterContext ctx). It can modify the request before it is sent, call ctx.next(req, res) to forward it, then inspect or modify the response before returning it.

public class CorrelationIdFilter implements Filter {
    @Override
    public Response filter(FilterableRequestSpecification req,
                           FilterableResponseSpecification res,
                           FilterContext ctx) {
        req.header("X-Correlation-Id", UUID.randomUUID().toString());
        return ctx.next(req, res);
    }
}

Registration options:

  • Per-request: given().filter(new CorrelationIdFilter())
  • Suite-wide: RestAssured.filters(new CorrelationIdFilter())
  • In RequestSpecBuilder: builder.addFilter(new CorrelationIdFilter())

Built-in filters: RequestLoggingFilter, ResponseLoggingFilter, AllureRestAssured (from the allure-rest-assured library).

Filters execute in registration order — register logging filters last so they capture any headers added by earlier filters.

// EXAMPLE

HeaderMaskingFilter.java

// Custom filter that masks Authorization header in logs
public class MaskAuthFilter implements Filter {
    @Override
    public Response filter(FilterableRequestSpecification req,
                           FilterableResponseSpecification res,
                           FilterContext ctx) {
        String auth = req.getHeaders().getValue("Authorization");
        if (auth != null) {
            // Replace the real value with a masked version for log output
            req.removeHeader("Authorization");
            req.header("Authorization", auth.substring(0, 10) + "***MASKED***");
        }
        return ctx.next(req, res);
    }
}

// Register globally — all tests get masked auth in logs
@BeforeAll
static void setup() {
    RestAssured.filters(
        new MaskAuthFilter(),
        new RequestLoggingFilter(LogDetail.ALL),   // logs after masking
        new ResponseLoggingFilter(LogDetail.ALL)
    );
}

// WHAT INTERVIEWERS LOOK FOR

Understanding the filter signature (request, response, context), how to forward with ctx.next(), and real use cases beyond logging. Order of registration (later filters see modified headers) is a strong signal of hands-on experience.

// COMMON PITFALL

Forgetting to call ctx.next() in the filter body — the request is never sent and the test hangs or throws a NullPointerException on the null response.