Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
116 changes: 99 additions & 17 deletions src/main/java/net/dv8tion/jda/api/requests/Route.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import net.dv8tion.jda.internal.utils.EncodingUtil;
import net.dv8tion.jda.internal.utils.EntityString;
import net.dv8tion.jda.internal.utils.Helpers;
import okhttp3.HttpUrl;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
Expand Down Expand Up @@ -661,7 +663,7 @@ public CompiledRoute compile(@Nonnull String... params) {
params.length);

StringJoiner major = new StringJoiner(":").setEmptyValue("n/a");
StringJoiner compiledRoute = new StringJoiner("/");
List<PathSegment> path = new ArrayList<>();

int paramIndex = 0;
for (String element : template) {
Expand All @@ -676,13 +678,13 @@ public CompiledRoute compile(@Nonnull String... params) {
major.add(name + "=" + value);
}
}
compiledRoute.add(EncodingUtil.encodeUTF8(value));
path.add(new PathSegment(value, false));
} else {
compiledRoute.add(element);
path.add(new PathSegment(element, true));
}
}

return new CompiledRoute(this, compiledRoute.toString(), major.toString());
return new CompiledRoute(this, path, major.toString());
}

@Override
Expand Down Expand Up @@ -713,19 +715,19 @@ public String toString() {
public class CompiledRoute {
private final Route baseRoute;
private final String major;
private final String compiledRoute;
private final List<String> query;
private final List<PathSegment> path;
private final List<QueryParameter> query;

private CompiledRoute(Route baseRoute, String compiledRoute, String major) {
private CompiledRoute(Route baseRoute, List<PathSegment> path, String major) {
this.baseRoute = baseRoute;
this.compiledRoute = compiledRoute;
this.path = path;
this.major = major;
this.query = null;
}

private CompiledRoute(CompiledRoute original, List<String> query) {
private CompiledRoute(CompiledRoute original, List<QueryParameter> query) {
this.baseRoute = original.baseRoute;
this.compiledRoute = original.compiledRoute;
this.path = original.path;
this.major = original.major;
this.query = query;
}
Expand Down Expand Up @@ -770,7 +772,7 @@ public CompiledRoute withQueryParams(@Nonnull String... params) {
Checks.check(params.length >= 2, "Params length must be at least 2");
Checks.check((params.length & 1) == 0, "Params length must be a multiple of 2");

List<String> newQuery;
List<QueryParameter> newQuery;
if (query == null) {
newQuery = new ArrayList<>(params.length / 2);
} else {
Expand All @@ -782,7 +784,7 @@ public CompiledRoute withQueryParams(@Nonnull String... params) {
for (int i = 0; i < params.length; i += 2) {
Checks.notEmpty(params[i], "Query key [" + i / 2 + "]");
Checks.notNull(params[i + 1], "Query value [" + i / 2 + "]");
newQuery.add(params[i] + '=' + EncodingUtil.encodeUTF8(params[i + 1]));
newQuery.add(new QueryParameter(params[i], params[i + 1]));
}

return new CompiledRoute(this, newQuery);
Expand All @@ -807,11 +809,61 @@ public String getMajorParameters() {
*/
@Nonnull
public String getCompiledRoute() {
String compiledRoute = path.stream().map(PathSegment::toString).collect(Collectors.joining("/"));

if (query == null) {
return compiledRoute;
}
// Append query to url
return compiledRoute + '?' + String.join("&", query);

String queryString = query.stream().map(QueryParameter::toString).collect(Collectors.joining("&", "?", ""));
return compiledRoute + queryString;
}

/**
* Builds an {@link HttpUrl} for this route using the provided {@code baseUrl}.
*
* <p>This method preserves the encoding performed by {@link #compile(String...)} and
* {@link #withQueryParams(String...)}:
* <ul>
* <li>Path segments are appended using {@link HttpUrl.Builder#addEncodedPathSegments(String)}.
* This means already-encoded sequences (such as {@code %2F}) are <em>not</em> decoded or normalized.</li>
* <li>Query parameters are appended using {@link HttpUrl.Builder#addEncodedQueryParameter(String, String)}.
* Values are expected to already be percent-encoded (as produced by {@link #withQueryParams(String...)}).</li>
* </ul>
*
* <p><b>Note:</b> The {@code baseUrl} should typically point to the API root (for example,
* {@code https://discord.com/api/v10/}), and this method will append the compiled route path and query.
*
* @param baseUrl
* The base URL to append this route to
*
* @throws IllegalArgumentException
* If null is provided
*
* @return The final {@link HttpUrl} for this route
*
* @see #getCompiledRoute()
*/
@Nonnull
public HttpUrl toHttpUrl(@Nonnull HttpUrl baseUrl) {
Checks.notNull(baseUrl, "Base URL");
HttpUrl.Builder url = baseUrl.newBuilder();

for (PathSegment segment : path) {
if (segment.encoded) {
url.addEncodedPathSegments(segment.value);
} else {
url.addPathSegments(segment.value);
}
}

if (query != null) {
for (QueryParameter queryParam : query) {
url.addQueryParameter(queryParam.name, queryParam.value);
}
}

return url.build();
}

/**
Expand All @@ -836,7 +888,7 @@ public Method getMethod() {

@Override
public int hashCode() {
return (compiledRoute + method.toString()).hashCode();
return (getCompiledRoute() + method.toString()).hashCode();
}

@Override
Expand All @@ -847,15 +899,45 @@ public boolean equals(Object o) {

CompiledRoute oCompiled = (CompiledRoute) o;

return baseRoute.equals(oCompiled.getBaseRoute()) && compiledRoute.equals(oCompiled.compiledRoute);
return baseRoute.equals(oCompiled.getBaseRoute()) && path.equals(oCompiled.path);
}

@Override
public String toString() {
return new EntityString(this)
.setType(method)
.addMetadata("compiledRoute", compiledRoute)
.addMetadata("compiledRoute", getCompiledRoute())
.toString();
}
}

private static final class QueryParameter {
private final String name;
private final String value;

private QueryParameter(String name, String value) {
this.name = name;
this.value = value;
}

@Override
public String toString() {
return name + "=" + EncodingUtil.encodeUTF8(value);
}
}

private static final class PathSegment {
private final String value;
private final boolean encoded;

private PathSegment(String value, boolean encoded) {
this.value = value;
this.encoded = encoded;
}

@Override
public String toString() {
return encoded ? value : EncodingUtil.encodeUTF8(value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import net.dv8tion.jda.internal.utils.config.ThreadingConfig;
import net.dv8tion.jda.internal.utils.config.sharding.*;
import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;

Expand Down Expand Up @@ -734,7 +735,12 @@ public JDA getJDA() {
public okhttp3.Response execute() {
try {
RestConfig config = restConfigProvider.apply(0);
String url = config.getBaseUrl() + getRoute().getCompiledRoute();
HttpUrl baseUrl = HttpUrl.parse(config.getBaseUrl());
if (baseUrl == null) {
throw new IllegalArgumentException("Invalid base url: " + config.getBaseUrl());
}

HttpUrl url = getRoute().toHttpUrl(baseUrl);
LOG.debug("Requesting shard total with url {}", url);

okhttp3.Request.Builder builder = new okhttp3.Request.Builder()
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/net/dv8tion/jda/internal/requests/Requester.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.requests.*;
import net.dv8tion.jda.api.requests.Request;
import net.dv8tion.jda.api.requests.Response;
import net.dv8tion.jda.api.requests.Route;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.utils.IOUtil;
import net.dv8tion.jda.internal.utils.JDALogger;
import net.dv8tion.jda.internal.utils.config.AuthorizationConfig;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.MDC;

Expand Down Expand Up @@ -73,7 +73,7 @@ public class Requester {
protected final JDAImpl api;
protected final AuthorizationConfig authConfig;
private final RestRateLimiter rateLimiter;
private final String baseUrl;
private final HttpUrl baseUrl;
private final String userAgent;
private final Consumer<? super okhttp3.Request.Builder> customBuilder;

Expand All @@ -94,7 +94,11 @@ public Requester(JDA api, AuthorizationConfig authConfig, RestConfig config, Res
this.authConfig = authConfig;
this.api = (JDAImpl) api;
this.rateLimiter = rateLimiter;
this.baseUrl = config.getBaseUrl();
this.baseUrl = HttpUrl.parse(config.getBaseUrl());
if (this.baseUrl == null) {
throw new IllegalArgumentException("Provided base url was invalid! Provided: " + config.getBaseUrl());
}

this.userAgent = config.getUserAgent();
this.customBuilder = config.getCustomBuilder();
this.httpClient = this.api.getHttpClient();
Expand Down Expand Up @@ -161,7 +165,7 @@ public okhttp3.Response execute(WorkTask task, boolean retried, boolean handleOn

okhttp3.Request.Builder builder = new okhttp3.Request.Builder();

String url = baseUrl + route.getCompiledRoute();
HttpUrl url = route.toHttpUrl(baseUrl);
builder.url(url);

Request<?> apiRequest = task.request;
Expand Down
Loading
Loading