Skip to content

Commit

Permalink
micrometer: cors preflight requests
Browse files Browse the repository at this point in the history
  • Loading branch information
ebullient committed Apr 13, 2021
1 parent d63baf1 commit dfd05be
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
@@ -0,0 +1,104 @@
package io.quarkus.micrometer.deployment.binder;

import static io.restassured.RestAssured.given;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.quarkus.micrometer.test.HelloResource;
import io.quarkus.micrometer.test.Util;
import io.quarkus.micrometer.test.VertxWebEndpoint;
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class UriTagCorsTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withConfigurationResource("test-logging.properties")
.overrideConfigKey("quarkus.micrometer.binder-enabled-default", "false")
.overrideConfigKey("quarkus.micrometer.binder.http-server.enabled", "true")
.overrideConfigKey("quarkus.micrometer.binder.vertx.enabled", "true")
.overrideConfigKey("quarkus.http.cors", "true")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(Util.class,
VertxWebEndpoint.class,
HelloResource.class));

static SimpleMeterRegistry registry = new SimpleMeterRegistry();

@BeforeAll
static void setRegistry() {
registry = new SimpleMeterRegistry();
Metrics.addRegistry(registry);
}

@AfterAll()
static void removeRegistry() {
Metrics.removeRegistry(registry);
}

@Test
public void testCORSPreflightRequest() {
String origin = "http://custom.origin.quarkus";
String methods = "GET,POST";
String headers = "X-Custom";
RestAssured.given()
.header("Origin", origin)
.header("Access-Control-Request-Method", methods)
.header("Access-Control-Request-Headers", headers)
.when().options("/hello/world").then()
.header("Access-Control-Allow-Origin", origin)
.header("Access-Control-Allow-Methods", methods)
.header("Access-Control-Allow-Headers", headers)
.statusCode(200);

RestAssured.given()
.header("Origin", origin)
.header("Access-Control-Request-Method", methods)
.header("Access-Control-Request-Headers", headers)
.when().options("/vertx/echo/anything").then()
.header("Access-Control-Allow-Origin", origin)
.header("Access-Control-Allow-Methods", methods)
.header("Access-Control-Allow-Headers", headers)
.statusCode(200);

RestAssured.given()
.header("Origin", origin)
.header("Access-Control-Request-Method", methods)
.header("Access-Control-Request-Headers", headers)
.when().options("/vertx/item/123").then()
.header("Access-Control-Allow-Origin", origin)
.header("Access-Control-Allow-Methods", methods)
.header("Access-Control-Allow-Headers", headers)
.statusCode(200);

RestAssured.given()
.when().options("/vertx/echo/anything").then()
.statusCode(200);

RestAssured.given()
.when().options("/hello/world").then()
.statusCode(200);

// CORS pre-flight
Assertions.assertEquals(1, registry.find("http.server.requests").tag("uri", "/cors-preflight").timers().size(),
Util.foundServerRequests(registry, "/cors-preflight should be used for preflight requests"));
Timer t = registry.find("http.server.requests").tag("uri", "/cors-preflight").timer();
Assertions.assertEquals(3, t.count(), "/cors-preflight checked twice");

// Normal OPTIONS requests
Assertions.assertEquals(1, registry.find("http.server.requests").tag("uri", "/vertx/echo/{msg}").timers().size(),
Util.foundServerRequests(registry, "/vertx/echo/{msg} for options request"));
Assertions.assertEquals(1, registry.find("http.server.requests").tag("uri", "/hello/{message}").timers().size(),
Util.foundServerRequests(registry, "/hello/{message} for options request"));
}
}
Expand Up @@ -69,7 +69,7 @@ static String applyMatchPatterns(String path, Map<Pattern, String> matchPatterns
}

/** Return path or null if it should be ignored */
static String filterIgnored(String path, List<Pattern> ignorePatterns) {
protected static String filterIgnored(String path, List<Pattern> ignorePatterns) {
if (!ignorePatterns.isEmpty()) {
for (Pattern p : ignorePatterns) {
if (p.matcher(path).matches()) {
Expand Down
Expand Up @@ -6,6 +6,7 @@
import java.util.regex.Pattern;

import io.quarkus.micrometer.runtime.binder.RequestMetricInfo;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.ext.web.RoutingContext;

Expand All @@ -31,6 +32,9 @@ public HttpRequestMetric(HttpServerRequest request) {
}

public String getNormalizedUriPath(Map<Pattern, String> matchPatterns, List<Pattern> ignorePatterns) {
if (isCORSPreflightRequest()) {
return filterIgnored("/cors-preflight", ignorePatterns);
}
return super.getNormalizedUriPath(matchPatterns, ignorePatterns, initialPath);
}

Expand Down Expand Up @@ -85,4 +89,11 @@ public String toString() {
return "HttpRequestMetric [initialPath=" + initialPath + ", currentRoutePath=" + getCurrentRoute()
+ ", templatePath=" + templatePath + ", request=" + request + "]";
}

private boolean isCORSPreflightRequest() {
return request.method() == HttpMethod.OPTIONS
&& request.getHeader("Origin") != null
&& request.getHeader("Access-Control-Request-Method") != null
&& request.getHeader("Access-Control-Request-Headers") != null;
}
}

0 comments on commit dfd05be

Please sign in to comment.