Add support for more HTTP request types and request headers

This commit is contained in:
Arjan Schrijver
2025-12-25 14:45:08 +01:00
committed by Arjan Schrijver
parent b950e91c4d
commit 82fe173706
9 changed files with 137 additions and 78 deletions
@@ -1,3 +0,0 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
parcelable HttpPostRequest;
@@ -1,3 +1,3 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
parcelable HttpGetRequest;
parcelable HttpRequest;
@@ -1,11 +1,10 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpGetRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpPostRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpCallback;
interface IHttpService {
int version();
void get(in HttpGetRequest request, IHttpCallback cb);
void get(in HttpRequest request, IHttpCallback cb);
}
@@ -27,8 +27,8 @@ import android.os.ParcelFileDescriptor
import android.os.RemoteException
import android.webkit.WebResourceResponse
import nodomain.freeyourgadget.gadgetbridge.GBApplication
import nodomain.freeyourgadget.internethelper.aidl.http.HttpGetRequest
import nodomain.freeyourgadget.internethelper.aidl.http.HttpHeaders
import nodomain.freeyourgadget.internethelper.aidl.http.HttpRequest
import nodomain.freeyourgadget.internethelper.aidl.http.HttpResponse
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpCallback
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpService
@@ -86,12 +86,19 @@ object InternetHelperSingleton {
}
@Throws(RemoteException::class, InterruptedException::class)
fun send(webRequest: Uri, allowInsecure: Boolean): WebResourceResponse? {
fun send(
webRequest: Uri,
method: HttpRequest.Method,
requestHeaders: Map<String, String>,
body: String?,
bodyContentType: String,
allowInsecure: Boolean,
): WebResourceResponse? {
val latch = CountDownLatch(1)
var result: WebResourceResponse? = null
val request = HttpGetRequest(webRequest.toString(), allowInsecure, HttpHeaders())
val request = HttpRequest(webRequest.toString(), method, body, bodyContentType, allowInsecure, HttpHeaders(requestHeaders))
LOG.debug("Forwarding GET request to {} to internet helper app", webRequest)
LOG.debug("Forwarding {} request to {} to internet helper app", method.name, webRequest)
try {
internetHelper?.get(request, object : IHttpCallback.Stub() {
override fun onResponse(response: HttpResponse) {
@@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.util
import android.net.Uri
import android.webkit.WebResourceResponse
import nodomain.freeyourgadget.gadgetbridge.GBApplication
import nodomain.freeyourgadget.internethelper.aidl.http.HttpRequest
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
@@ -57,7 +58,14 @@ class InternetUtils {
val response: WebResourceResponse? = if (GBApplication.hasDirectInternetAccess()) {
directRequest(uri, method, requestHeaders, body, bodyContentType, allowInsecure)
} else {
InternetHelperSingleton.send(uri, allowInsecure)
InternetHelperSingleton.send(
uri,
HttpRequest.Method.valueOf(method),
requestHeaders,
body,
bodyContentType,
allowInsecure,
)
}
if (response == null) return null
@@ -104,7 +112,14 @@ class InternetUtils {
allowInsecure = false
)
} else {
InternetHelperSingleton.send(uri, false)
InternetHelperSingleton.send(
uri,
HttpRequest.Method.GET,
requestHeaders = emptyMap(),
null,
"application/octet-stream",
false
)
}
response?.data?.use { input ->
@@ -48,6 +48,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.weather.Weather;
import nodomain.freeyourgadget.gadgetbridge.model.weather.WeatherMapper;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.InternetHelperSingleton;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpRequest;
public class GBWebClient extends WebViewClient {
private static final Logger LOG = LoggerFactory.getLogger(GBWebClient.class);
@@ -72,8 +73,8 @@ public class GBWebClient extends WebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Uri parsedUri = request.getUrl();
LOG.debug("WEBVIEW shouldInterceptRequest URL: {}", parsedUri.toString());
WebResourceResponse mimickedReply = mimicReply(parsedUri);
LOG.debug("WEBVIEW shouldInterceptRequest URL: {} (method {})", parsedUri.toString(), request.getMethod());
WebResourceResponse mimickedReply = mimicReply(parsedUri, request.getMethod(), request.getRequestHeaders());
if (mimickedReply != null)
return mimickedReply;
return super.shouldInterceptRequest(view, request);
@@ -83,13 +84,13 @@ public class GBWebClient extends WebViewClient {
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
LOG.debug("WEBVIEW shouldInterceptRequest URL (legacy): {}", url);
Uri parsedUri = Uri.parse(url);
WebResourceResponse mimickedReply = mimicReply(parsedUri);
WebResourceResponse mimickedReply = mimicReply(parsedUri, "GET", new HashMap<>());
if (mimickedReply != null)
return mimickedReply;
return super.shouldInterceptRequest(view, url);
}
private WebResourceResponse mimicReply(Uri requestedUri) {
private WebResourceResponse mimicReply(Uri requestedUri, String method, Map<String, String> requestHeaders) {
GBPrefs prefs = GBApplication.getPrefs();
boolean locallySupported = StringUtils.indexOfAny(requestedUri.getHost(), LocallySupportedDomains) != -1;
boolean urlIsAllowed = locallySupported;
@@ -134,7 +135,7 @@ public class GBWebClient extends WebViewClient {
if (!forceLocal && !directInternetAccess && InternetHelperSingleton.INSTANCE.ensureInternetHelperBound()) {
LOG.debug("WEBVIEW forwarding request to the internet helper");
try {
WebResourceResponse wrr = InternetHelperSingleton.INSTANCE.send(requestedUri, false);
WebResourceResponse wrr = InternetHelperSingleton.INSTANCE.send(requestedUri, HttpRequest.Method.valueOf(method), requestHeaders, null, "application/octet-stream", false);
if (wrr != null && wrr.getStatusCode() < 400)
return wrr;
else
@@ -1,60 +0,0 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class HttpGetRequest implements Parcelable {
private final String url;
private final boolean allowInsecure;
private final HttpHeaders headers;
protected HttpGetRequest(final Parcel in) {
url = in.readString();
allowInsecure = in.readByte() != 0; // readBoolean() requires API level 29
headers = in.readParcelable(HttpGetRequest.class.getClassLoader());
}
public HttpGetRequest(String url, boolean allowInsecure, HttpHeaders headers) {
this.url = url;
this.allowInsecure = allowInsecure;
this.headers = headers;
}
public static final Creator<HttpGetRequest> CREATOR = new Creator<>() {
@Override
public HttpGetRequest createFromParcel(final Parcel in) {
return new HttpGetRequest(in);
}
@Override
public HttpGetRequest[] newArray(final int size) {
return new HttpGetRequest[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeString(url);
dest.writeByte((byte) (allowInsecure ? 1 : 0)); // writeBoolean() requires API level 29
dest.writeParcelable(headers, 0);
}
public String getUrl() {
return url;
}
public boolean getAllowInsecure() {
return allowInsecure;
}
public HttpHeaders getHeaders() {
return headers;
}
}
@@ -23,6 +23,12 @@ public class HttpHeaders implements Parcelable {
}
}
public HttpHeaders(Map<String, String> headersMap) {
for (String key : headersMap.keySet()) {
headers.add(new Pair<>(key, headersMap.get(key)));
}
}
public HttpHeaders() {
}
@@ -0,0 +1,94 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class HttpRequest implements Parcelable {
public enum Method {
GET,
POST,
HEAD,
PUT,
PATCH,
DELETE,
OPTIONS,
}
private final String url;
private final Method method;
private final String body;
private final String bodyContentType;
private final boolean allowInsecure;
private final HttpHeaders headers;
protected HttpRequest(final Parcel in) {
url = in.readString();
method = Method.values()[in.readInt()];
body = in.readString();
bodyContentType = in.readString();
allowInsecure = in.readByte() != 0; // readBoolean() requires API level 29
headers = in.readParcelable(HttpRequest.class.getClassLoader());
}
public HttpRequest(String url, Method method, String body, String bodyContentType, boolean allowInsecure, HttpHeaders headers) {
this.url = url;
this.method = method;
this.body = body;
this.bodyContentType = bodyContentType;
this.allowInsecure = allowInsecure;
this.headers = headers;
}
public static final Creator<HttpRequest> CREATOR = new Creator<>() {
@Override
public HttpRequest createFromParcel(final Parcel in) {
return new HttpRequest(in);
}
@Override
public HttpRequest[] newArray(final int size) {
return new HttpRequest[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeString(url);
dest.writeInt(method.ordinal());
dest.writeString(body);
dest.writeString(bodyContentType);
dest.writeByte((byte) (allowInsecure ? 1 : 0)); // writeBoolean() requires API level 29
dest.writeParcelable(headers, 0);
}
public String getUrl() {
return url;
}
public Method getMethod() {
return method;
}
public String getBody() {
return body;
}
public String getBodyContentType() {
return bodyContentType;
}
public boolean getAllowInsecure() {
return allowInsecure;
}
public HttpHeaders getHeaders() {
return headers;
}
}