diff --git a/src/main/java/io/neonbee/endpoint/raw/RawEndpoint.java b/src/main/java/io/neonbee/endpoint/raw/RawEndpoint.java index 9771f552..ea6bb4f0 100644 --- a/src/main/java/io/neonbee/endpoint/raw/RawEndpoint.java +++ b/src/main/java/io/neonbee/endpoint/raw/RawEndpoint.java @@ -86,6 +86,8 @@ public Future createEndpointRouter(Vertx vertx, String basePath, JsonObj @VisibleForTesting static class RawHandler implements Handler { + private static final String CONTENT_TYPE = "Content-Type"; + private final boolean exposeHiddenVerticles; private final RegexBlockList exposedVerticles; @@ -175,10 +177,11 @@ queryParameterMap, multiMapToMap(request.headers()), routingContext.body().buffe return; } - HttpServerResponse response = routingContext.response() - .putHeader("Content-Type", - Optional.ofNullable(context.responseData().get("Content-Type")) - .map(String.class::cast).orElse("application/json")); + HttpServerResponse response = routingContext.response(); + response.putHeader(CONTENT_TYPE, + Optional.ofNullable(context.responseData().get(CONTENT_TYPE)) + .map(String.class::cast).orElse("application/json")); + if (result instanceof JsonObject) { result = ((JsonObject) result).toBuffer(); } else if (result instanceof JsonArray) { @@ -189,9 +192,11 @@ queryParameterMap, multiMapToMap(request.headers()), routingContext.body().buffe // application/json. result = Json.encodeToBuffer(asyncResult.result()); } else { - // fallback to text/plain, so that the browser tries to display it, instead of downloading - // it - response.putHeader("Content-Type", "text/plain"); + // fallback to text/plain if the Content-Type isn't set, so that the browser tries to + // display it, instead of downloading it + response.putHeader(CONTENT_TYPE, + Optional.ofNullable(context.responseData().get(CONTENT_TYPE)) + .map(String.class::cast).orElse("text/plain")); } response.end((Buffer) result); diff --git a/src/test/java/io/neonbee/endpoint/raw/RawEndpointTest.java b/src/test/java/io/neonbee/endpoint/raw/RawEndpointTest.java index d5f68c02..cb2e3f77 100644 --- a/src/test/java/io/neonbee/endpoint/raw/RawEndpointTest.java +++ b/src/test/java/io/neonbee/endpoint/raw/RawEndpointTest.java @@ -38,6 +38,9 @@ import io.vertx.junit5.VertxTestContext; class RawEndpointTest extends DataVerticleTestBase { + + public static final String CONTENT_TYPE = "Content-Type"; + private static RoutingContext mockRoutingContext(String routingPath) { RoutingContext routingContextMock = mock(RoutingContext.class); Route routeMock = mock(Route.class); @@ -134,24 +137,31 @@ void testPassQueryToDataQuery(VertxTestContext testContext) { .onComplete(testContext.succeedingThenComplete()); } - @Test + static Stream testSettingContentTypeParameter() { + return Stream.of( + Arguments.of(new JsonResponseVerticle()), + Arguments.of(new BufferResponseVerticle())); + } + + @ParameterizedTest(name = "{index}: with verticle name {0}./") + @MethodSource("testSettingContentTypeParameter") @DisplayName("RawDataEndpointHandler must set the Content-Type header correct") - void test(VertxTestContext testContext) { - deployVerticle(new RawResponseVerticle()) + void testSettingContentType(DataVerticle dataVerticle, VertxTestContext testContext) { + deployVerticle(dataVerticle) .compose(s -> sendRequest("Test", "", "")) .onComplete(testContext.succeeding(resp -> testContext.verify(() -> { - assertThat(resp.getHeader("Content-Type")).isEqualTo("image/gif"); + assertThat(resp.getHeader(CONTENT_TYPE)).isEqualTo("image/gif"); assertThat(resp.bodyAsJsonObject()).isEqualTo(JsonObject.of("foo", "bar")); testContext.completeNow(); }))); } @NeonBeeDeployable(namespace = NEONBEE_NAMESPACE, autoDeploy = false) - public static class RawResponseVerticle extends DataVerticle { + public static class JsonResponseVerticle extends DataVerticle { @Override public Future retrieveData(DataQuery query, DataContext context) { - context.responseData().put("Content-Type", "image/gif"); + context.responseData().put(CONTENT_TYPE, "image/gif"); return Future.succeededFuture(JsonObject.of("foo", "bar")); } @@ -161,6 +171,21 @@ public String getName() { } } + @NeonBeeDeployable(namespace = NEONBEE_NAMESPACE, autoDeploy = false) + public static class BufferResponseVerticle extends DataVerticle { + + @Override + public Future retrieveData(DataQuery query, DataContext context) { + context.responseData().put(CONTENT_TYPE, "image/gif"); + return Future.succeededFuture(JsonObject.of("foo", "bar").toBuffer()); + } + + @Override + public String getName() { + return "Test"; + } + } + private Future> sendRequest(String verticleName, String path, String query) { String uriPath = String.format("/raw/%s/%s/%s?%s", NEONBEE_NAMESPACE, verticleName, path, query); return createRequest(HttpMethod.GET, uriPath).send();