Skip to content

Commit bef0068

Browse files
authored
Introduce FilterRestHandler (#98861) (#98920)
RestHandler has a number of methods that affect the behaviour of request processing. If the handler is wrapped (e.g. SecurityRestFilter or DeprecationRestHandler) then these methods must be delegated to the underlying handler. This commit introduces a new abstract base class `FilterRestHandler` that correctly delegates these methods so that wrappers (subclasses) do not need to implement the behaviour on a case-by-case basis
1 parent 415ff6a commit bef0068

File tree

3 files changed

+71
-57
lines changed

3 files changed

+71
-57
lines changed

server/src/main/java/org/elasticsearch/rest/DeprecationRestHandler.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
* {@code DeprecationRestHandler} provides a proxy for any existing {@link RestHandler} so that usage of the handler can be
2121
* logged using the {@link DeprecationLogger}.
2222
*/
23-
public class DeprecationRestHandler implements RestHandler {
23+
public class DeprecationRestHandler extends FilterRestHandler implements RestHandler {
2424

2525
public static final String DEPRECATED_ROUTE_KEY = "deprecated_route";
26-
private final RestHandler handler;
26+
2727
private final String deprecationMessage;
2828
private final DeprecationLogger deprecationLogger;
2929
private final boolean compatibleVersionWarning;
@@ -55,7 +55,7 @@ public DeprecationRestHandler(
5555
DeprecationLogger deprecationLogger,
5656
boolean compatibleVersionWarning
5757
) {
58-
this.handler = Objects.requireNonNull(handler);
58+
super(handler);
5959
this.deprecationMessage = requireValidHeader(deprecationMessage);
6060
this.deprecationLogger = Objects.requireNonNull(deprecationLogger);
6161
this.compatibleVersionWarning = compatibleVersionWarning;
@@ -92,17 +92,7 @@ public void handleRequest(RestRequest request, RestChannel channel, NodeClient c
9292
}
9393
}
9494

95-
handler.handleRequest(request, channel, client);
96-
}
97-
98-
@Override
99-
public RestHandler getConcreteRestHandler() {
100-
return handler.getConcreteRestHandler();
101-
}
102-
103-
@Override
104-
public boolean supportsContentStream() {
105-
return handler.supportsContentStream();
95+
getDelegate().handleRequest(request, channel, client);
10696
}
10797

10898
/**
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.rest;
10+
11+
import java.util.List;
12+
import java.util.Objects;
13+
14+
public abstract class FilterRestHandler implements RestHandler {
15+
private final RestHandler delegate;
16+
17+
protected FilterRestHandler(RestHandler delegate) {
18+
this.delegate = Objects.requireNonNull(delegate);
19+
}
20+
21+
protected RestHandler getDelegate() {
22+
return delegate;
23+
}
24+
25+
@Override
26+
public RestHandler getConcreteRestHandler() {
27+
return delegate.getConcreteRestHandler();
28+
}
29+
30+
@Override
31+
public List<RestHandler.Route> routes() {
32+
return delegate.routes();
33+
}
34+
35+
@Override
36+
public boolean allowSystemIndexAccessByDefault() {
37+
return delegate.allowSystemIndexAccessByDefault();
38+
}
39+
40+
@Override
41+
public boolean canTripCircuitBreaker() {
42+
return delegate.canTripCircuitBreaker();
43+
}
44+
45+
@Override
46+
public boolean allowsUnsafeBuffers() {
47+
return delegate.allowsUnsafeBuffers();
48+
}
49+
50+
@Override
51+
public boolean supportsContentStream() {
52+
return delegate.supportsContentStream();
53+
}
54+
55+
@Override
56+
public boolean mediaTypesValid(RestRequest request) {
57+
return delegate.mediaTypesValid(request);
58+
}
59+
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/SecurityRestFilter.java

Lines changed: 8 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.action.ActionListener;
1414
import org.elasticsearch.client.internal.node.NodeClient;
1515
import org.elasticsearch.common.util.concurrent.ThreadContext;
16+
import org.elasticsearch.rest.FilterRestHandler;
1617
import org.elasticsearch.rest.RestChannel;
1718
import org.elasticsearch.rest.RestHandler;
1819
import org.elasticsearch.rest.RestRequest;
@@ -24,15 +25,12 @@
2425
import org.elasticsearch.xpack.security.authz.restriction.WorkflowService;
2526
import org.elasticsearch.xpack.security.operator.OperatorPrivileges;
2627

27-
import java.util.List;
28-
2928
import static org.elasticsearch.core.Strings.format;
3029

31-
public class SecurityRestFilter implements RestHandler {
30+
public class SecurityRestFilter extends FilterRestHandler implements RestHandler {
3231

3332
private static final Logger logger = LogManager.getLogger(SecurityRestFilter.class);
3433

35-
private final RestHandler restHandler;
3634
private final SecondaryAuthenticator secondaryAuthenticator;
3735
private final AuditTrailService auditTrailService;
3836
private final boolean enabled;
@@ -49,27 +47,18 @@ public SecurityRestFilter(
4947
RestHandler restHandler,
5048
OperatorPrivileges.OperatorPrivilegesService operatorPrivilegesService
5149
) {
50+
super(restHandler);
5251
this.enabled = enabled;
5352
this.threadContext = threadContext;
5453
this.secondaryAuthenticator = secondaryAuthenticator;
5554
this.auditTrailService = auditTrailService;
5655
this.workflowService = workflowService;
57-
this.restHandler = restHandler;
5856
// can be null if security is not enabled
5957
this.operatorPrivilegesService = operatorPrivilegesService == null
6058
? OperatorPrivileges.NOOP_OPERATOR_PRIVILEGES_SERVICE
6159
: operatorPrivilegesService;
6260
}
6361

64-
@Override
65-
public boolean allowSystemIndexAccessByDefault() {
66-
return restHandler.allowSystemIndexAccessByDefault();
67-
}
68-
69-
public RestHandler getConcreteRestHandler() {
70-
return restHandler.getConcreteRestHandler();
71-
}
72-
7362
@Override
7463
public void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
7564
// requests with the OPTIONS method should be handled elsewhere, and not by calling {@code RestHandler#handleRequest}
@@ -94,17 +83,17 @@ public void handleRequest(RestRequest request, RestChannel channel, NodeClient c
9483
if (secondaryAuthentication != null) {
9584
logger.trace("Found secondary authentication {} in REST request [{}]", secondaryAuthentication, request.uri());
9685
}
97-
workflowService.resolveWorkflowAndStoreInThreadContext(restHandler, threadContext);
86+
workflowService.resolveWorkflowAndStoreInThreadContext(getConcreteRestHandler(), threadContext);
9887
doHandleRequest(request, channel, client);
9988
}, e -> handleException(request, channel, e)));
10089
}
10190

10291
private void doHandleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
10392
threadContext.sanitizeHeaders();
10493
// operator privileges can short circuit to return a non-successful response
105-
if (operatorPrivilegesService.checkRest(restHandler, request, channel, threadContext)) {
94+
if (operatorPrivilegesService.checkRest(getConcreteRestHandler(), request, channel, threadContext)) {
10695
try {
107-
restHandler.handleRequest(request, channel, client);
96+
getDelegate().handleRequest(request, channel, client);
10897
} catch (Exception e) {
10998
logger.debug(() -> format("Request handling failed for REST request [%s]", request.uri()), e);
11099
throw e;
@@ -123,40 +112,16 @@ protected void handleException(RestRequest request, RestChannel channel, Excepti
123112
}
124113
}
125114

126-
@Override
127-
public boolean canTripCircuitBreaker() {
128-
return restHandler.canTripCircuitBreaker();
129-
}
130-
131-
@Override
132-
public boolean supportsContentStream() {
133-
return restHandler.supportsContentStream();
134-
}
135-
136-
@Override
137-
public boolean allowsUnsafeBuffers() {
138-
return restHandler.allowsUnsafeBuffers();
139-
}
140-
141-
@Override
142-
public List<Route> routes() {
143-
return restHandler.routes();
144-
}
145-
146115
// for testing
147116
OperatorPrivileges.OperatorPrivilegesService getOperatorPrivilegesService() {
148117
return operatorPrivilegesService;
149118
}
150119

151120
private RestRequest maybeWrapRestRequest(RestRequest restRequest) {
152-
if (restHandler instanceof RestRequestFilter) {
153-
return ((RestRequestFilter) restHandler).getFilteredRequest(restRequest);
121+
if (getConcreteRestHandler() instanceof RestRequestFilter rrf) {
122+
return rrf.getFilteredRequest(restRequest);
154123
}
155124
return restRequest;
156125
}
157126

158-
@Override
159-
public boolean mediaTypesValid(RestRequest request) {
160-
return restHandler.mediaTypesValid(request);
161-
}
162127
}

0 commit comments

Comments
 (0)