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

Allow to skip parsing the request's url into URI #10178

Merged
merged 4 commits into from
Dec 5, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,6 @@ public class NettyClientHttpRequest<B> implements MutableHttpRequest<B>, NettyHt
private NettyHttpParameters httpParameters;
private ConversionService conversionService = ConversionService.SHARED;

/**
* This constructor is actually required for the case of non-standard http methods.
*
* @param httpMethod The http method. CUSTOM value is used for non-standard
* @param uri The uri
* @param httpMethodName Method name. Is the same as httpMethod.name() value for standard http methods.
*/
NettyClientHttpRequest(HttpMethod httpMethod, URI uri, String httpMethodName) {
this.httpMethod = httpMethod;
this.uri = uri;
this.httpMethodName = httpMethodName;
}

/**
* @param httpMethod The Http method
* @param uri The URI
Expand All @@ -104,11 +91,13 @@ public class NettyClientHttpRequest<B> implements MutableHttpRequest<B>, NettyHt
* This constructor is actually required for the case of non-standard http methods.
*
* @param httpMethod The http method. CUSTOM value is used for non-standard
* @param uri The uri
* @param url The uri
* @param httpMethodName Method name. Is the same as httpMethod.name() value for standard http methods.
*/
NettyClientHttpRequest(HttpMethod httpMethod, String uri, String httpMethodName) {
this(httpMethod, URI.create(uri), httpMethodName);
NettyClientHttpRequest(HttpMethod httpMethod, String url, String httpMethodName) {
this.httpMethod = httpMethod;
this.uri = URI.create(url);
this.httpMethodName = httpMethodName;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpParameters;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MediaType;
import io.micronaut.http.netty.stream.DefaultStreamedHttpRequest;
import io.micronaut.http.netty.stream.StreamedHttpRequest;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
Expand All @@ -34,9 +33,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Locale;
import java.util.Optional;

/**
* Abstract implementation of {@link HttpRequest} for Netty.
Expand All @@ -51,15 +47,13 @@ public abstract class AbstractNettyHttpRequest<B> extends DefaultAttributeMap im
protected final io.netty.handler.codec.http.HttpRequest nettyRequest;
protected final ConversionService conversionService;
protected final HttpMethod httpMethod;
protected final URI uri;
protected final String unvalidatedUrl;
protected final String httpMethodName;

private URI uri;
private NettyHttpParameters httpParameters;
private Optional<MediaType> mediaType;
private Charset charset;
private Optional<Locale> locale;
private String path;
private Collection<MediaType> accept;

/**
* @param nettyRequest The Http netty request
Expand All @@ -68,22 +62,7 @@ public abstract class AbstractNettyHttpRequest<B> extends DefaultAttributeMap im
public AbstractNettyHttpRequest(io.netty.handler.codec.http.HttpRequest nettyRequest, ConversionService conversionService) {
this.nettyRequest = nettyRequest;
this.conversionService = conversionService;
URI fullUri = URI.create(nettyRequest.uri());
if (fullUri.getAuthority() != null || fullUri.getScheme() != null) {
// https://example.com/foo -> /foo
try {
fullUri = new URI(
null, // scheme
null, // authority
fullUri.getPath(),
fullUri.getQuery(),
fullUri.getFragment()
);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
this.uri = fullUri;
this.unvalidatedUrl = nettyRequest.uri();
this.httpMethodName = nettyRequest.method().name();
this.httpMethod = HttpMethod.parse(httpMethodName);
}
Expand Down Expand Up @@ -163,23 +142,6 @@ public HttpParameters getParameters() {
return params;
}

@Override
public Collection<MediaType> accept() {
if (accept == null) {
accept = HttpRequest.super.accept();
}
return accept;
}

@Override
@SuppressWarnings("java:S2789") // performance opt
public Optional<MediaType> getContentType() {
if (mediaType == null) {
mediaType = HttpRequest.super.getContentType();
}
return mediaType;
}

@Override
public Charset getCharacterEncoding() {
if (charset == null) {
Expand All @@ -188,23 +150,24 @@ public Charset getCharacterEncoding() {
return charset;
}

@Override
@SuppressWarnings("java:S2789") // performance opt
public Optional<Locale> getLocale() {
if (locale == null) {
locale = HttpRequest.super.getLocale();
}
return locale;
}

@Override
public HttpMethod getMethod() {
return httpMethod;
}

@Override
public URI getUri() {
return this.uri;
URI u = this.uri;
if (u == null) {
synchronized (this) { // double check
u = this.uri;
if (u == null) {
u = createURI(unvalidatedUrl);
this.uri = u;
}
}
}
return u;
}

@Override
Expand All @@ -214,7 +177,7 @@ public String getPath() {
synchronized (this) { // double check
p = this.path;
if (p == null) {
p = decodePath();
p = parsePath(unvalidatedUrl);
this.path = p;
}
}
Expand All @@ -223,7 +186,7 @@ public String getPath() {
}

/**
* @param characterEncoding The charactger encoding
* @param characterEncoding The character encoding
* @return The Charset
*/
protected abstract Charset initCharset(Charset characterEncoding);
Expand All @@ -238,18 +201,65 @@ protected final QueryStringDecoder createDecoder(URI uri) {
return cs != null ? new QueryStringDecoder(uri, cs) : new QueryStringDecoder(uri);
}

private String decodePath() {
QueryStringDecoder queryStringDecoder = createDecoder(uri);
return queryStringDecoder.rawPath();
}

private NettyHttpParameters decodeParameters() {
QueryStringDecoder queryStringDecoder = createDecoder(uri);
QueryStringDecoder queryStringDecoder = createDecoder(getUri());
return new NettyHttpParameters(queryStringDecoder.parameters(), conversionService, null);
}

@Override
public String getMethodName() {
return httpMethodName;
}

private static URI createURI(String url) {
URI fullUri = URI.create(url);
if (fullUri.getAuthority() != null || fullUri.getScheme() != null) {
// https://example.com/foo -> /foo
try {
fullUri = new URI(
null, // scheme
null, // authority
fullUri.getPath(),
fullUri.getQuery(),
fullUri.getFragment()
);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
return fullUri;
}

/**
* Extract the path out of the uri.
* https://github.com/eclipse-vertx/vert.x/blob/master/src/main/java/io/vertx/core/http/impl/HttpUtils.java
*/
private static String parsePath(String uri) {
if (uri.isEmpty()) {
return "";
}
int i;
if (uri.charAt(0) == '/') {
i = 0;
} else {
i = uri.indexOf("://");
if (i == -1) {
i = 0;
} else {
i = uri.indexOf('/', i + 3);
if (i == -1) {
// contains no /
return "/";
}
}
}
int queryStart = uri.indexOf('?', i);
if (queryStart == -1) {
queryStart = uri.length();
if (i == 0) {
return uri;
}
}
return uri.substring(i, queryStart);
}
}
Loading
Loading