Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explain semantics of quarkus.rest.path; add tests #15474

Merged
merged 1 commit into from Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -580,10 +580,10 @@ public List<HandlerChainCustomizer> scan(MethodInfo method, Map<String, Object>
});
}

private String determineApplicationPath(IndexView index, String defaultPath) {
private String determineApplicationPath(IndexView index, Optional<String> defaultPath) {
Collection<AnnotationInstance> applicationPaths = index.getAnnotations(ResteasyReactiveDotNames.APPLICATION_PATH);
if (applicationPaths.isEmpty()) {
return defaultPath;
return defaultPath.orElse("/");
}
// currently we only examine the first class that is annotated with @ApplicationPath so best
// fail if the user code has multiple such annotations instead of surprising the user
Expand Down
@@ -1,15 +1,20 @@
package io.quarkus.resteasy.reactive.server.deployment;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;

@ConfigRoot(name = "rest")
public class ResteasyReactiveServerConfig {

/**
* Set this to override the default path for JAX-RS resources if there are no
* annotated application classes.
* Set this to define the application path that serves as the base URI for all
* JAX-RS resource URIs provided by {@code @Path} annotations when there are no
* {@code @ApplicationPath} annotations defined on {@code Application} classes.
* <p>
* This value is always resolved relative to {@code quarkus.http.root-path}.
*/
@ConfigItem(defaultValue = "/")
String path;
@ConfigItem
Optional<String> path;
}
Expand Up @@ -3,11 +3,26 @@
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
/**
* Per spec:
* <quote>
* Paths are relative. For an annotated class the base URI is the application path, see ApplicationPath.
* For an annotated method the base URI is the effective URI of the containing class. For the purposes of
* absolutizing a path against the base URI , a leading '/' in a path is ignored and base URIs are treated
* as if they ended in '/'.
* </quote>
*/
@Path("hello")
public class HelloResource {

@GET
public String hello() {
return "hello";
}

@GET
@Path("/nested")
public String nested() {
return "world hello";
}
}
@@ -0,0 +1,29 @@
package io.quarkus.resteasy.reactive.server.test.path;

import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class RelativeRestPathTestCase {

@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.withConfigurationResource("empty.properties")
.overrideConfigKey("quarkus.rest.path", "foo")
.overrideConfigKey("quarkus.http.root-path", "/app")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClass(HelloResource.class));

@Test
public void testRestPath() {
RestAssured.basePath = "/";
// This is expected behavior (relative path appended to HTTP root path)
RestAssured.when().get("/app/foo/hello").then().body(Matchers.is("hello"));
RestAssured.when().get("/app/foo/hello/nested").then().body(Matchers.is("world hello"));
}
}
@@ -0,0 +1,45 @@
package io.quarkus.resteasy.reactive.server.test.path;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class RestApplicationPathTestCase {

@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.withConfigurationResource("empty.properties")
.overrideConfigKey("quarkus.rest.path", "/foo")
.overrideConfigKey("quarkus.http.root-path", "/app")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(HelloResource.class, BarApp.class));

/**
* Using @ApplicationPath will overlay/replace `quarkus.rest.path`.
* Per spec:
* <quote>
* Identifies the application path that serves as the base URI for all resource
* URIs provided by Path. May only be applied to a subclass of Application.
* </quote>
*
* This path will also be relative to the configured HTTP root
*/
@ApplicationPath("/bar")
public static class BarApp extends Application {
}

@Test
public void testRestPath() {
RestAssured.basePath = "/";
RestAssured.when().get("/app/bar/hello").then().body(Matchers.is("hello"));
RestAssured.when().get("/app/bar/hello/nested").then().body(Matchers.is("world hello"));
}
}
Expand Up @@ -2,7 +2,6 @@

import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -14,15 +13,16 @@ public class RestPathTestCase {

@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClass(HelloResource.class)
.addAsResource(new StringAsset("quarkus.rest.path=/foo"), "application.properties"));
.withConfigurationResource("empty.properties")
.overrideConfigKey("quarkus.rest.path", "/foo")
.overrideConfigKey("quarkus.http.root-path", "/app")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClass(HelloResource.class));

@Test
public void testRestPath() {
RestAssured.get("/hello")
.then().statusCode(404);
RestAssured.get("/foo/hello")
.then().statusCode(200).body(Matchers.equalTo("hello"));

RestAssured.basePath = "/";
RestAssured.when().get("/app/foo/hello").then().body(Matchers.is("hello"));
RestAssured.when().get("/app/foo/hello/nested").then().body(Matchers.is("world hello"));
}
}