From 0a501429e6cb72e9873eba94c6060fac26bbe484 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 23 Dec 2021 12:36:05 -0500 Subject: [PATCH] Move okhttp client from http-api The client has been recreated with a new builder off of the http-api client for awhile anyway since runelite-client has multiple other requirements (caching, tls, etc). This fully moves creation of the okhttp client into both http-service and runelite-client separately. I've kept the CLIENT field in http-api for now since a few external plugins depend on it currently. --- http-api/pom.xml | 40 ------------- .../net/runelite/http/api/RuneLiteAPI.java | 57 +----------------- .../src/main/resources/runelite.properties | 3 - .../runelite/http/api/RuneLiteAPITest.java | 58 ------------------- http-service/pom.xml | 49 ++++++++++++++++ .../service/SpringBootWebApplication.java | 22 ++++++- .../http/service/account/AccountService.java | 5 +- .../src/main/resources/application.yaml | 3 + runelite-client/pom.xml | 26 +++++++++ .../java/net/runelite/client/RuneLite.java | 37 ++++++++---- .../runelite/client/RuneLiteProperties.java | 12 ++++ .../java/net/runelite/client/ws/WSClient.java | 4 +- .../net/runelite/client/runelite.properties | 2 + ...tpCacheSanityTest.java => OkHttpTest.java} | 23 ++++++-- 14 files changed, 162 insertions(+), 179 deletions(-) delete mode 100644 http-api/src/main/resources/runelite.properties delete mode 100644 http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java rename runelite-client/src/test/java/net/runelite/client/{OkHttpCacheSanityTest.java => OkHttpTest.java} (89%) diff --git a/http-api/pom.xml b/http-api/pom.xml index 49bb4a43f0..6f4e9a635e 100644 --- a/http-api/pom.xml +++ b/http-api/pom.xml @@ -34,11 +34,6 @@ Web API http-api - - nogit - false - - com.squareup.okhttp3 @@ -77,39 +72,4 @@ test - - - - - src/main/resources - true - - - - - pl.project13.maven - git-commit-id-plugin - 2.2.6 - - - query-git-info - - revision - - - false - false - - true - - - git.commit.id.abbrev - git.dirty - - - - - - - diff --git a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java index 99c699da51..2cec04c008 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -27,78 +27,25 @@ package net.runelite.http.api; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.awt.Color; -import java.io.IOException; -import java.io.InputStream; import java.time.Instant; -import java.util.Properties; -import java.util.concurrent.TimeUnit; -import lombok.Getter; import net.runelite.http.api.gson.ColorTypeAdapter; import net.runelite.http.api.gson.IllegalReflectionExclusion; import net.runelite.http.api.gson.InstantTypeAdapter; -import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class RuneLiteAPI { - private static final Logger logger = LoggerFactory.getLogger(RuneLiteAPI.class); - public static final String RUNELITE_AUTH = "RUNELITE-AUTH"; public static final String RUNELITE_MACHINEID = "RUNELITE-MACHINEID"; - public static final OkHttpClient CLIENT; + @Deprecated + public static OkHttpClient CLIENT; public static final Gson GSON; public static final MediaType JSON = MediaType.parse("application/json"); - public static String userAgent; - - private static final Properties properties = new Properties(); - @Getter - private static String version; static { - try - { - InputStream in = RuneLiteAPI.class.getResourceAsStream("/runelite.properties"); - properties.load(in); - - version = properties.getProperty("runelite.version"); - String commit = properties.getProperty("runelite.commit"); - boolean dirty = Boolean.parseBoolean(properties.getProperty("runelite.dirty")); - - userAgent = "RuneLite/" + version + "-" + commit + (dirty ? "+" : ""); - } - catch (NumberFormatException e) - { - throw new RuntimeException("Version string has not been substituted; Re-run maven"); - } - catch (IOException ex) - { - logger.error(null, ex); - } - - CLIENT = new OkHttpClient.Builder() - .pingInterval(30, TimeUnit.SECONDS) - .addNetworkInterceptor(new Interceptor() - { - - @Override - public Response intercept(Chain chain) throws IOException - { - Request userAgentRequest = chain.request() - .newBuilder() - .header("User-Agent", userAgent) - .build(); - return chain.proceed(userAgentRequest); - } - }) - .build(); - GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder diff --git a/http-api/src/main/resources/runelite.properties b/http-api/src/main/resources/runelite.properties deleted file mode 100644 index b912fac6ce..0000000000 --- a/http-api/src/main/resources/runelite.properties +++ /dev/null @@ -1,3 +0,0 @@ -runelite.version=${project.version} -runelite.commit=${git.commit.id.abbrev} -runelite.dirty=${git.dirty} \ No newline at end of file diff --git a/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java b/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java deleted file mode 100644 index d1fd3562bd..0000000000 --- a/http-api/src/test/java/net/runelite/http/api/RuneLiteAPITest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2018, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.api; - -import java.io.IOException; -import okhttp3.Request; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import static org.junit.Assert.assertTrue; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -public class RuneLiteAPITest -{ - @Rule - public final MockWebServer server = new MockWebServer(); - - @Before - public void before() throws IOException - { - server.enqueue(new MockResponse().setBody("OK")); - } - - @Test - public void testUserAgent() throws IOException, InterruptedException - { - Request request = new Request.Builder() - .url(server.url("/").url()) - .build(); - RuneLiteAPI.CLIENT.newCall(request).execute().close(); - - // rest of UA depends on if git is found - assertTrue(server.takeRequest().getHeader("User-Agent").startsWith("RuneLite/" + RuneLiteAPI.getVersion())); - } -} \ No newline at end of file diff --git a/http-service/pom.xml b/http-service/pom.xml index 15f6992c83..d983f9e9da 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -39,6 +39,8 @@ 1.5.6.RELEASE + nogit + false @@ -154,6 +156,13 @@ runelite-${project.version} + + + src/main/resources + true + + + org.apache.maven.plugins @@ -164,6 +173,10 @@ org.springframework.boot spring-boot-maven-plugin ${spring.boot.version} + + + false + com.github.kongchen @@ -215,6 +228,42 @@ + + pl.project13.maven + git-commit-id-plugin + 2.2.6 + + + query-git-info + + revision + + + false + false + + true + + + git.commit.id.abbrev + git.dirty + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + @ + + false + + diff --git a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java index 6d045b8231..4c425cb0cf 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.time.Instant; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.naming.NamingException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; @@ -39,10 +40,10 @@ import javax.servlet.ServletContextListener; import javax.servlet.ServletException; import javax.sql.DataSource; import lombok.extern.slf4j.Slf4j; -import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.service.util.InstantConverter; import okhttp3.Cache; import okhttp3.OkHttpClient; +import okhttp3.Request; import org.slf4j.ILoggerFactory; import org.slf4j.impl.StaticLoggerBinder; import org.springframework.beans.factory.annotation.Qualifier; @@ -200,9 +201,24 @@ public class SpringBootWebApplication extends SpringBootServletInitializer } @Bean - public OkHttpClient okHttpClient() + public OkHttpClient okHttpClient( + @Value("${runelite.version}") String version, + @Value("${runelite.commit}") String commit, + @Value("${runelite.dirty}") boolean dirty + ) { - return RuneLiteAPI.CLIENT; + final String userAgent = "RuneLite/" + version + "-" + commit + (dirty ? "+" : ""); + return new OkHttpClient.Builder() + .pingInterval(30, TimeUnit.SECONDS) + .addNetworkInterceptor(chain -> + { + Request userAgentRequest = chain.request() + .newBuilder() + .header("User-Agent", userAgent) + .build(); + return chain.proceed(userAgentRequest); + }) + .build(); } public static void main(String[] args) diff --git a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java index 4f39ed00e1..10a289b927 100644 --- a/http-service/src/main/java/net/runelite/http/service/account/AccountService.java +++ b/http-service/src/main/java/net/runelite/http/service/account/AccountService.java @@ -98,6 +98,7 @@ public class AccountService private final String oauthClientId; private final String oauthClientSecret; private final String oauthCallback; + private final String runeliteVersion; private final AuthFilter auth; private final RedisPool jedisPool; @@ -107,6 +108,7 @@ public class AccountService @Value("${oauth.client-id}") String oauthClientId, @Value("${oauth.client-secret}") String oauthClientSecret, @Value("${oauth.callback}") String oauthCallback, + @Value("${runelite.version}") String runeliteVersion, AuthFilter auth, RedisPool jedisPool ) @@ -115,6 +117,7 @@ public class AccountService this.oauthClientId = oauthClientId; this.oauthClientSecret = oauthClientSecret; this.oauthCallback = oauthCallback; + this.runeliteVersion = runeliteVersion; this.auth = auth; this.jedisPool = jedisPool; @@ -143,7 +146,7 @@ public class AccountService { State state = new State(); state.setUuid(uuid); - state.setApiVersion(RuneLiteAPI.getVersion()); + state.setApiVersion(runeliteVersion); OAuth20Service service = new ServiceBuilder() .apiKey(oauthClientId) diff --git a/http-service/src/main/resources/application.yaml b/http-service/src/main/resources/application.yaml index f77e17ae19..7431545cbb 100644 --- a/http-service/src/main/resources/application.yaml +++ b/http-service/src/main/resources/application.yaml @@ -33,6 +33,9 @@ mongo: database: runelite runelite: + version: @project.version@ + commit: @git.commit.id.abbrev@ + dirty: @git.dirty@ # Twitter client for feed twitter: consumerkey: diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index e2ee15124e..49b8425eeb 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -38,6 +38,8 @@ true true + nogit + false @@ -474,6 +476,30 @@ + + pl.project13.maven + git-commit-id-plugin + 2.2.6 + + + query-git-info + + revision + + + false + false + + true + + + git.commit.id.abbrev + git.dirty + + + + + diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 1d314f44ab..fad5c22eb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -44,6 +44,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.Locale; +import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import javax.annotation.Nullable; import javax.inject.Provider; @@ -80,6 +81,7 @@ import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay; import net.runelite.http.api.RuneLiteAPI; import okhttp3.Cache; import okhttp3.OkHttpClient; +import okhttp3.Request; import okhttp3.Response; import org.slf4j.LoggerFactory; @@ -97,6 +99,7 @@ public class RuneLite public static final File DEFAULT_CONFIG_FILE = new File(RUNELITE_DIR, "settings.properties"); private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb + public static String USER_AGENT = "RuneLite/" + RuneLiteProperties.getVersion() + "-" + RuneLiteProperties.getCommit() + (RuneLiteProperties.isDirty() ? "+" : ""); @Getter private static Injector injector; @@ -203,16 +206,8 @@ public class RuneLite } }); - OkHttpClient.Builder okHttpClientBuilder = RuneLiteAPI.CLIENT.newBuilder(); - setupCache(okHttpClientBuilder, new File(CACHE_DIR, "okhttp")); - - final boolean insecureSkipTlsVerification = options.has("insecure-skip-tls-verification"); - if (insecureSkipTlsVerification || RuneLiteProperties.isInsecureSkipTlsVerification()) - { - setupInsecureTrustManager(okHttpClientBuilder); - } - - final OkHttpClient okHttpClient = okHttpClientBuilder.build(); + final OkHttpClient okHttpClient = buildHttpClient(options.has("insecure-skip-tls-verification")); + RuneLiteAPI.CLIENT = okHttpClient; SplashScreen.init(); SplashScreen.stage(0, "Retrieving client", ""); @@ -416,9 +411,20 @@ public class RuneLite } @VisibleForTesting - static void setupCache(OkHttpClient.Builder builder, File cacheDir) + static OkHttpClient buildHttpClient(boolean insecureSkipTlsVerification) { - builder.cache(new Cache(cacheDir, MAX_OKHTTP_CACHE_SIZE)) + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .pingInterval(30, TimeUnit.SECONDS) + .addNetworkInterceptor(chain -> + { + Request userAgentRequest = chain.request() + .newBuilder() + .header("User-Agent", USER_AGENT) + .build(); + return chain.proceed(userAgentRequest); + }) + // Setup cache + .cache(new Cache(new File(CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE)) .addNetworkInterceptor(chain -> { // This has to be a network interceptor so it gets hit before the cache tries to store stuff @@ -432,6 +438,13 @@ public class RuneLite } return res; }); + + if (insecureSkipTlsVerification || RuneLiteProperties.isInsecureSkipTlsVerification()) + { + setupInsecureTrustManager(builder); + } + + return builder.build(); } private static void setupInsecureTrustManager(OkHttpClient.Builder okHttpClientBuilder) diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java index 1f878b26cc..e598439c2d 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java @@ -35,6 +35,8 @@ import okhttp3.HttpUrl; public class RuneLiteProperties { private static final String RUNELITE_VERSION = "runelite.version"; + private static final String RUNELITE_COMMIT = "runelite.commit"; + private static final String RUNELITE_DIRTY = "runelite.dirty"; private static final String DISCORD_INVITE = "runelite.discord.invite"; private static final String LAUNCHER_VERSION_PROPERTY = "runelite.launcher.version"; private static final String INSECURE_SKIP_TLS_VERIFICATION_PROPERTY = "runelite.insecure-skip-tls-verification"; @@ -67,6 +69,16 @@ public class RuneLiteProperties return properties.getProperty(RUNELITE_VERSION); } + public static String getCommit() + { + return properties.getProperty(RUNELITE_COMMIT); + } + + public static boolean isDirty() + { + return Boolean.parseBoolean(properties.getProperty(RUNELITE_DIRTY)); + } + public static String getDiscordInvite() { return properties.getProperty(DISCORD_INVITE); diff --git a/runelite-client/src/main/java/net/runelite/client/ws/WSClient.java b/runelite-client/src/main/java/net/runelite/client/ws/WSClient.java index 41ac088c7d..ea42605075 100644 --- a/runelite-client/src/main/java/net/runelite/client/ws/WSClient.java +++ b/runelite-client/src/main/java/net/runelite/client/ws/WSClient.java @@ -35,8 +35,8 @@ import javax.inject.Named; import javax.inject.Singleton; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLite; import net.runelite.client.eventbus.EventBus; -import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.ws.WebsocketGsonFactory; import net.runelite.http.api.ws.WebsocketMessage; import net.runelite.http.api.ws.messages.Handshake; @@ -106,7 +106,7 @@ public class WSClient extends WebSocketListener implements AutoCloseable Request request = new Request.Builder() .url(runeliteWs) - .header("User-Agent", RuneLiteAPI.userAgent) + .header("User-Agent", RuneLite.USER_AGENT) .build(); webSocket = okHttpClient.newWebSocket(request, this); diff --git a/runelite-client/src/main/resources/net/runelite/client/runelite.properties b/runelite-client/src/main/resources/net/runelite/client/runelite.properties index 50b70b6e83..8952e01593 100644 --- a/runelite-client/src/main/resources/net/runelite/client/runelite.properties +++ b/runelite-client/src/main/resources/net/runelite/client/runelite.properties @@ -1,5 +1,7 @@ runelite.title=RuneLite runelite.version=${project.version} +runelite.commit=${git.commit.id.abbrev} +runelite.dirty=${git.dirty} runelite.discord.appid=409416265891971072 runelite.discord.invite=https://discord.gg/ArdAhnN runelite.github.link=https://github.com/runelite diff --git a/runelite-client/src/test/java/net/runelite/client/OkHttpCacheSanityTest.java b/runelite-client/src/test/java/net/runelite/client/OkHttpTest.java similarity index 89% rename from runelite-client/src/test/java/net/runelite/client/OkHttpCacheSanityTest.java rename to runelite-client/src/test/java/net/runelite/client/OkHttpTest.java index 2478042ed2..83032c4e5c 100644 --- a/runelite-client/src/test/java/net/runelite/client/OkHttpCacheSanityTest.java +++ b/runelite-client/src/test/java/net/runelite/client/OkHttpTest.java @@ -30,7 +30,6 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.concurrent.TimeUnit; -import net.runelite.http.api.RuneLiteAPI; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; @@ -38,11 +37,12 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; import org.junit.Assert; +import static org.junit.Assert.assertTrue; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -public class OkHttpCacheSanityTest +public class OkHttpTest { @Rule public TemporaryFolder cacheFolder = new TemporaryFolder(); @@ -71,9 +71,7 @@ public class OkHttpCacheSanityTest @Test public void testCacheSanity() throws IOException, InterruptedException { - OkHttpClient.Builder builder = RuneLiteAPI.CLIENT.newBuilder(); - RuneLite.setupCache(builder, cacheFolder.getRoot()); - OkHttpClient client = builder.build(); + OkHttpClient client = RuneLite.buildHttpClient(false); Instant lastModified = Instant.now().minusSeconds(20); @@ -122,4 +120,19 @@ public class OkHttpCacheSanityTest Assert.assertNotNull("cache did not make a conditional request", req); Assert.assertNotNull(req.getHeader("If-Modified-Since")); } + + @Test + public void testUserAgent() throws IOException, InterruptedException + { + server.enqueue(new MockResponse().setBody("OK")); + + Request request = new Request.Builder() + .url(server.url("/")) + .build(); + RuneLite.buildHttpClient(false) + .newCall(request).execute().close(); + + // rest of UA depends on if git is found + assertTrue(server.takeRequest().getHeader("User-Agent").startsWith("RuneLite/" + RuneLiteProperties.getVersion())); + } }