Disable Quarkus endpoints with a request filter
I needed a simple way to disable all endpoints in a Quarkus application based on a configuration property. A request filter was the right tool for the job, but some care had to be taken to not also disable the Dev UI.
A server request filter is a method annotated with @ServerRequestFilter. To access a configuration property, inject it into is parent class:
public class Filters {
@ConfigProperty(name="features.endpoints-enabled")
boolean featureEndpointsEnabled;
@ServerRequestFilter
public RestResponse<?> featureFlagFilter(ContainerRequestContext requestContext) {
if (!featureEndpointsEnabled &&
!requestContext.getUriInfo().getPath().startsWith("/q/")) {
return RestResponse.ResponseBuilder.notFound().build();
}
return null;
}
}
When the method returns null, the processing will proceed, making the endpoint accessible. When the method returns a RestResponse, the processing stops and that response will be returned to the caller.
If you still want the Dev UI to work when you disable the endpoints, you need to check the requested path, and not block requests to paths which start with /q/.
To test the filter, you would need to change the value of a configuration property for the particular test. One way to do this is by using Quarkus test profiles. The test method must be placed in a separate test class which also acts as a test profile:
@QuarkusTest
@TestProfile(DisabledExampleResourceTest.class)
public class DisabledExampleResourceTest implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return Map.of(
"features.endpoints-enabled", "false"
);
}
@Test
void testHelloEndpointDisabled() {
given()
.when().get("/hello")
.then()
.statusCode(404)
.body(is(""));
}
}
The getConfigOverrides method returns the key-value pairs of configuration properties to override.
You can find a sample project in my GitHub repository. It adds the filter to a new Quarkus project with a sample endpoint, and a test that validates its behavior.
Although request filters aren't all the flexible, they are a great fit for a functionality that affects all or many endpoints in the application.
