From 37bc0e83e30d8abf524f1ebd186e60c1c6ed51f7 Mon Sep 17 00:00:00 2001 From: Yuqi Du Date: Tue, 23 Jul 2024 16:41:17 -0700 Subject: [PATCH 1/2] init --- .../api/request/token/TokenFilter.java | 32 ------------------- .../sgv2/jsonapi/exception/ErrorCode.java | 2 ++ .../mappers/ThrowableToErrorMapper.java | 12 +++++++ .../WebApplicationExceptionMapper.java | 7 ++++ .../api/v1/HttpStatusCodeIntegrationTest.java | 21 ++++++++++++ 5 files changed, 42 insertions(+), 32 deletions(-) delete mode 100644 src/main/java/io/stargate/sgv2/jsonapi/api/request/token/TokenFilter.java diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/request/token/TokenFilter.java b/src/main/java/io/stargate/sgv2/jsonapi/api/request/token/TokenFilter.java deleted file mode 100644 index f32d1848f6..0000000000 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/request/token/TokenFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.stargate.sgv2.jsonapi.api.request.token; - -import static io.stargate.sgv2.jsonapi.config.constants.HttpConstants.DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME; - -import io.quarkus.vertx.http.runtime.filters.Filters; -import io.vertx.core.MultiMap; -import jakarta.enterprise.context.RequestScoped; -import jakarta.enterprise.event.Observes; - -/** - * Request based, filtering out authentication token and add correct header Coordinator needs - * X-Cassandra-Token as token name JSON API requires Token as token name Also supports - * X-Cassandra-Token for backward compatibility - */ -@RequestScoped -public class TokenFilter { - - // JSON API token name "Token", also supports X-Cassandra-Token for backward compatibility - public void registerMyFilter(@Observes Filters filters) { - filters.register( - rc -> { - MultiMap headers = rc.request().headers(); - if (headers.contains("Token")) { - headers.add(DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME, headers.get("Token")); - } else if (headers.contains("token")) { - headers.add(DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME, headers.get("token")); - } - rc.next(); - }, - 10000); - } -} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java index ed1ba17fc8..7b52d29b42 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java @@ -105,6 +105,8 @@ public enum ErrorCode { INVALID_USAGE_OF_VECTORIZE("`$vectorize` and `$vector` can't be used together"), + INVALID_CONTENT_TYPE_HEADER("Invalid Content-Type header"), + UNSUPPORTED_PROJECTION_PARAM("Unsupported projection parameter"), UNSUPPORTED_UPDATE_DATA_TYPE("Unsupported update data type"), diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java index b11ed23801..2358cbf575 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java @@ -15,6 +15,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.exception.JsonApiException; +import jakarta.ws.rs.NotSupportedException; import jakarta.ws.rs.core.Response; import java.util.Collection; import java.util.Collections; @@ -69,6 +70,17 @@ public final class ThrowableToErrorMapper { return handleDriverException((DriverException) throwable, message); } + // handle an invalid Content-Type header + if (throwable instanceof NotSupportedException + && throwable + .getMessage() + .contains("The content-type header value did not match the value")) { + // validate the Content-Type header, 415 if failed + return ErrorCode.INVALID_CONTENT_TYPE_HEADER + .toApiException() + .getCommandResultError(Response.Status.UNSUPPORTED_MEDIA_TYPE); + } + // handle all other exceptions return handleUnrecognizedException(throwable, message); }; diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java index 08e77fbbd5..6f95818292 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java @@ -6,6 +6,7 @@ import io.stargate.sgv2.jsonapi.exception.JsonApiException; import jakarta.ws.rs.NotAllowedException; import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.NotSupportedException; import jakarta.ws.rs.WebApplicationException; import org.jboss.resteasy.reactive.RestResponse; import org.jboss.resteasy.reactive.server.ServerExceptionMapper; @@ -42,6 +43,12 @@ public RestResponse webApplicationExceptionMapper(WebApplicationE if (e instanceof NotFoundException) { return RestResponse.status(RestResponse.Status.NOT_FOUND, commandResult); } + // Return 415 for invalid Content-Type + if (e instanceof NotSupportedException + && e.getMessage().contains("The content-type header value did not match the value")) { + return RestResponse.status(RestResponse.Status.UNSUPPORTED_MEDIA_TYPE, commandResult); + } + return RestResponse.ok(commandResult); } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java index 91411795d2..3c62ca53c7 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java @@ -102,6 +102,27 @@ public void regularError() { .body("errors[0].exceptionClass", is("JsonApiException")); } + @Test + public void invalidContentType() { + given() + .headers(getHeaders()) + .contentType(ContentType.HTML) + .body( + """ + { + "findCollections": { } + } + """) + .when() + .post(NamespaceResource.BASE_PATH, namespaceName) + .then() + .statusCode(415) + .body("errors", is(notNullValue())) + .body("errors[0].message", is("Invalid Content-Type header")) + .body("errors[0].errorCode", is("INVALID_CONTENT_TYPE_HEADER")) + .body("errors[0].exceptionClass", is("JsonApiException")); + } + @Test public void resourceNotFound() { String json = From d5ad1680b751c4be6473241b70f5ad434ce63053 Mon Sep 17 00:00:00 2001 From: Yuqi Du Date: Wed, 24 Jul 2024 08:36:26 -0700 Subject: [PATCH 2/2] fix comments --- .../jsonapi/exception/mappers/ThrowableToErrorMapper.java | 5 +---- .../exception/mappers/WebApplicationExceptionMapper.java | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java index 2358cbf575..b5f8db4995 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java @@ -71,10 +71,7 @@ public final class ThrowableToErrorMapper { } // handle an invalid Content-Type header - if (throwable instanceof NotSupportedException - && throwable - .getMessage() - .contains("The content-type header value did not match the value")) { + if (throwable instanceof NotSupportedException) { // validate the Content-Type header, 415 if failed return ErrorCode.INVALID_CONTENT_TYPE_HEADER .toApiException() diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java index 6f95818292..b4f9d9f60c 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/WebApplicationExceptionMapper.java @@ -44,8 +44,7 @@ public RestResponse webApplicationExceptionMapper(WebApplicationE return RestResponse.status(RestResponse.Status.NOT_FOUND, commandResult); } // Return 415 for invalid Content-Type - if (e instanceof NotSupportedException - && e.getMessage().contains("The content-type header value did not match the value")) { + if (e instanceof NotSupportedException) { return RestResponse.status(RestResponse.Status.UNSUPPORTED_MEDIA_TYPE, commandResult); }