Skip to content

Commit

Permalink
Fix CORS annotation handling error in certain cases (#5105)
Browse files Browse the repository at this point in the history
Signed-off-by: tim.quinn@oracle.com <tim.quinn@oracle.com>

Signed-off-by: tim.quinn@oracle.com <tim.quinn@oracle.com>
  • Loading branch information
tjquinno authored Oct 10, 2022
1 parent 7f6e557 commit 46c0f0f
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.AnnotatedType;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessAnnotatedType;
import jakarta.enterprise.inject.spi.ProcessManagedBean;
import jakarta.enterprise.inject.spi.WithAnnotations;
import jakarta.ws.rs.OPTIONS;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.config.ConfigProvider;
Expand All @@ -61,27 +58,20 @@ public class CorsCdiExtension implements Extension {

private CorsSupportMp corsSupportMp;

private final Set<AnnotatedType<?>> annotatedTypes = new HashSet<>();
private final Set<Method> methodsWithCrossOriginIncorrectlyUsed = new HashSet<>();
private final Map<Method, CrossOriginConfig> corsConfigs = new HashMap<>();

void recordCrossOrigin(@Observes @WithAnnotations(CrossOrigin.class) ProcessAnnotatedType<?> pat) {
annotatedTypes.add(pat.getAnnotatedType());
}

void processManagedBean(@Observes ProcessManagedBean<?> pmb) {
if (annotatedTypes.contains(pmb.getAnnotatedBeanClass())) {
pmb.getAnnotatedBeanClass().getMethods().forEach(am -> {
Method method = am.getJavaMember();
if (am.isAnnotationPresent(CrossOrigin.class) && !am.isAnnotationPresent(OPTIONS.class)) {
methodsWithCrossOriginIncorrectlyUsed.add(method);
} else {
crossOriginConfigFromAnnotationOnAssociatedMethod(method)
.ifPresent(crossOriginConfig -> corsConfigs.put(method,
crossOriginConfig));
}
});
}
pmb.getAnnotatedBeanClass().getMethods().forEach(am -> {
Method method = am.getJavaMember();
if (am.isAnnotationPresent(CrossOrigin.class) && !am.isAnnotationPresent(OPTIONS.class)) {
methodsWithCrossOriginIncorrectlyUsed.add(method);
} else {
crossOriginConfigFromAnnotationOnAssociatedMethod(method)
.ifPresent(crossOriginConfig -> corsConfigs.put(method,
crossOriginConfig));
}
});
}

void recordSupplierOfCrossOriginConfigFromAnnotation(Supplier<Optional<CrossOriginConfig>> supplier) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.microprofile.cors;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

import io.helidon.microprofile.tests.junit5.AddBean;
import io.helidon.microprofile.tests.junit5.AddExtension;

import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessAnnotatedType;
import jakarta.enterprise.util.AnnotationLiteral;
import jakarta.inject.Inject;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

@AddBean(CrossOriginTest.CorsResource0.class)
@AddExtension(TestWithAdjustedCorsType.AugmentingExtension.class)
class TestWithAdjustedCorsType extends BaseCrossOriginTest {

@Inject
private WebTarget webTarget;

@Test
void checkAdjustedResource() {
// The extension below will have augmented the AnnotatedType (adding a synthetic annotation).
// Weld delivers a different concrete subtype of AnnotatedType to the CORS extension as a result.
// Make sure the CORS request still works correctly.

Response response = webTarget.path("/cors0")
.request()
.header("Origin", "http://foo.com")
.header("Host", "here.com")
.buildGet()
.invoke();

assertThat("Status from simple CORS request", response.getStatus(), is(200));
}

public static class AugmentingExtension implements Extension {

void processAnnotatedType(@Observes ProcessAnnotatedType<?> pat) {
// Single out the CORS-controlled resource.
if (pat.getAnnotatedType().getJavaClass().getName().equals(CrossOriginTest.CorsResource0.class.getName())) {
pat.configureAnnotatedType()
.add(AugmentingAnnotation.Literal.getInstance());
}
}
}

@Target(ElementType.TYPE)
static @interface AugmentingAnnotation {
class Literal extends AnnotationLiteral<AugmentingAnnotation> implements AugmentingAnnotation {

private static final long serialVersionUID = 1L;

private static final Literal INSTANCE=new Literal();

static Literal getInstance(){
return INSTANCE;
}

private Literal(){
}
}
}
}

0 comments on commit 46c0f0f

Please sign in to comment.