From dec8ca1f685c151853ea2a474244b6aca26fd662 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Tue, 13 Jul 2021 13:48:40 -0400 Subject: [PATCH] Add proxy support --- .../ca/gosyer/data/server/HttpClient.kt | 23 +++++++++- .../gosyer/data/server/ServerPreferences.kt | 21 ++++++++++ .../ca/gosyer/data/server/model/Proxy.kt | 16 +++++++ .../ui/settings/SettingsServerScreen.kt | 42 ++++++++++++++++++- src/main/resources/values/values/strings.xml | 6 +++ 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt diff --git a/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt b/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt index 39387edf..d029e9fc 100644 --- a/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt +++ b/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt @@ -7,22 +7,43 @@ package ca.gosyer.data.server import ca.gosyer.BuildConfig +import ca.gosyer.data.server.model.Proxy import io.ktor.client.HttpClient +import io.ktor.client.engine.ProxyBuilder +import io.ktor.client.engine.ProxyConfig import io.ktor.client.engine.okhttp.OkHttp import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.serializer.KotlinxSerializer import io.ktor.client.features.logging.LogLevel import io.ktor.client.features.logging.Logging import io.ktor.client.features.websocket.WebSockets +import io.ktor.http.URLBuilder import kotlinx.serialization.json.Json import javax.inject.Inject import javax.inject.Provider typealias Http = HttpClient -internal class HttpProvider @Inject constructor() : Provider { +internal class HttpProvider @Inject constructor( + private val serverPreferences: ServerPreferences +) : Provider { override fun get(): Http { return HttpClient(OkHttp) { + engine { + proxy = when (serverPreferences.proxy().get()) { + Proxy.NO_PROXY -> ProxyConfig.NO_PROXY + Proxy.HTTP_PROXY -> ProxyBuilder.http( + URLBuilder( + host = serverPreferences.proxyHttpHost().get(), + port = serverPreferences.proxyHttpPort().get() + ).build() + ) + Proxy.SOCKS_PROXY -> ProxyBuilder.socks( + serverPreferences.proxySocksHost().get(), + serverPreferences.proxySocksPort().get() + ) + } + } install(JsonFeature) { serializer = KotlinxSerializer( Json { diff --git a/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt b/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt index b3ed7922..ad713380 100644 --- a/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt +++ b/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt @@ -8,6 +8,7 @@ package ca.gosyer.data.server import ca.gosyer.common.prefs.Preference import ca.gosyer.common.prefs.PreferenceStore +import ca.gosyer.data.server.model.Proxy class ServerPreferences(private val preferenceStore: PreferenceStore) { @@ -26,4 +27,24 @@ class ServerPreferences(private val preferenceStore: PreferenceStore) { fun serverUrl(): Preference { return ServerUrlPreference("", server(), port()) } + + fun proxy(): Preference { + return preferenceStore.getJsonObject("proxy", Proxy.NO_PROXY, Proxy.serializer()) + } + + fun proxyHttpHost(): Preference { + return preferenceStore.getString("proxy_http_host") + } + + fun proxyHttpPort(): Preference { + return preferenceStore.getInt("proxy_http_port") + } + + fun proxySocksHost(): Preference { + return preferenceStore.getString("proxy_socks_host") + } + + fun proxySocksPort(): Preference { + return preferenceStore.getInt("proxy_socks_port") + } } diff --git a/src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt b/src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt new file mode 100644 index 00000000..e7effd76 --- /dev/null +++ b/src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt @@ -0,0 +1,16 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package ca.gosyer.data.server.model + +import kotlinx.serialization.Serializable + +@Serializable +enum class Proxy { + NO_PROXY, + HTTP_PROXY, + SOCKS_PROXY +} diff --git a/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt b/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt index 368fcd40..25db54ab 100644 --- a/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt +++ b/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt @@ -10,8 +10,11 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import ca.gosyer.data.server.ServerPreferences +import ca.gosyer.data.server.model.Proxy import ca.gosyer.ui.base.components.Toolbar +import ca.gosyer.ui.base.prefs.ChoicePreference import ca.gosyer.ui.base.prefs.EditTextPreference import ca.gosyer.ui.base.prefs.SwitchPreference import ca.gosyer.ui.base.prefs.asStateIn @@ -24,16 +27,31 @@ import com.github.zsoltk.compose.router.BackStack import javax.inject.Inject class SettingsServerViewModel @Inject constructor( - private val serverPreferences: ServerPreferences + serverPreferences: ServerPreferences ) : ViewModel() { val host = serverPreferences.host().asStateIn(scope) val server = serverPreferences.server().asStateIn(scope) val port = serverPreferences.port().asStringStateIn(scope) + + val proxy = serverPreferences.proxy().asStateIn(scope) + + @Composable + fun getProxyChoices() = mapOf( + Proxy.NO_PROXY to stringResource("no_proxy"), + Proxy.HTTP_PROXY to stringResource("http_proxy"), + Proxy.SOCKS_PROXY to stringResource("socks_proxy") + ) + + val httpHost = serverPreferences.proxyHttpHost().asStateIn(scope) + val httpPort = serverPreferences.proxyHttpPort().asStringStateIn(scope) + val socksHost = serverPreferences.proxySocksHost().asStateIn(scope) + val socksPort = serverPreferences.proxySocksPort().asStringStateIn(scope) } @Composable fun SettingsServerScreen(navController: BackStack) { val vm = viewModel() + val proxy by vm.proxy.collectAsState() Column { Toolbar(stringResource("settings_server_screen"), navController, true) SwitchPreference(preference = vm.host, title = stringResource("host_server")) @@ -44,6 +62,28 @@ fun SettingsServerScreen(navController: BackStack) { item { EditTextPreference(vm.port, stringResource("server_port"), subtitle = vm.port.collectAsState().value) } + item { + ChoicePreference(vm.proxy, vm.getProxyChoices(), stringResource("server_proxy")) + } + when (proxy) { + Proxy.NO_PROXY -> Unit + Proxy.HTTP_PROXY -> { + item { + EditTextPreference(vm.httpHost, stringResource("http_proxy"), vm.httpHost.collectAsState().value) + } + item { + EditTextPreference(vm.httpPort, stringResource("http_port"), vm.httpPort.collectAsState().value) + } + } + Proxy.SOCKS_PROXY -> { + item { + EditTextPreference(vm.socksHost, stringResource("socks_proxy"), vm.socksHost.collectAsState().value) + } + item { + EditTextPreference(vm.socksPort, stringResource("socks_port"), vm.socksPort.collectAsState().value) + } + } + } } } } diff --git a/src/main/resources/values/values/strings.xml b/src/main/resources/values/values/strings.xml index a004d090..a4d78bad 100644 --- a/src/main/resources/values/values/strings.xml +++ b/src/main/resources/values/values/strings.xml @@ -170,4 +170,10 @@ Host server inside TachideskJUI Server URL Server PORT + No Proxy + HTTP Proxy + SOCKS Proxy + Proxy access to the server + HTTP PORT + SOCKS PORT \ No newline at end of file