Skip to content

Commit

Permalink
Optimise request/response vertx header lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
franz1981 committed Feb 6, 2024
1 parent 99d258c commit 5bacb3b
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.SecurityContext;

import org.jboss.resteasy.reactive.server.core.Deployment;
Expand Down Expand Up @@ -169,6 +170,26 @@ public boolean resumeExternalProcessing() {
return false;
}

@Override
public String getRequestAccept() {
return getRequestHeader(HttpHeaders.ACCEPT);
}

@Override
public List<String> getAllRequestAccepts() {
return getAllRequestHeaders(HttpHeaders.ACCEPT);
}

@Override
public String getRequestContentType() {
return getRequestHeader(HttpHeaders.CONTENT_TYPE);
}

@Override
public List<String> getAllRequestContentTypes() {
return getAllRequestHeaders(HttpHeaders.CONTENT_TYPE);
}

@Override
public String getRequestHeader(CharSequence name) {
return request.getHeader(name.toString());
Expand Down Expand Up @@ -402,6 +423,11 @@ public ServerHttpResponse setResponseHeader(CharSequence name, CharSequence valu
return this;
}

@Override
public ServerHttpResponse setResponseContentType(final boolean capitalLettersHeaderName, final CharSequence value) {
return setResponseHeader(capitalLettersHeaderName ? "Content-Type" : "content-type", value);
}

@Override
public ServerHttpResponse setResponseHeader(CharSequence name, Iterable<CharSequence> values) {
for (CharSequence v : values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,57 @@ public boolean isProducesChecked() {
return producesChecked;
}

public List<String> getAccept(boolean single) {
if (httpHeaders == null) {
if (single) {
var accept = serverRequest().getRequestAccept();
if (accept == null) {
return null;
}
return List.of(accept);
}
// empty collections must not be turned to null
return serverRequest().getAllRequestAccepts();
} else {
if (single) {
return List.of(httpHeaders.getMutableHeaders().getFirst(HttpHeaders.ACCEPT));
}
// empty collections must not be turned to null
List<String> list = httpHeaders.getMutableHeaders().get(HttpHeaders.ACCEPT);
if (list == null) {
return Collections.emptyList();
} else {
return list;
}
}
}

// same as getAccept but for ContentType
public List<String> getContentType(boolean single) {
if (httpHeaders == null) {
if (single) {
var contentType = serverRequest().getRequestContentType();
if (contentType == null) {
return null;
}
return List.of(contentType);
}
// empty collections must not be turned to null
return serverRequest().getAllRequestContentTypes();
} else {
if (single) {
return List.of(httpHeaders.getMutableHeaders().getFirst(HttpHeaders.CONTENT_TYPE));
}
// empty collections must not be turned to null
List<String> list = httpHeaders.getMutableHeaders().get(HttpHeaders.CONTENT_TYPE);
if (list == null) {
return Collections.emptyList();
} else {
return list;
}
}
}

@Override
public Object getHeader(String name, boolean single) {
if (httpHeaders == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.StreamingOutput;
import jakarta.ws.rs.core.Variant;
import jakarta.ws.rs.ext.MessageBodyReader;
import jakarta.ws.rs.ext.MessageBodyWriter;
import jakarta.ws.rs.ext.WriterInterceptor;

Expand Down Expand Up @@ -80,11 +79,8 @@ public void accept(ResteasyReactiveRequestContext context) {

private static final String CONTENT = "Content";
private static final String CONTENT_LOWER = "content";
private static final String TYPE = "Type";
private static final String TYPE_LOWER = "type";
private static final String LENGTH = "Length";
private static final String LENGTH_LOWER = "length";
private static final String CONTENT_TYPE = CONTENT + "-" + TYPE; // use this instead of the Vert.x constant because the TCK expects upper case

public final static List<Serialisers.BuiltinReader> BUILTIN_READERS = List.of(
new Serialisers.BuiltinReader(String.class, ServerStringMessageBodyHandler.class,
Expand Down Expand Up @@ -137,8 +133,6 @@ public void accept(ResteasyReactiveRequestContext context) {
MediaType.WILDCARD));

public static final MessageBodyWriter<?>[] NO_WRITER = new MessageBodyWriter[0];
public static final MessageBodyReader<?>[] NO_READER = new MessageBodyReader[0];

private final ConcurrentMap<Class<?>, List<ResourceWriter>> noMediaTypeClassCache = new ConcurrentHashMap<>();
private final Function<Class<?>, List<ResourceWriter>> mappingFunction = new Function<Class<?>, List<ResourceWriter>>() {
@Override
Expand Down Expand Up @@ -485,10 +479,15 @@ public static void encodeResponseHeaders(ResteasyReactiveRequestContext requestC
}
EncodedMediaType contentType = requestContext.getResponseContentType();
if (contentType != null) {
vertxResponse.setResponseHeader(CONTENT_TYPE, contentType.toString());
vertxResponse.setResponseContentType(true, contentType.toString());
}
return;
}
encodeExistingResponseHeaders(requestContext, vertxResponse);
}

private static void encodeExistingResponseHeaders(ResteasyReactiveRequestContext requestContext,
ServerHttpResponse vertxResponse) {
Response response = requestContext.getResponse().get();
vertxResponse.setStatusCode(response.getStatus());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import jakarta.ws.rs.NotAllowedException;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.NotSupportedException;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

Expand Down Expand Up @@ -106,12 +105,12 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti

// according to the spec we need to return HTTP 415 when content-type header doesn't match what is specified in @Consumes
if (!target.value.getConsumes().isEmpty()) {
String contentType = (String) requestContext.getHeader(HttpHeaders.CONTENT_TYPE, true);
if (contentType != null) {
var contentTypes = requestContext.getContentType(true);
if (contentTypes != null) {
try {
if (MediaTypeHelper.getFirstMatch(
target.value.getConsumes(),
Collections.singletonList(MediaType.valueOf(contentType))) == null) {
Collections.singletonList(MediaType.valueOf(contentTypes.get(0)))) == null) {
throw new NotSupportedException("The content-type header value did not match the value in @Consumes");
}
} catch (IllegalArgumentException e) {
Expand All @@ -123,7 +122,7 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti
if (target.value.getProduces() != null) {
// there could potentially be multiple Accept headers and we need to response with 406
// if none match the method's @Produces
List<String> accepts = (List<String>) requestContext.getHeader(HttpHeaders.ACCEPT, false);
List<String> accepts = requestContext.getAccept(false);
if (!accepts.isEmpty()) {
boolean hasAtLeastOneMatch = false;
for (int i = 0; i < accepts.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@

public interface ServerHttpRequest {

String getRequestAccept();

List<String> getAllRequestAccepts();

String getRequestContentType();

List<String> getAllRequestContentTypes();

String getRequestHeader(CharSequence name);

Iterable<Map.Entry<String, String>> getAllRequestHeaders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public interface ServerHttpResponse extends StreamingResponse<ServerHttpResponse

ServerHttpResponse setResponseHeader(CharSequence name, CharSequence value);

ServerHttpResponse setResponseContentType(boolean capitalLettersHeaderName, CharSequence value);

ServerHttpResponse setResponseHeader(CharSequence name, Iterable<CharSequence> values);

Iterable<Map.Entry<String, String>> getAllResponseHeaders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
public class VertxResteasyReactiveRequestContext extends ResteasyReactiveRequestContext
implements ServerHttpRequest, ServerHttpResponse, Handler<Void> {

private static final CharSequence CAPITAL_CONTENT_TYPE = io.vertx.core.http.HttpHeaders
.createOptimized(HttpHeaders.CONTENT_TYPE);
public static final String CONTINUE = "100-continue";
protected final RoutingContext context;
protected final HttpServerRequest request;
Expand Down Expand Up @@ -144,6 +146,26 @@ public boolean resumeExternalProcessing() {
return true;
}

@Override
public String getRequestAccept() {
return request.headers().get(io.vertx.core.http.HttpHeaders.ACCEPT);
}

@Override
public List<String> getAllRequestAccepts() {
return request.headers().getAll(io.vertx.core.http.HttpHeaders.ACCEPT);
}

@Override
public String getRequestContentType() {
return request.headers().get(io.vertx.core.http.HttpHeaders.CONTENT_TYPE);
}

@Override
public List<String> getAllRequestContentTypes() {
return request.headers().getAll(io.vertx.core.http.HttpHeaders.CONTENT_TYPE);
}

@Override
public String getRequestHeader(CharSequence name) {
return request.headers().get(name);
Expand Down Expand Up @@ -389,6 +411,13 @@ public ServerHttpResponse setResponseHeader(CharSequence name, Iterable<CharSequ
return this;
}

@Override
public ServerHttpResponse setResponseContentType(boolean capitalLettersHeaderName, CharSequence value) {
response.headers().set(capitalLettersHeaderName ? CAPITAL_CONTENT_TYPE : io.vertx.core.http.HttpHeaders.CONTENT_TYPE,
value);
return this;
}

@Override
public Iterable<Map.Entry<String, String>> getAllResponseHeaders() {
return response.headers();
Expand Down

0 comments on commit 5bacb3b

Please sign in to comment.