Fixed proxy support

This commit is contained in:
ByteHamster 2021-05-09 18:00:21 +02:00
parent d08a9c423e
commit e521b85070
2 changed files with 47 additions and 67 deletions

View File

@ -30,8 +30,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.service.download.ProxyConfig; import de.danoeh.antennapod.core.service.download.ProxyConfig;
import io.reactivex.Single; import io.reactivex.Completable;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
@ -41,9 +40,6 @@ import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
public class ProxyDialog { public class ProxyDialog {
private static final String TAG = "ProxyDialog";
private final Context context; private final Context context;
private AlertDialog dialog; private AlertDialog dialog;
@ -116,32 +112,32 @@ public class ProxyDialog {
types.add(Proxy.Type.SOCKS.name()); types.add(Proxy.Type.SOCKS.name());
} }
ArrayAdapter<String> adapter = new ArrayAdapter<>(context, ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, types); android.R.layout.simple_spinner_item, types);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spType.setAdapter(adapter); spType.setAdapter(adapter);
ProxyConfig proxyConfig = UserPreferences.getProxyConfig(); ProxyConfig proxyConfig = UserPreferences.getProxyConfig();
spType.setSelection(adapter.getPosition(proxyConfig.type.name())); spType.setSelection(adapter.getPosition(proxyConfig.type.name()));
etHost = content.findViewById(R.id.etHost); etHost = content.findViewById(R.id.etHost);
if(!TextUtils.isEmpty(proxyConfig.host)) { if (!TextUtils.isEmpty(proxyConfig.host)) {
etHost.setText(proxyConfig.host); etHost.setText(proxyConfig.host);
} }
etHost.addTextChangedListener(requireTestOnChange); etHost.addTextChangedListener(requireTestOnChange);
etPort = content.findViewById(R.id.etPort); etPort = content.findViewById(R.id.etPort);
if(proxyConfig.port > 0) { if (proxyConfig.port > 0) {
etPort.setText(String.valueOf(proxyConfig.port)); etPort.setText(String.valueOf(proxyConfig.port));
} }
etPort.addTextChangedListener(requireTestOnChange); etPort.addTextChangedListener(requireTestOnChange);
etUsername = content.findViewById(R.id.etUsername); etUsername = content.findViewById(R.id.etUsername);
if(!TextUtils.isEmpty(proxyConfig.username)) { if (!TextUtils.isEmpty(proxyConfig.username)) {
etUsername.setText(proxyConfig.username); etUsername.setText(proxyConfig.username);
} }
etUsername.addTextChangedListener(requireTestOnChange); etUsername.addTextChangedListener(requireTestOnChange);
etPassword = content.findViewById(R.id.etPassword); etPassword = content.findViewById(R.id.etPassword);
if(!TextUtils.isEmpty(proxyConfig.password)) { if (!TextUtils.isEmpty(proxyConfig.password)) {
etPassword.setText(proxyConfig.username); etPassword.setText(proxyConfig.password);
} }
etPassword.addTextChangedListener(requireTestOnChange); etPassword.addTextChangedListener(requireTestOnChange);
if(proxyConfig.type == Proxy.Type.DIRECT) { if (proxyConfig.type == Proxy.Type.DIRECT) {
enableSettings(false); enableSettings(false);
setTestRequired(false); setTestRequired(false);
} }
@ -184,8 +180,8 @@ public class ProxyDialog {
private boolean checkValidity() { private boolean checkValidity() {
boolean valid = true; boolean valid = true;
if(spType.getSelectedItemPosition() > 0) { if (spType.getSelectedItemPosition() > 0) {
valid &= checkHost(); valid = checkHost();
} }
valid &= checkPort(); valid &= checkPort();
return valid; return valid;
@ -193,11 +189,11 @@ public class ProxyDialog {
private boolean checkHost() { private boolean checkHost() {
String host = etHost.getText().toString(); String host = etHost.getText().toString();
if(host.length() == 0) { if (host.length() == 0) {
etHost.setError(context.getString(R.string.proxy_host_empty_error)); etHost.setError(context.getString(R.string.proxy_host_empty_error));
return false; return false;
} }
if(!"localhost".equals(host) && !Patterns.DOMAIN_NAME.matcher(host).matches()) { if (!"localhost".equals(host) && !Patterns.DOMAIN_NAME.matcher(host).matches()) {
etHost.setError(context.getString(R.string.proxy_host_invalid_error)); etHost.setError(context.getString(R.string.proxy_host_invalid_error));
return false; return false;
} }
@ -215,10 +211,10 @@ public class ProxyDialog {
private int getPort() { private int getPort() {
String port = etPort.getText().toString(); String port = etPort.getText().toString();
if(port.length() > 0) { if (port.length() > 0) {
try { try {
return Integer.parseInt(port); return Integer.parseInt(port);
} catch(NumberFormatException e) { } catch (NumberFormatException e) {
// ignore // ignore
} }
} }
@ -226,7 +222,7 @@ public class ProxyDialog {
} }
private void setTestRequired(boolean required) { private void setTestRequired(boolean required) {
if(required) { if (required) {
testSuccessful = false; testSuccessful = false;
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.proxy_test_label); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.proxy_test_label);
} else { } else {
@ -240,7 +236,7 @@ public class ProxyDialog {
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
if(!checkValidity()) { if (!checkValidity()) {
setTestRequired(true); setTestRequired(true);
return; return;
} }
@ -251,7 +247,7 @@ public class ProxyDialog {
txtvMessage.setTextColor(textColorPrimary); txtvMessage.setTextColor(textColorPrimary);
txtvMessage.setText("{fa-circle-o-notch spin} " + checking); txtvMessage.setText("{fa-circle-o-notch spin} " + checking);
txtvMessage.setVisibility(View.VISIBLE); txtvMessage.setVisibility(View.VISIBLE);
disposable = Single.create((SingleOnSubscribe<Response>) emitter -> { disposable = Completable.create(emitter -> {
String type = (String) spType.getSelectedItem(); String type = (String) spType.getSelectedItem();
String host = etHost.getText().toString(); String host = etHost.getText().toString();
String port = etPort.getText().toString(); String port = etPort.getText().toString();
@ -263,59 +259,44 @@ public class ProxyDialog {
} }
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue); SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase(Locale.US)); Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase(Locale.US));
Proxy proxy = new Proxy(proxyType, address);
OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder() OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS) .connectTimeout(10, TimeUnit.SECONDS)
.proxy(proxy); .proxy(new Proxy(proxyType, address));
builder.interceptors().clear();
OkHttpClient client = builder.build();
if (!TextUtils.isEmpty(username)) { if (!TextUtils.isEmpty(username)) {
String credentials = Credentials.basic(username, password); builder.proxyAuthenticator((route, response) -> {
client.interceptors().add(chain -> { String credentials = Credentials.basic(username, password);
Request request = chain.request().newBuilder() return response.request().newBuilder()
.header("Proxy-Authorization", credentials).build(); .header("Proxy-Authorization", credentials)
return chain.proceed(request); .build();
}); });
} }
Request request = new Request.Builder() OkHttpClient client = builder.build();
.url("http://www.google.com") Request request = new Request.Builder().url("https://www.example.com").head().build();
.head() try (Response response = client.newCall(request).execute()) {
.build(); if (response.isSuccessful()) {
try { emitter.onComplete();
Response response = client.newCall(request).execute(); } else {
emitter.onSuccess(response); emitter.onError(new IOException(response.message()));
} catch(IOException e) { }
} catch (IOException e) {
emitter.onError(e); emitter.onError(e);
} }
}) })
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
response -> { () -> {
int colorId; txtvMessage.setTextColor(ContextCompat.getColor(context, R.color.download_success_green));
String icon; String message = String.format("%s %s", "{fa-check}",
String result; context.getString(R.string.proxy_test_successful));
if(response.isSuccessful()) {
colorId = R.color.download_success_green;
icon = "{fa-check}";
result = context.getString(R.string.proxy_test_successful);
} else {
colorId = R.color.download_failed_red;
icon = "{fa-close}";
result = context.getString(R.string.proxy_test_failed);
}
int color = ContextCompat.getColor(context, colorId);
txtvMessage.setTextColor(color);
String message = String.format("%s %s: %s", icon, result, response.message());
txtvMessage.setText(message); txtvMessage.setText(message);
setTestRequired(!response.isSuccessful()); setTestRequired(false);
}, },
error -> { error -> {
String icon = "{fa-close}"; error.printStackTrace();
String result = context.getString(R.string.proxy_test_failed); txtvMessage.setTextColor(ContextCompat.getColor(context, R.color.download_failed_red));
int color = ContextCompat.getColor(context, R.color.download_failed_red); String message = String.format("%s %s: %s", "{fa-close}",
txtvMessage.setTextColor(color); context.getString(R.string.proxy_test_failed), error.getMessage());
String message = String.format("%s %s: %s", icon, result, error.getMessage());
txtvMessage.setText(message); txtvMessage.setText(message);
setTestRequired(true); setTestRequired(true);
} }

View File

@ -118,14 +118,13 @@ public class AntennapodHttpClient {
if (config.type != Proxy.Type.DIRECT) { if (config.type != Proxy.Type.DIRECT) {
int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT; int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT;
SocketAddress address = InetSocketAddress.createUnresolved(config.host, port); SocketAddress address = InetSocketAddress.createUnresolved(config.host, port);
Proxy proxy = new Proxy(config.type, address); builder.proxy(new Proxy(config.type, address));
builder.proxy(proxy);
if (!TextUtils.isEmpty(config.username) && config.password != null) { if (!TextUtils.isEmpty(config.username) && config.password != null) {
String credentials = Credentials.basic(config.username, config.password); builder.proxyAuthenticator((route, response) -> {
builder.interceptors().add(chain -> { String credentials = Credentials.basic(config.username, config.password);
Request request = chain.request().newBuilder() return response.request().newBuilder()
.header("Proxy-Authorization", credentials).build(); .header("Proxy-Authorization", credentials)
return chain.proceed(request); .build();
}); });
} }
} }