|
@@ -32,7 +32,6 @@ import org.elasticsearch.http.HttpStats;
|
|
|
import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService;
|
|
|
import org.elasticsearch.rest.RestHandler.Route;
|
|
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
|
|
-import org.elasticsearch.tasks.Task;
|
|
|
import org.elasticsearch.test.ESTestCase;
|
|
|
import org.elasticsearch.test.client.NoOpNodeClient;
|
|
|
import org.elasticsearch.test.rest.FakeRestRequest;
|
|
@@ -60,13 +59,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
|
import static org.elasticsearch.rest.RestController.ELASTIC_INTERNAL_ORIGIN_HTTP_HEADER;
|
|
|
+import static org.elasticsearch.rest.RestController.ELASTIC_PRODUCT_HTTP_HEADER;
|
|
|
+import static org.elasticsearch.rest.RestController.ELASTIC_PRODUCT_HTTP_HEADER_VALUE;
|
|
|
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
|
|
import static org.elasticsearch.rest.RestRequest.Method.OPTIONS;
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.hasItem;
|
|
|
import static org.hamcrest.Matchers.is;
|
|
|
-import static org.hamcrest.Matchers.nullValue;
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
import static org.mockito.ArgumentMatchers.anyMap;
|
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
@@ -105,7 +105,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
HttpServerTransport httpServerTransport = new TestHttpServerTransport();
|
|
|
client = new NoOpNodeClient(this.getTestName());
|
|
|
tracer = mock(Tracer.class);
|
|
|
- restController = new RestController(Collections.emptySet(), null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
+ restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
restController.registerHandler(
|
|
|
new Route(GET, "/"),
|
|
|
(request, channel, client) -> channel.sendResponse(
|
|
@@ -124,30 +124,17 @@ public class RestControllerTests extends ESTestCase {
|
|
|
IOUtils.close(client);
|
|
|
}
|
|
|
|
|
|
- public void testApplyRelevantHeaders() throws Exception {
|
|
|
+ public void testApplyProductSpecificResponseHeaders() {
|
|
|
final ThreadContext threadContext = client.threadPool().getThreadContext();
|
|
|
- Set<RestHeaderDefinition> headers = new HashSet<>(
|
|
|
- Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", true))
|
|
|
- );
|
|
|
- final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
- Map<String, List<String>> restHeaders = new HashMap<>();
|
|
|
- restHeaders.put("header.1", Collections.singletonList("true"));
|
|
|
- restHeaders.put("header.2", Collections.singletonList("true"));
|
|
|
- restHeaders.put("header.3", Collections.singletonList("false"));
|
|
|
- RestRequest fakeRequest = new FakeRestRequest.Builder(xContentRegistry()).withHeaders(restHeaders).build();
|
|
|
+ final RestController restController = new RestController(null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
+ RestRequest fakeRequest = new FakeRestRequest.Builder(xContentRegistry()).build();
|
|
|
AssertingChannel channel = new AssertingChannel(fakeRequest, false, RestStatus.BAD_REQUEST);
|
|
|
restController.dispatchRequest(fakeRequest, channel, threadContext);
|
|
|
// the rest controller relies on the caller to stash the context, so we should expect these values here as we didn't stash the
|
|
|
// context in this test
|
|
|
- assertEquals("true", threadContext.getHeader("header.1"));
|
|
|
- assertEquals("true", threadContext.getHeader("header.2"));
|
|
|
- assertNull(threadContext.getHeader("header.3"));
|
|
|
List<String> expectedProductResponseHeader = new ArrayList<>();
|
|
|
- expectedProductResponseHeader.add(RestController.ELASTIC_PRODUCT_HTTP_HEADER_VALUE);
|
|
|
- assertEquals(
|
|
|
- expectedProductResponseHeader,
|
|
|
- threadContext.getResponseHeaders().getOrDefault(RestController.ELASTIC_PRODUCT_HTTP_HEADER, null)
|
|
|
- );
|
|
|
+ expectedProductResponseHeader.add(ELASTIC_PRODUCT_HTTP_HEADER_VALUE);
|
|
|
+ assertEquals(expectedProductResponseHeader, threadContext.getResponseHeaders().getOrDefault(ELASTIC_PRODUCT_HTTP_HEADER, null));
|
|
|
}
|
|
|
|
|
|
public void testRequestWithDisallowedMultiValuedHeader() {
|
|
@@ -155,7 +142,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
Set<RestHeaderDefinition> headers = new HashSet<>(
|
|
|
Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", false))
|
|
|
);
|
|
|
- final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
+ final RestController restController = new RestController(null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
Map<String, List<String>> restHeaders = new HashMap<>();
|
|
|
restHeaders.put("header.1", Collections.singletonList("boo"));
|
|
|
restHeaders.put("header.2", List.of("foo", "bar"));
|
|
@@ -170,7 +157,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
*/
|
|
|
public void testDispatchStartsTrace() {
|
|
|
final ThreadContext threadContext = client.threadPool().getThreadContext();
|
|
|
- final RestController restController = new RestController(Set.of(), null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
+ final RestController restController = new RestController(null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
RestRequest fakeRequest = new FakeRestRequest.Builder(xContentRegistry()).build();
|
|
|
final RestController spyRestController = spy(restController);
|
|
|
when(spyRestController.getAllHandlers(null, fakeRequest.rawPath())).thenReturn(new Iterator<>() {
|
|
@@ -194,35 +181,12 @@ public class RestControllerTests extends ESTestCase {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Check that the REST controller picks up and propagates W3C trace context headers via the {@link ThreadContext}.
|
|
|
- * @see <a href="https://www.w3.org/TR/trace-context/">Trace Context - W3C Recommendation</a>
|
|
|
- */
|
|
|
- public void testTraceParentAndTraceId() {
|
|
|
- final ThreadContext threadContext = client.threadPool().getThreadContext();
|
|
|
- Set<RestHeaderDefinition> headers = Set.of(new RestHeaderDefinition(Task.TRACE_PARENT_HTTP_HEADER, false));
|
|
|
- final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
- Map<String, List<String>> restHeaders = new HashMap<>();
|
|
|
- final String traceParentValue = "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01";
|
|
|
- restHeaders.put(Task.TRACE_PARENT_HTTP_HEADER, Collections.singletonList(traceParentValue));
|
|
|
- RestRequest fakeRequest = new FakeRestRequest.Builder(xContentRegistry()).withHeaders(restHeaders).build();
|
|
|
- AssertingChannel channel = new AssertingChannel(fakeRequest, false, RestStatus.BAD_REQUEST);
|
|
|
-
|
|
|
- restController.dispatchRequest(fakeRequest, channel, threadContext);
|
|
|
-
|
|
|
- // the rest controller relies on the caller to stash the context, so we should expect these values here as we didn't stash the
|
|
|
- // context in this test
|
|
|
- assertThat(threadContext.getHeader(Task.TRACE_ID), equalTo("0af7651916cd43dd8448eb211c80319c"));
|
|
|
- assertThat(threadContext.getHeader(Task.TRACE_PARENT_HTTP_HEADER), nullValue());
|
|
|
- assertThat(threadContext.getTransient("parent_" + Task.TRACE_PARENT_HTTP_HEADER), equalTo(traceParentValue));
|
|
|
- }
|
|
|
-
|
|
|
public void testRequestWithDisallowedMultiValuedHeaderButSameValues() {
|
|
|
final ThreadContext threadContext = client.threadPool().getThreadContext();
|
|
|
Set<RestHeaderDefinition> headers = new HashSet<>(
|
|
|
Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", false))
|
|
|
);
|
|
|
- final RestController restController = new RestController(headers, null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
+ final RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
Map<String, List<String>> restHeaders = new HashMap<>();
|
|
|
restHeaders.put("header.1", Collections.singletonList("boo"));
|
|
|
restHeaders.put("header.2", List.of("foo", "foo"));
|
|
@@ -293,7 +257,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testRegisterSecondMethodWithDifferentNamedWildcard() {
|
|
|
- final RestController restController = new RestController(null, null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
+ final RestController restController = new RestController(null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
RestRequest.Method firstMethod = randomFrom(RestRequest.Method.values());
|
|
|
RestRequest.Method secondMethod = randomFrom(Arrays.stream(RestRequest.Method.values()).filter(m -> m != firstMethod).toList());
|
|
@@ -317,7 +281,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
AtomicBoolean wrapperCalled = new AtomicBoolean(false);
|
|
|
final RestHandler handler = (RestRequest request, RestChannel channel, NodeClient client) -> handlerCalled.set(true);
|
|
|
final HttpServerTransport httpServerTransport = new TestHttpServerTransport();
|
|
|
- final RestController restController = new RestController(Collections.emptySet(), h -> {
|
|
|
+ final RestController restController = new RestController(h -> {
|
|
|
assertSame(handler, h);
|
|
|
return (RestRequest request, RestChannel channel, NodeClient client) -> wrapperCalled.set(true);
|
|
|
}, client, circuitBreakerService, usageService, tracer, false);
|
|
@@ -407,7 +371,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead()));
|
|
|
RestRequest request = testRestRequest("/", content, null);
|
|
|
AssertingChannel channel = new AssertingChannel(request, true, RestStatus.NOT_ACCEPTABLE);
|
|
|
- restController = new RestController(Collections.emptySet(), null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
+ restController = new RestController(null, null, circuitBreakerService, usageService, tracer, false);
|
|
|
restController.registerHandler(
|
|
|
new Route(GET, "/"),
|
|
|
(r, c, client) -> c.sendResponse(new RestResponse(RestStatus.OK, RestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY))
|
|
@@ -774,15 +738,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
|
|
|
public void testDispatchCompatibleHandler() {
|
|
|
|
|
|
- RestController restController = new RestController(
|
|
|
- Collections.emptySet(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
final RestApiVersion version = RestApiVersion.minimumSupported();
|
|
|
|
|
@@ -806,15 +762,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
|
|
|
public void testDispatchCompatibleRequestToNewlyAddedHandler() {
|
|
|
|
|
|
- RestController restController = new RestController(
|
|
|
- Collections.emptySet(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
final RestApiVersion version = RestApiVersion.minimumSupported();
|
|
|
|
|
@@ -849,15 +797,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testCurrentVersionVNDMediaTypeIsNotUsingCompatibility() {
|
|
|
- RestController restController = new RestController(
|
|
|
- Collections.emptySet(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
final RestApiVersion version = RestApiVersion.current();
|
|
|
|
|
@@ -882,15 +822,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testCustomMediaTypeValidation() {
|
|
|
- RestController restController = new RestController(
|
|
|
- Collections.emptySet(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
final String mediaType = "application/x-protobuf";
|
|
|
FakeRestRequest fakeRestRequest = requestWithContent(mediaType);
|
|
@@ -916,15 +848,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testBrowserSafelistedContentTypesAreRejected() {
|
|
|
- RestController restController = new RestController(
|
|
|
- Collections.emptySet(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
|
|
|
final String mediaType = randomFrom(RestController.SAFELISTED_MEDIA_TYPES);
|
|
|
FakeRestRequest fakeRestRequest = requestWithContent(mediaType);
|
|
@@ -945,15 +869,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testRegisterWithReservedPath() {
|
|
|
- final RestController restController = new RestController(
|
|
|
- Set.of(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- usageService,
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ final RestController restController = new RestController(null, client, circuitBreakerService, usageService, tracer, false);
|
|
|
for (String path : RestController.RESERVED_PATHS) {
|
|
|
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> {
|
|
|
restController.registerHandler(
|
|
@@ -971,15 +887,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
* Test that when serverless is disabled, all endpoints are available regardless of ServerlessScope annotations.
|
|
|
*/
|
|
|
public void testApiProtectionWithServerlessDisabled() {
|
|
|
- final RestController restController = new RestController(
|
|
|
- Set.of(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- new UsageService(),
|
|
|
- tracer,
|
|
|
- false
|
|
|
- );
|
|
|
+ final RestController restController = new RestController(null, client, circuitBreakerService, new UsageService(), tracer, false);
|
|
|
restController.registerHandler(new PublicRestHandler());
|
|
|
restController.registerHandler(new InternalRestHandler());
|
|
|
restController.registerHandler(new HiddenRestHandler());
|
|
@@ -996,15 +904,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
* annotated with a PUBLIC scope.
|
|
|
*/
|
|
|
public void testApiProtectionWithServerlessEnabledAsEndUser() {
|
|
|
- final RestController restController = new RestController(
|
|
|
- Set.of(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- new UsageService(),
|
|
|
- tracer,
|
|
|
- true
|
|
|
- );
|
|
|
+ final RestController restController = new RestController(null, client, circuitBreakerService, new UsageService(), tracer, true);
|
|
|
restController.registerHandler(new PublicRestHandler());
|
|
|
restController.registerHandler(new InternalRestHandler());
|
|
|
restController.registerHandler(new HiddenRestHandler());
|
|
@@ -1027,15 +927,7 @@ public class RestControllerTests extends ESTestCase {
|
|
|
* annotated with a PUBLIC or INTERNAL scope.
|
|
|
*/
|
|
|
public void testApiProtectionWithServerlessEnabledAsInternalUser() {
|
|
|
- final RestController restController = new RestController(
|
|
|
- Set.of(),
|
|
|
- null,
|
|
|
- client,
|
|
|
- circuitBreakerService,
|
|
|
- new UsageService(),
|
|
|
- tracer,
|
|
|
- true
|
|
|
- );
|
|
|
+ final RestController restController = new RestController(null, client, circuitBreakerService, new UsageService(), tracer, true);
|
|
|
restController.registerHandler(new PublicRestHandler());
|
|
|
restController.registerHandler(new InternalRestHandler());
|
|
|
restController.registerHandler(new HiddenRestHandler());
|