Skip to content

Commit

Permalink
Reactive routes - set content-type from Route#produces()
Browse files Browse the repository at this point in the history
- if no content-type header is set try to use
RoutingContext#getAcceptableContentType()
- resolves quarkusio#10465
  • Loading branch information
mkouba committed Jul 6, 2020
1 parent 4ea20a0 commit f3ced2d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.quarkus.vertx.web.runtime.MultiJsonArraySupport;
import io.quarkus.vertx.web.runtime.MultiSseSupport;
import io.quarkus.vertx.web.runtime.MultiSupport;
import io.quarkus.vertx.web.runtime.RouteHandlers;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.groups.UniSubscribe;
Expand Down Expand Up @@ -136,6 +137,9 @@ class Methods {
CreationalContext.class);
static final MethodDescriptor OBJECT_CONSTRUCTOR = MethodDescriptor.ofConstructor(Object.class);

static final MethodDescriptor ROUTE_HANDLERS_SET_CONTENT_TYPE = MethodDescriptor
.ofMethod(RouteHandlers.class, "setContentType", void.class, RoutingContext.class);

private Methods() {
// Avoid direct instantiation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,10 +530,13 @@ void implementInvoke(HandlerDescriptor descriptor, BeanInfo bean, MethodInfo met
// Invoke the business method handler
ResultHandle res = invoke.invokeVirtualMethod(methodDescriptor, beanInstanceHandle, paramHandles);

// If no content-type header is set then try to use the most acceptable content type
invoke.invokeStaticMethod(Methods.ROUTE_HANDLERS_SET_CONTENT_TYPE, routingContext);

// Get the response: HttpServerResponse response = rc.response()
ResultHandle response = invoke.invokeInterfaceMethod(Methods.RESPONSE, routingContext);
MethodDescriptor end = Methods.getEndMethodForContentType(descriptor);
if (descriptor.isReturningUni()) {
ResultHandle response = invoke.invokeInterfaceMethod(Methods.RESPONSE, routingContext);
// The method returns a Uni.
// We subscribe to this Uni and write the provided item in the HTTP response
// If the method returned null, we fail
Expand Down Expand Up @@ -568,7 +571,7 @@ void implementInvoke(HandlerDescriptor descriptor, BeanInfo bean, MethodInfo met

} else if (descriptor.getContentType() != null) {
// The method returns "something" in a synchronous manner, write it into the response

ResultHandle response = invoke.invokeInterfaceMethod(Methods.RESPONSE, routingContext);
// If the method returned null, we fail
// If the method returns string or buffer, the response.end method is used to write the response
// If the method returns an object, the result is mapped to JSON and written into the response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.vertx.core.Handler;
import io.vertx.core.http.HttpMethod;
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.
Expand Down Expand Up @@ -74,8 +75,11 @@

/**
* Used for content-based routing.
* <p>
* If no {@code Content-Type} header is set then try to use the most acceptable content type.
*
* @see io.vertx.ext.web.Route#produces(String)
* @see RoutingContext#getAcceptableContentType()
* @return the produced content types
*/
String[] produces() default {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@
import io.quarkus.arc.Arc;
import io.quarkus.arc.impl.LazyValue;
import io.quarkus.security.identity.SecurityIdentity;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.RoutingContext;

final class RouteHandlers {
public final class RouteHandlers {

private RouteHandlers() {
}

static final String CONTENT_TYPE = "content-type";

private static final LazyValue<Event<SecurityIdentity>> SECURITY_IDENTITY_EVENT = new LazyValue<>(
RouteHandlers::createEvent);

public static void setContentType(RoutingContext context) {
HttpServerResponse response = context.response();
if (response.headers().get(CONTENT_TYPE) == null) {
String acceptableContentType = context.getAcceptableContentType();
if (acceptableContentType != null) {
response.putHeader(CONTENT_TYPE, acceptableContentType);
}
}
}

static void fireSecurityIdentity(SecurityIdentity identity) {
SECURITY_IDENTITY_EVENT.get().fire(identity);
}
Expand Down

0 comments on commit f3ced2d

Please sign in to comment.