diff --git a/microprofile/cors/src/main/java/io/helidon/microprofile/cors/CrossOriginFilter.java b/microprofile/cors/src/main/java/io/helidon/microprofile/cors/CrossOriginFilter.java index c6901551630..2ee7e9149c4 100644 --- a/microprofile/cors/src/main/java/io/helidon/microprofile/cors/CrossOriginFilter.java +++ b/microprofile/cors/src/main/java/io/helidon/microprofile/cors/CrossOriginFilter.java @@ -102,13 +102,13 @@ Optional crossOriginFromAnnotationSupplier() { Optional optionsMethod = Arrays.stream(resourceClass.getDeclaredMethods()) .filter(m -> { OPTIONS optsAnnot2 = m.getAnnotation(OPTIONS.class); + Path pathAnnot2 = m.getAnnotation(Path.class); if (optsAnnot2 != null) { if (pathAnnot != null) { - Path pathAnnot2 = m.getAnnotation(Path.class); return pathAnnot2 != null && pathAnnot.value() .equals(pathAnnot2.value()); } - return true; + return pathAnnot2 == null; } return false; }) diff --git a/microprofile/cors/src/test/java/io/helidon/microprofile/cors/CrossOriginTest.java b/microprofile/cors/src/test/java/io/helidon/microprofile/cors/CrossOriginTest.java index 8de00d876e2..52e26e2a1d2 100644 --- a/microprofile/cors/src/test/java/io/helidon/microprofile/cors/CrossOriginTest.java +++ b/microprofile/cors/src/test/java/io/helidon/microprofile/cors/CrossOriginTest.java @@ -19,6 +19,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.RequestScoped; import javax.ws.rs.DELETE; +import javax.ws.rs.GET; import javax.ws.rs.HttpMethod; import javax.ws.rs.OPTIONS; import javax.ws.rs.PUT; @@ -84,7 +85,7 @@ static public class CorsApplication extends Application { @Override public Set> getClasses() { - return Set.of(CorsResource1.class, CorsResource2.class, CorsResource3.class); + return Set.of(CorsResource0.class, CorsResource1.class, CorsResource2.class, CorsResource3.class); } } @@ -147,6 +148,34 @@ public Response putCors() { } } + @RequestScoped + @Path("/cors0") + static public class CorsResource0 { + + @PUT + @Path("/subpath") + public Response put() { + return Response.ok().build(); + } + + @GET + public Response get() { + return Response.ok().build(); + } + + @OPTIONS + @CrossOrigin(value = {"http://foo.bar", "http://bar.foo"}, + allowMethods = {"PUT"}) + @Path("/subpath") + public void optionsForSubpath() { + } + + @OPTIONS + @CrossOrigin() + public void optionsForMainPath() { + } + } + @Test void test1PreFlightAllowedOrigin() { Response res = target.path("/app/cors1") @@ -353,4 +382,40 @@ void testErrorResponse() { assertThat(res.getStatusInfo(), is(Response.Status.NOT_FOUND)); assertThat(res.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN), is(false)); } + + @Test + void testMainPathInPresenceOfSubpath() { + Response res = target.path("/app/cors0") + .request() + .header(ORIGIN, "http://foo.bar") + .get(); + assertThat(res.getStatusInfo(), is(Response.Status.OK)); + assertThat(res.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN), is(true)); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN), is("*")); + } + + @Test + void testSubPathPreflightAllowed() { + Response res = target.path("/app/cors0/subpath") + .request() + .header(ORIGIN, "http://foo.bar") + .header(ACCESS_CONTROL_REQUEST_METHOD, "PUT") + .options(); + assertThat(res.getStatusInfo(), is(Response.Status.OK)); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://foo.bar")); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_METHODS), is("PUT")); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue())); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_MAX_AGE), is("3600")); + } + + @Test + void testSubPathActualAllowed() { + Response res = target.path("/app/cors0/subpath") + .request() + .header(ORIGIN, "http://foo.bar") + .header(ACCESS_CONTROL_REQUEST_METHOD, "PUT") + .put(Entity.entity("", MediaType.TEXT_PLAIN_TYPE)); + assertThat(res.getStatusInfo(), is(Response.Status.OK)); + assertThat(res.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://foo.bar")); + } }