io.quarkus.vertx.web.Route Maven / Gradle / Ivy
Show all versions of quarkus-reactive-routes Show documentation
package io.quarkus.vertx.web;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.quarkus.vertx.web.Route.Routes;
import io.vertx.core.Handler;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
/**
* This annotation can be used to configure a reactive route in a declarative way.
*
* The target business method must be non-private and non-static.
* The annotated method can accept arguments of the following types:
*
* - {@code io.vertx.ext.web.RoutingContext}
* - {@code io.vertx.mutiny.ext.web.RoutingContext}
* - {@code io.quarkus.vertx.web.RoutingExchange}
* - {@code io.vertx.core.http.HttpServerRequest}
* - {@code io.vertx.core.http.HttpServerResponse}
* - {@code io.vertx.mutiny.core.http.HttpServerRequest}
* - {@code io.vertx.mutiny.core.http.HttpServerResponse}
*
* Furthermore, it is possible to inject the request parameters into a method parameter annotated with
* {@link io.quarkus.vertx.web.Param}:
*
*
*
* class Routes {
* {@literal @Route}
* String hello({@literal @Param Optional} name) {
* return "Hello " + name.orElse("world");
* }
* }
*
*
*
* The request headers can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Header}:
*
*
*
* class Routes {
* {@literal @Route}
* String helloFromHeader({@literal @Header("My-Header")} String header) {
* return "Hello " + header;
* }
* }
*
*
*
* The request body can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Body}:
*
*
*
* class Routes {
* {@literal @Route(produces = "application/json")}
* Person updatePerson({@literal @Body} Person person) {
* person.setName("Bob");
* return person;
* }
* }
*
*
*
* If the annotated method returns {@code void} then it has to accept at least one argument that makes it possible to end the
* response, for example {@link RoutingContext}.
* If the annotated method does not return {@code void} then the arguments are optional.
*
* If both {@link #path()} and {@link #regex()} are set the regular expression is used for matching.
*
* If neither {@link #path()} nor {@link #regex()} is specified and the handler type is not {@link HandlerType#FAILURE} then the
* route will match a path derived from the name of the method. This is done by de-camel-casing the name and then joining the
* segments
* with hyphens.
*/
@Repeatable(Routes.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Route {
/**
* Represents an HTTP method.
* This enumeration only provides the common HTTP method.
* For custom methods, you need to register the {@code route} manually on the managed {@code Router}.
*/
enum HttpMethod {
GET,
HEAD,
POST,
PUT,
DELETE,
OPTIONS
}
/**
*
* @see Router#route(String)
* @return the path
*/
String path() default "";
/**
*
* @see Router#routeWithRegex(String)
* @return the path regex
*/
String regex() default "";
/**
*
* @see io.vertx.ext.web.Route#methods()
* @return the HTTP methods
*/
HttpMethod[] methods() default {};
/**
*
* @return the type of the handler
*/
HandlerType type() default HandlerType.NORMAL;
/**
* If set to a positive number, it indicates the place of the route in the chain.
*
* @see io.vertx.ext.web.Route#order(int)
*/
int order() default 0;
/**
* Used for content-based routing and stream serialization.
*
* If no {@code Content-Type} header is set then try to use the most acceptable content-type.
*
* If the request does not contain an 'Accept' header and no content type is explicitly set in the
* handler then the content type will be set to the first content type in the array.
*
* When a route returns a {@link io.smallrye.mutiny.Multi}, this attribute is used to define how that stream is
* serialized. In this case, accepted values are:
*
* - {@link ReactiveRoutes#APPLICATION_JSON} - Encode the response into a JSON Array, where each item is sent one by
* one,
* - {@link ReactiveRoutes#EVENT_STREAM} - Encode the response as a stream of server-sent-events,
* - {@link ReactiveRoutes#ND_JSON} or {@link ReactiveRoutes#JSON_STREAM} - Encode the response as JSON stream,
* when each item is sent one by one with a `\n` as delimiter between them
*
*
* When this attribute is not set, and the route returns a {@link io.smallrye.mutiny.Multi}, no special serialization is
* applied.
* The items are sent one-by-one without delimiters.
*
* @see io.vertx.ext.web.Route#produces(String)
* @see RoutingContext#getAcceptableContentType()
* @return the produced content types
*/
String[] produces() default {};
/**
* Used for content-based routing.
*
* @see io.vertx.ext.web.Route#consumes(String)
* @return the consumed content types
*/
String[] consumes() default {};
enum HandlerType {
/**
* A non-blocking request handler.
*
* @see io.vertx.ext.web.Route#handler(Handler)
*/
NORMAL,
/**
* A blocking request handler.
*
* @see io.vertx.ext.web.Route#blockingHandler(Handler)
*/
BLOCKING,
/**
* A failure handler can declare a single method parameter whose type extends {@link Throwable}. The type of the
* parameter is used to match the result of {@link RoutingContext#failure()}.
*
*
*
* class Routes {
* {@literal @Route(type = HandlerType.FAILURE)}
* void unsupported(UnsupportedOperationException e, HttpServerResponse response) {
* response.setStatusCode(501).end(e.getMessage());
* }
* }
*
*
*
*
* If a failure handler declares neither a path nor a regex then the route matches all requests.
*
* @see io.vertx.ext.web.Route#failureHandler(Handler)
*/
FAILURE;
public static HandlerType from(String value) {
for (HandlerType handlerType : values()) {
if (handlerType.toString().equals(value)) {
return handlerType;
}
}
return null;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Routes {
Route[] value();
}
}