QA How-To
REST Assured logging filters: A Practical Guide (2026)
Use REST Assured logging filters safely with runnable Java examples for failed-test diagnostics, redaction, custom filters, ordering, and secure CI reports.
24 min read | 3,123 words
TL;DR
REST Assured logging filters can print request and response details, but production suites should default to logging only on validation failure. Redact credentials, keep bodies bounded, add correlation IDs, and use ordered custom filters only for diagnostics that the built-in logging DSL cannot provide.
Key Takeaways
- Prefer failure-only request and response logging for routine automated suites.
- Blacklist secret headers and sanitize sensitive body fields before logs reach CI artifacts.
- Remember that request logs describe the REST Assured specification, not guaranteed wire-level bytes.
- Use custom filters for correlation, timing, and attachments, while always continuing through FilterContext.
- Control dependent filter execution with OrderedFilter and test the order explicitly.
- Capture bounded diagnostics in memory when a reporting extension should publish them only after failure.
- Treat logs as production data with access controls, retention limits, and ownership.
REST Assured logging filters make failed API tests diagnosable by showing the request specification and returned response near the assertion failure. The safest default in 2026 is not .log().all() on every call. It is conditional logging, secret redaction, bounded output, and a correlation ID that connects the test to server-side traces.
This guide uses Java 17, JUnit 5, and REST Assured 6.0.1. The examples use public APIs from io.restassured.filter, io.restassured.filter.log, and io.restassured.config. They are designed for real suites where logs are uploaded by CI and may be read by more people than the test source.
TL;DR
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
class HealthLoggingTest {
@Test
void logs_request_and_response_only_when_validation_fails() {
given()
.baseUri(System.getProperty("baseUrl", "http://localhost:8080"))
.log().ifValidationFails()
.when()
.get("/api/health")
.then()
.log().ifValidationFails()
.statusCode(200)
.body("status", equalTo("UP"));
}
}
| Mechanism | When it writes | Best use | Main risk |
|---|---|---|---|
.log().all() |
Every execution | Local investigation of one test | Noise and secret exposure |
.log().ifValidationFails() |
A REST Assured validation fails | Normal CI diagnostics | Does not cover failures after extraction |
RequestLoggingFilter |
When the filter runs | Central request logging | Later filters may change the request |
ResponseLoggingFilter |
According to its configuration | Central response logging | Large or sensitive bodies |
Custom Filter |
Whatever logic you implement | Correlation, timing, report attachments | Bugs can alter requests or hide failures |
1. How REST Assured logging filters work
A REST Assured filter surrounds an HTTP exchange. Its filter method receives a mutable request specification, a response specification, and a FilterContext. Calling context.next(requestSpec, responseSpec) passes control to the next filter and eventually dispatches the request. When that call returns, the filter can inspect the Response. This around-call model supports logging, authentication, correlation headers, metrics, and reporting.
REST Assured also exposes fluent logging shortcuts. Request logging is configured in the given phase, while response logging is configured after then. The shortcuts are usually clearer for a single test. Filter classes are useful when a shared specification or framework policy should apply the behavior to many tests.
The important limitation is that RequestLoggingFilter prints the request specification visible at its position in the filter chain. A later filter or the underlying HTTP client can add or change headers. Therefore, the output is a strong diagnostic of what the test asked REST Assured to send, but it is not a byte-for-byte network capture. Use approved transport logging or server traces when exact wire behavior matters.
A filter must call next exactly once in ordinary use. Forgetting it means no request is sent. Calling it twice sends two requests, which is dangerous for POST, payment, or mutation endpoints. A diagnostic filter should observe without changing functional behavior.
For a broader introduction to the DSL around these filters, read REST Assured given when then.
2. Set up a runnable REST Assured 6.0.1 project
REST Assured 6 requires Java 17 or newer. A small Maven project can run the examples with JUnit Jupiter. Pin versions through properties so an upgrade is deliberate and reviewable.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qajobfit.examples</groupId>
<artifactId>rest-assured-logging</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<rest-assured.version>6.0.1</rest-assured.version>
<junit.version>5.13.4</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
</plugin>
</plugins>
</build>
</project>
Put tests in src/test/java, start the system under test, and pass its URL without storing credentials in source.
mvn test -DbaseUrl=http://localhost:8080
The examples intentionally use a local default so they compile without organization-specific configuration. A real suite should fail early if the selected environment requires an explicit URL. Avoid global RestAssured.baseURI when parallel classes target different services. A reusable request specification is easier to isolate and review.
3. Choose the right logging level
Request logging supports focused choices such as .log().method(), .log().uri(), .log().headers(), .log().params(), .log().cookies(), .log().body(), and .log().all(). Response logging supports status, headers, cookies, body, and all details. Log only the evidence needed for the failure you are investigating.
given()
.baseUri(baseUrl)
.queryParam("state", "active")
.log().method()
.log().uri()
.when()
.get("/api/users")
.then()
.log().status()
.statusCode(200);
Always-on method and URI output can be acceptable for a small smoke suite. Always-on bodies rarely are. Bodies may contain passwords, reset links, OAuth tokens, personal data, health data, or thousands of records. They also make the actual assertion message hard to find.
Use .then().log().ifError() when an HTTP 4xx or 5xx response itself is the trigger. Use .then().log().ifStatusCodeIsEqualTo(429) when one status deserves focused evidence. Use .then().log().ifStatusCodeMatches(greaterThanOrEqualTo(500)) for a matcher-based response rule. These conditions differ from validation-failure logging. A deliberately asserted 400 response is not an HTTP error from the test's perspective, while an unexpected 200 can still fail a body assertion.
During local test creation, full logging helps reveal JSON paths and headers. Remove or narrow it before commit. A useful review question is, "Would this log remain safe if the test uses a real staging account tomorrow?"
4. Configure REST Assured logging filters for failures
Failure-only logging is the strongest general policy because it keeps successful build output short and preserves request and response context for REST Assured assertion failures. Configure it per request when tests have different sensitivity policies.
import io.restassured.config.LogConfig;
import io.restassured.config.RestAssuredConfig;
import io.restassured.filter.log.LogDetail;
RestAssuredConfig diagnosticConfig = RestAssuredConfig.config()
.logConfig(LogConfig.logConfig()
.enableLoggingOfRequestAndResponseIfValidationFails(LogDetail.ALL));
given()
.config(diagnosticConfig)
.baseUri(baseUrl)
.when()
.get("/api/orders/{id}", orderId)
.then()
.statusCode(200)
.body("id", equalTo(orderId));
The fluent pair .log().ifValidationFails() on both sides is more visible inside a test. LogConfig is better when a request specification owns the suite policy. The global shortcut RestAssured.enableLoggingOfRequestAndResponseIfValidationFails() exists, but mutable global state can leak across test classes and complicate parallel runs.
Conditional logging is tied to REST Assured validation. If you extract a response and later use JUnit assertions, a failure in those assertions does not automatically trigger REST Assured's conditional response log. Either keep relevant HTTP assertions in .then(), capture bounded diagnostics into a per-test buffer, or attach the sanitized response through a JUnit extension when the test fails.
Do not catch an assertion error just to print data and then return. If a custom reporting layer catches it, attach diagnostics and rethrow the original error so the test remains failed and its stack trace is preserved.
5. Redact authorization, cookies, and sensitive fields
REST Assured LogConfig can blacklist headers. The logged value becomes a blacklist marker while the actual request still carries the original value. Apply the same policy to obvious and organization-specific credential headers.
LogConfig safeLogConfig = LogConfig.logConfig()
.blacklistHeader("Authorization")
.blacklistHeader("Cookie")
.blacklistHeader("Set-Cookie")
.blacklistHeader("X-API-Key");
given()
.config(RestAssuredConfig.config().logConfig(safeLogConfig))
.baseUri(baseUrl)
.header("Authorization", "Bearer " + accessToken)
.log().ifValidationFails()
.when()
.get("/api/me")
.then()
.log().ifValidationFails()
.statusCode(200);
Header blacklisting does not sanitize bodies, query parameters, URLs, multipart parts, or application-generated messages. A token passed as ?access_token= can still appear in the URI. Passwords inside JSON remain visible if body logging is enabled. The better fix is to keep secrets out of URLs and use synthetic data. When a sensitive body must be tested, log only status and selected safe headers, or create a sanitizer that parses a copy for reporting.
Never mutate the actual request body merely to redact the log. Sanitize a diagnostic representation. Regex replacement is fragile for nested JSON, escaped values, arrays, XML, and compressed content. Prefer content-type-aware parsing with an allowlist of fields that may be reported. If parsing fails, omit the body and state why.
CI artifacts need access controls and expiration even after redaction. Correlation identifiers, tenant IDs, and endpoint paths can still reveal operational details. The API security testing basics guide helps turn these concerns into a broader security test plan.
6. Use built-in RequestLoggingFilter and ResponseLoggingFilter
The built-in filter classes centralize logging outside the fluent chain. Their no-argument forms write standard details to the default output. Add them to a request with .filter(...) or .filters(...).
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.log.ResponseLoggingFilter;
given()
.baseUri(baseUrl)
.filters(new RequestLoggingFilter(), new ResponseLoggingFilter())
.when()
.get("/api/health")
.then()
.statusCode(200);
This logs every matching exchange, so it is primarily useful for local debugging, small controlled suites, or output redirected to a per-test buffer. ErrorLoggingFilter is another built-in option for error responses. Do not confuse an HTTP error condition with an assertion failure. Negative tests intentionally exercise errors and may pass, while a wrong success payload can fail without an HTTP error.
Filter placement matters. A request logging filter that runs before a correlation filter will not display the added correlation header. A response filter sees the response returned through the chain. When diagnostics depend on modifications, define order deliberately instead of relying on list position scattered across helpers.
Avoid installing both built-in filters and the equivalent .log().all() calls unless duplicate output is intentional. Frameworks often accumulate logging in a base specification, a client helper, and the test itself. One request then appears several times with slightly different details, which confuses incident analysis. Establish one owner for suite-wide diagnostics.
When a test produces many polling requests, log the final unsuccessful attempt plus a compact attempt summary. Printing every full response can overwhelm the report and hide the useful end state.
7. Build a safe custom correlation and timing filter
A custom filter is appropriate when every request needs a unique correlation ID and a compact timing line. The following implementation uses supported REST Assured interfaces and changes only one diagnostic header.
package com.qajobfit.logging;
import io.restassured.filter.Filter;
import io.restassured.filter.FilterContext;
import io.restassured.response.Response;
import io.restassured.specification.FilterableRequestSpecification;
import io.restassured.specification.FilterableResponseSpecification;
import java.time.Duration;
import java.util.UUID;
public final class CorrelationTimingFilter implements Filter {
@Override
public Response filter(
FilterableRequestSpecification request,
FilterableResponseSpecification responseSpec,
FilterContext context) {
String correlationId = UUID.randomUUID().toString();
request.header("X-Correlation-Id", correlationId);
long started = System.nanoTime();
Response response = context.next(request, responseSpec);
long elapsedMs = Duration.ofNanos(System.nanoTime() - started).toMillis();
System.out.printf(
"api_call method=%s uri=%s status=%d elapsed_ms=%d correlation_id=%s%n",
request.getMethod(),
request.getURI(),
response.statusCode(),
elapsedMs,
correlationId
);
return response;
}
}
Apply it with given().filter(new CorrelationTimingFilter()). System.nanoTime() is correct for elapsed time because it is monotonic within the process. This measurement includes client processing and network time, so do not label it server duration. Also avoid asserting a tight service-level threshold from a shared CI runner based on this value alone.
For real reporting, replace standard output with a test-scoped event sink. Keep the event structured and bounded. Do not include the authorization header or body. If the request already has a caller-supplied correlation ID, decide whether the filter should preserve it, reject duplicates, or replace it, then document that policy.
8. Control filter ordering with OrderedFilter
REST Assured supports OrderedFilter for deterministic precedence. A lower returned number runs earlier on the request path. Filters without an explicit order have the default precedence documented by REST Assured. Use well-spaced constants so another filter can be inserted later.
import io.restassured.filter.FilterContext;
import io.restassured.filter.OrderedFilter;
import io.restassured.response.Response;
import io.restassured.specification.FilterableRequestSpecification;
import io.restassured.specification.FilterableResponseSpecification;
public final class FixedCorrelationFilter implements OrderedFilter {
private final String correlationId;
public FixedCorrelationFilter(String correlationId) {
this.correlationId = correlationId;
}
@Override
public int getOrder() {
return 100;
}
@Override
public Response filter(
FilterableRequestSpecification request,
FilterableResponseSpecification responseSpec,
FilterContext context) {
request.header("X-Correlation-Id", correlationId);
return context.next(request, responseSpec);
}
}
An authentication filter might run after environment selection but before logging. A redacting logger should see the final header names while never printing their values. On the response path, completion unwinds through filters in the opposite direction, just like nested function calls. Draw the order when several filters depend on each other.
Test filter order against a local stub or fake endpoint. Assert that the server receives the correlation header once, that the logger shows the expected redacted marker, and that one call produces one server interaction. This is framework code, so it deserves focused tests rather than being trusted because individual API scenarios pass.
Avoid using filter order as a hidden business workflow. Filters should supply cross-cutting transport behavior. Resource creation, retries with domain consequences, and state transitions belong in explicit clients or scenario code.
9. Capture diagnostics for JUnit and CI reports
Console output is easy, but parallel tests can interleave lines. A better pattern is a separate ByteArrayOutputStream per test, connected to logging filters or configured output, then attached to the test report only on failure. Keep the buffer test-scoped and close any wrapping streams.
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.log.ResponseLoggingFilter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintStream diagnostics = new PrintStream(bytes, true, StandardCharsets.UTF_8);
var response = given()
.baseUri(baseUrl)
.filters(
new RequestLoggingFilter(diagnostics),
new ResponseLoggingFilter(diagnostics)
)
.when()
.get("/api/health");
String captured = bytes.toString(StandardCharsets.UTF_8);
response.then().statusCode(200);
This example captures every detail produced by those filter constructors, so apply redaction and output limits before using it for sensitive endpoints. A framework can combine the buffer with a JUnit 5 extension that publishes sanitized content only when execution fails. Do not use a static buffer, because concurrent tests will mix data and can expose one tenant's response in another test's report.
Set a maximum attachment size. For a huge response, retain status, content type, correlation ID, selected headers, byte length, and a truncated safe excerpt. State clearly that the excerpt was truncated. Binary bodies should normally be described by media type, length, and perhaps a checksum, not converted into console text.
If your team uses Allure or another report system, keep the REST Assured filter independent of the vendor where practical. Emit a small diagnostic model, then let an adapter attach it. This reduces lock-in and makes the filter unit-testable.
10. Diagnose redirects, retries, and asynchronous polling
A single logical API operation can create multiple HTTP exchanges through redirects, client retries, token refresh, or polling. Logging must make each exchange identifiable. Include method, resolved URI without secret query values, status, attempt number, elapsed time, and correlation ID.
REST Assured may follow redirects according to its configuration. When redirect behavior is under test, disable following so an unexpected 302 is not hidden by the final 200.
given()
.baseUri(baseUrl)
.redirects().follow(false)
.log().ifValidationFails()
.when()
.get("/api/legacy-report")
.then()
.log().ifValidationFails()
.statusCode(301)
.header("Location", "/api/reports/current");
Do not implement automatic retries in a generic logging filter. Retrying POST can duplicate side effects, and retrying every 500 can conceal defects. If a documented operation is retryable, encode idempotency rules, bounded attempts, backoff, and retryable statuses in an explicit client policy. Log each attempt compactly and preserve the final response.
For eventual consistency, polling is more honest than a fixed sleep. Record the operation ID, poll the documented status endpoint until a deadline, and attach the last response if the condition is not met. The API error handling and negative testing guide explains how to distinguish expected error contracts from infrastructure failures.
11. Test the logging layer itself
Logging code can leak secrets, duplicate requests, consume response streams, or make passing tests fail. Treat it as production-quality code. Unit-test a sanitizer with nested objects, arrays, escaped text, missing fields, non-JSON bodies, and invalid encodings. Verify that known secrets never appear in captured output.
At integration level, point REST Assured at a local stub server. Send an authorization header, a cookie, and a JSON password. Assert that the server receives the real values while the captured log contains redaction markers. Return a large response and confirm the attachment is capped. Return binary data and confirm it is summarized.
Test failure paths as well. Make the downstream call throw, make the output sink fail, and make sanitization reject malformed input. Diagnostics should not replace the original HTTP or assertion exception. If logging itself fails, report that as suppressed context where appropriate and preserve the primary cause.
Also test concurrency. Run several requests with recognizable IDs and ensure each per-test attachment contains only its own events. A thread-local can work with simple synchronous execution, but explicit test-scoped context is safer when execution crosses threads.
Review logs during release exercises. A technically correct filter is insufficient if responders cannot find the correlation ID or distinguish request setup from the returned response. Observability is successful when a failed test leads quickly to a falsifiable cause.
12. REST Assured logging filters best practices
Use a small policy matrix instead of one logging mode for every endpoint. Public health checks may safely emit status and latency. Authentication endpoints should omit bodies and blacklist cookies. File endpoints should report metadata only. Business APIs can allowlist selected identifiers that are synthetic and useful.
| Endpoint class | Default diagnostic content | Exclude |
|---|---|---|
| Health and readiness | Method, path, status, elapsed time | Infrastructure secrets |
| Authentication | Method, path, status, correlation ID | Bodies, authorization, cookies |
| Business JSON | Safe identifiers, status, selected headers | Tokens, personal data, financial data |
| File transfer | Media type, byte count, checksum if approved | Raw binary content |
| Bulk or search | Query shape, result count, truncation note | Full result set and secret query values |
Name the owner of the logging policy. Review it when APIs add headers or body fields, because yesterday's safe payload can contain tomorrow's access token. Keep artifact retention aligned with the sensitivity of the environment. Limit who can rerun tests with verbose diagnostics.
Prefer correlation over content. A clean correlation ID that opens the correct server trace is usually more useful than a megabyte of client output. Keep clocks synchronized in CI and services so request windows align.
Finally, document how a developer enables temporary verbose logging locally without committing it. A system property that selects a safe verbose profile can be useful, provided CI defaults remain restrictive and secrets are still redacted.
Interview Questions and Answers
Q: What is a REST Assured filter?
A filter is around-call middleware for a REST Assured request and response. It can inspect or modify the request, call FilterContext.next, then inspect the returned response. I use filters for cross-cutting transport concerns such as correlation and sanitized diagnostics, not for hidden business workflows.
Q: What is the difference between ifError() and ifValidationFails()?
ifError() is driven by an HTTP error response. ifValidationFails() is driven by a REST Assured expectation that does not match. A negative test can intentionally assert a 400 and pass, while a 200 response can fail because its body is wrong.
Q: Why is RequestLoggingFilter not a wire log?
It prints the request specification at its place in the filter chain. Later filters and the underlying client may add or modify data. I use it for test diagnostics and use controlled transport or server logging when exact transmitted bytes matter.
Q: How do you stop REST Assured logs from leaking bearer tokens?
I blacklist authorization, cookie, API key, and organization-specific secret headers through LogConfig. I keep secrets out of URLs and avoid body logging on sensitive endpoints. CI artifacts also get restricted access and short retention.
Q: How do you order several filters?
I implement OrderedFilter and return documented, spaced precedence values. Lower values run earlier on the request path. I verify the resulting order with a local endpoint because logging, correlation, and authentication can depend on seeing each other's changes.
Q: Why can failure-only logging miss some failures?
It reacts to REST Assured validation failures. If code extracts a response and later fails a JUnit assertion, the conditional REST Assured logger may not run. I keep HTTP expectations in the validation chain or capture sanitized diagnostics in test-scoped state for a JUnit extension.
Q: What should a custom timing filter report?
It should report client-observed elapsed time, method, safe URI, status, and correlation ID. It should use System.nanoTime() for duration and avoid claiming the result is server processing time. It should not turn a noisy CI timing sample into a fragile performance assertion.
Common Mistakes
- Committing
.log().all()on every request and response. - Blacklisting
Authorizationbut exposing refresh tokens or passwords in bodies and query parameters. - Treating a request specification log as proof of exact wire-level headers.
- Adding the same logging behavior in a base spec, client helper, and individual test.
- Forgetting
FilterContext.next, or calling it twice and sending duplicate requests. - Sharing a static output buffer across parallel tests.
- Consuming or replacing the response body in a diagnostic filter.
- Catching an assertion failure for logging and failing to rethrow it.
- Retrying mutation requests inside a generic logging filter.
- Uploading unlimited bodies or binary content as CI attachments.
- Letting a logging exception replace the original API failure.
- Keeping test logs forever without an owner or access policy.
Conclusion
REST Assured logging filters are most valuable when they turn a failed assertion into a short path to the cause. Use conditional logging for everyday tests, redact secrets across headers, URLs, and bodies, and prefer correlation IDs over indiscriminate payload capture. When built-in logging is insufficient, write a small custom filter that calls the chain once, returns the original response, and emits bounded structured evidence.
Start by replacing suite-wide .log().all() calls with failure-only logging and a reviewed blacklist. Then add one correlation filter and verify it against a local endpoint. That gives developers useful diagnostics without turning the test report into a security and maintenance problem.
Interview Questions and Answers
Explain how a custom REST Assured filter executes.
The filter receives filterable request and response specifications plus a `FilterContext`. It may inspect or safely amend the request, then calls `context.next` once. That call returns the response, which the filter can inspect before returning it unchanged.
When would you use a logging filter instead of the fluent log DSL?
I use the fluent DSL when behavior belongs to one test and visibility is useful. I use a filter when correlation, sanitized logging, or report attachment is a suite-wide transport concern. The filter is independently tested and has one clear owner.
How do you secure REST Assured logs in CI?
I log on failure, blacklist credential headers, avoid sensitive bodies and query values, use synthetic test data, and cap attachment size. I also restrict artifact access and retention. Redaction is tested with known marker secrets.
Why might request logging omit a header that the server received?
The logger reports the request specification at its filter position. A later filter or the underlying client may add the header afterward. Filter ordering or server-side traces can explain the difference.
What defect can result from calling FilterContext.next twice?
It can dispatch the request twice. That may duplicate a create, payment, or other side effect and make failures difficult to reproduce. A normal diagnostic filter calls it exactly once and returns that response.
How would you attach REST Assured diagnostics to a failed JUnit test?
I capture sanitized output in a per-test bounded buffer or event model. A JUnit 5 extension publishes it only on failure. I avoid static state so parallel tests cannot mix each other's request data.
How do you validate a logging filter?
I use a local stub endpoint and send recognizable secrets and correlation values. I assert the endpoint receives the real request once, the captured log is redacted, large data is truncated, and logging failures do not replace the primary assertion error.
Frequently Asked Questions
How do I log only failed REST Assured requests?
Use `.log().ifValidationFails()` in the request and response validation chains, or enable request and response failure logging through `LogConfig`. This triggers on REST Assured validation failures and keeps passing test output quiet.
What is RequestLoggingFilter in REST Assured?
`RequestLoggingFilter` is a built-in filter that prints details from the request specification. Its output is diagnostic, not a guaranteed wire capture, because later filters and the HTTP client can still modify the request.
How can I hide an Authorization header in REST Assured logs?
Configure `LogConfig.logConfig().blacklistHeader("Authorization")` and apply it through `RestAssuredConfig`. Add cookies, API key headers, and organization-specific credential headers to the same policy.
Does REST Assured log response bodies on HTTP errors?
It can. Use response logging with `ifError()`, an error logging filter, or a specific status matcher. For test failures caused by a wrong successful response, use `ifValidationFails()` instead.
Can a REST Assured filter change a request?
Yes. A filter receives a `FilterableRequestSpecification` and can add headers or alter other request data before calling the next filter. Diagnostic filters should minimize mutation so they do not change the behavior under test.
How do REST Assured ordered filters work?
Implement `OrderedFilter` and return a precedence from `getOrder()`. Lower values run earlier on the outgoing request path, while response handling unwinds through the nested calls.
Should API test logs be stored as CI artifacts?
Only sanitized, bounded diagnostics should be uploaded. Apply access controls, expiration, and a clear ownership policy because even redacted logs can expose endpoint structure and operational identifiers.
Related Guides
- REST Assured file upload: A Practical Guide (2026)
- REST Assured given when then: A Practical Guide (2026)
- REST Assured JSON schema validation: A Practical Guide (2026)
- REST Assured OAuth2 authentication: A Practical Guide (2026)
- REST Assured POJO serialization: A Practical Guide (2026)
- REST Assured request and response spec: A Practical Guide (2026)