diff --git a/rest/src/main/java/se/yolean/kafka/hook/rest/KafkaHookRestResource.java b/rest/src/main/java/se/yolean/kafka/hook/rest/KafkaHookRestResource.java index 95ade98..32e0bb4 100644 --- a/rest/src/main/java/se/yolean/kafka/hook/rest/KafkaHookRestResource.java +++ b/rest/src/main/java/se/yolean/kafka/hook/rest/KafkaHookRestResource.java @@ -17,20 +17,35 @@ import se.yolean.kafka.hook.http.KafkaHookResource; @Produces(MediaType.APPLICATION_JSON) -@Path("/hook/v1") +@Path("/") public class KafkaHookRestResource { @Inject KafkaHookResource hook; @POST - public Response produce(@Context HttpHeaders headers, @Context UriInfo uri, InputStream payload) throws IOException { + @Path("hook/v1") + public Response produce(@Context HttpHeaders headers, @Context UriInfo uri, InputStream payload) + throws IOException { return hook.produce(headers, uri, "", payload); } @POST - @Path("/{type}") + @Path("hook/v1/{type:.*}") public Response produce(@Context HttpHeaders headers, @Context UriInfo uri, @PathParam("type") String type, InputStream payload) - // if we fail to read the payload, which would be very strange + throws IOException { + return hook.produce(headers, uri, type, payload); + } + + @POST + @Path("{prefix}/v1/hook") + public Response produceAltPathWithoutType(@Context HttpHeaders headers, @Context UriInfo uri, InputStream payload) + throws IOException { + return hook.produce(headers, uri, "", payload); + } + + @POST + @Path("{prefix}/v1/hook/{type:.*}") + public Response produceAltPath(@Context HttpHeaders headers, @Context UriInfo uri, @PathParam("type") String type, InputStream payload) throws IOException { return hook.produce(headers, uri, type, payload); } diff --git a/rest/src/test/java/se/yolean/kafka/hook/rest/KafkaHookResourceIntegrationTest.java b/rest/src/test/java/se/yolean/kafka/hook/rest/KafkaHookResourceIntegrationTest.java index 0b70b1d..a52bff8 100644 --- a/rest/src/test/java/se/yolean/kafka/hook/rest/KafkaHookResourceIntegrationTest.java +++ b/rest/src/test/java/se/yolean/kafka/hook/rest/KafkaHookResourceIntegrationTest.java @@ -29,6 +29,7 @@ import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.CoreMatchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import java.io.UnsupportedEncodingException; import java.time.Duration; @@ -160,6 +161,44 @@ public void testProduceString() throws UnsupportedEncodingException { assertEquals("github.com/Yolean/kafka-hook/mytype", headers(record2).get("ce_type")); } + @Test + public void testProduceAlternativeUrls() throws UnsupportedEncodingException { + given() + .contentType(ContentType.TEXT) + .accept(ContentType.JSON) + .body("test1".getBytes()) + .when().post("/hook/v1/mytype/with/slashes") + .then() + .body(containsString("\"offset\":" + (startOffset))) + .statusCode(200); + given() + .contentType(ContentType.TEXT) + .accept(ContentType.JSON) + .body("test2".getBytes()) + .when().post("/some-prefix/v1/hook") + .then() + .body(containsString("\"offset\":" + (startOffset + 1))) + .statusCode(200); + given() + .contentType(ContentType.TEXT) + .accept(ContentType.JSON) + .body("test3".getBytes()) + .when().post("/some-prefix/v1/hook/sub/type/") + .then() + .body(containsString("\"offset\":" + (startOffset + 2))) + .statusCode(200); + waitBetweenPolls(); + ConsumerRecords records = consumer.poll(Duration.ofMillis(1000)); + Iterator> it = records.iterator(); + ConsumerRecord record1 = it.next(); + assertEquals("github.com/Yolean/kafka-hook/mytype/with/slashes", headers(record1).get("ce_type")); + ConsumerRecord record2 = it.next(); + assertEquals("github.com/Yolean/kafka-hook/", headers(record2).get("ce_type")); + ConsumerRecord record3 = it.next(); + assertNotEquals("github.com/Yolean/kafka-hook/sub/type/", headers(record3).get("ce_type")); + assertEquals("github.com/Yolean/kafka-hook/sub/type", headers(record3).get("ce_type")); + } + @Test public void testCloudeventsDistributedTracingExtensionWithEnvoyHeaders() { given()