mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-29 01:44:36 -04:00
Make RestController pluggable (#98187)
This commit changes the ActionModules to allow the RestController to be provided by an internal plugin. It renames `RestInterceptorActionPlugin` to `RestServerActionPlugin` and adds a new `getRestController` method to it. There may be multiple RestServerActionPlugins installed on a node, but only 1 may provide a Rest Wrapper (getRestHandlerInterceptor) and only 1 may provide a RestController (getRestController).
This commit is contained in:
parent
2aca985e29
commit
3093c40b8b
12 changed files with 341 additions and 42 deletions
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
package co.elastic.elasticsearch.test;
|
||||
|
||||
import org.elasticsearch.client.internal.node.NodeClient;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.indices.breaker.CircuitBreakerService;
|
||||
import org.elasticsearch.logging.LogManager;
|
||||
import org.elasticsearch.logging.Logger;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.plugins.interceptor.RestServerActionPlugin;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.tracing.Tracer;
|
||||
import org.elasticsearch.usage.UsageService;
|
||||
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class CustomRestPlugin extends Plugin implements RestServerActionPlugin {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(CustomRestPlugin.class);
|
||||
|
||||
private static void echoHeader(String name, RestRequest request, ThreadContext threadContext) {
|
||||
var value = request.header(name);
|
||||
if (value != null) {
|
||||
threadContext.addResponseHeader(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomInterceptor implements RestHandler {
|
||||
|
||||
private final ThreadContext threadContext;
|
||||
private final RestHandler delegate;
|
||||
|
||||
public CustomInterceptor(ThreadContext threadContext, RestHandler delegate) {
|
||||
this.threadContext = threadContext;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
|
||||
logger.info("intercept request {} {}", request.method(), request.uri());
|
||||
echoHeader("x-test-interceptor", request, threadContext);
|
||||
delegate.handleRequest(request, channel, client);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class CustomController extends RestController {
|
||||
public CustomController(
|
||||
UnaryOperator<RestHandler> handlerWrapper,
|
||||
NodeClient client,
|
||||
CircuitBreakerService circuitBreakerService,
|
||||
UsageService usageService,
|
||||
Tracer tracer
|
||||
) {
|
||||
super(handlerWrapper, client, circuitBreakerService, usageService, tracer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchRequest(RestRequest request, RestChannel channel, ThreadContext threadContext) {
|
||||
logger.info("dispatch request {} {}", request.method(), request.uri());
|
||||
echoHeader("x-test-controller", request, threadContext);
|
||||
super.dispatchRequest(request, channel, threadContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext) {
|
||||
return handler -> new CustomInterceptor(threadContext, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestController getRestController(
|
||||
UnaryOperator<RestHandler> handlerWrapper,
|
||||
NodeClient client,
|
||||
CircuitBreakerService circuitBreakerService,
|
||||
UsageService usageService,
|
||||
Tracer tracer
|
||||
) {
|
||||
return new CustomController(handlerWrapper, client, circuitBreakerService, usageService, tracer);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.plugins.interceptor;
|
||||
|
||||
import co.elastic.elasticsearch.test.CustomRestPlugin;
|
||||
|
||||
import org.elasticsearch.client.Request;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.elasticsearch.common.util.CollectionUtils.appendToCopyNoNullElements;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
||||
public class CustomRestPluginIT extends ESIntegTestCase {
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return appendToCopyNoNullElements(super.nodePlugins(), CustomRestPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addMockHttpTransport() {
|
||||
return false; // enable http
|
||||
}
|
||||
|
||||
public void testInterceptor() throws Exception {
|
||||
var headerValue = randomAlphaOfLengthBetween(4, 12);
|
||||
assertThat(doRequest("x-test-interceptor", headerValue), equalTo(headerValue));
|
||||
assertThat(doRequest("x-test-interceptor", null), equalTo(null));
|
||||
}
|
||||
|
||||
public void testController() throws Exception {
|
||||
var headerValue = randomAlphaOfLengthBetween(4, 12);
|
||||
assertThat(doRequest("x-test-controller", headerValue), equalTo(headerValue));
|
||||
assertThat(doRequest("x-test-controller", null), equalTo(null));
|
||||
}
|
||||
|
||||
private String doRequest(String headerName, String headerValue) throws IOException {
|
||||
assertThat(headerName, notNullValue());
|
||||
|
||||
var client = getRestClient();
|
||||
RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder();
|
||||
if (headerValue != null) {
|
||||
options.addHeader(headerName, headerValue);
|
||||
}
|
||||
var request = new Request("GET", "/_nodes/_local/plugins");
|
||||
request.setOptions(options);
|
||||
|
||||
final Response response = client.performRequest(request);
|
||||
return response.getHeader(headerName);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue