POST fix.

This commit is contained in:
Koen 2024-01-21 18:37:02 +01:00
commit 816d3c58f2
10 changed files with 70 additions and 36 deletions

View file

@ -243,7 +243,9 @@ declare class DashSource implements IVideoSource {
declare interface IRequest { declare interface IRequest {
url: string, url: string,
headers: Map<string, string> headers: Map<string, string>,
method: string,
body?: string
} }
declare interface IRequestModifierDef { declare interface IRequestModifierDef {
allowByteSkip: boolean allowByteSkip: boolean
@ -251,7 +253,7 @@ declare interface IRequestModifierDef {
declare class RequestModifier { declare class RequestModifier {
constructor(obj: IRequestModifierDef) { } constructor(obj: IRequestModifierDef) { }
modifyRequest(url: string, headers: Map<string, string>): IRequest; modifyRequest(url: string, headers: Map<string, string>, method: string, body?: string): IRequest;
} }
//Channel //Channel

View file

@ -1,4 +1,4 @@
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.datasource.HttpDataSource import androidx.media3.datasource.HttpDataSource

View file

@ -1,14 +1,14 @@
package com.futo.platformplayer.api.media.models.modifier package com.futo.platformplayer.api.media.models.modifier
class AdhocRequestModifier: IRequestModifier { class AdhocRequestModifier: IRequestModifier {
val _handler: (String, Map<String,String>)->IRequest; val _handler: (String, Map<String,String>, String, String?)->IRequest;
override var allowByteSkip: Boolean = false; override var allowByteSkip: Boolean = false;
constructor(modifyReq: (String, Map<String,String>)->IRequest) { constructor(modifyReq: (String, Map<String,String>, String, String?)->IRequest) {
_handler = modifyReq; _handler = modifyReq;
} }
override fun modifyRequest(url: String, headers: Map<String, String>): IRequest { override fun modifyRequest(url: String, headers: Map<String, String>, method: String, body: String?): IRequest {
return _handler(url, headers); return _handler(url, headers, method, body);
} }
} }

View file

@ -1,6 +1,8 @@
package com.futo.platformplayer.api.media.models.modifier package com.futo.platformplayer.api.media.models.modifier
interface IRequest { interface IRequest {
val method: String?;
val url: String?; val url: String?;
val headers: Map<String, String>; val headers: Map<String, String>?;
val body: String?;
} }

View file

@ -3,5 +3,5 @@ package com.futo.platformplayer.api.media.models.modifier
interface IRequestModifier { interface IRequestModifier {
var allowByteSkip: Boolean; var allowByteSkip: Boolean;
fun modifyRequest(url: String, headers: Map<String, String>): IRequest fun modifyRequest(url: String, headers: Map<String, String>, method: String, body: String?): IRequest
} }

View file

@ -12,31 +12,40 @@ import com.futo.platformplayer.getOrDefault
class JSRequest : IRequest { class JSRequest : IRequest {
private val _v8Url: String?; private val _v8Url: String?;
private val _v8Headers: Map<String, String>?; private val _v8Headers: Map<String, String>?;
private val _v8Method: String?;
private val _v8Body: String?;
private val _v8Options: Options?; private val _v8Options: Options?;
override var url: String? = null; override var url: String? = null;
override lateinit var headers: Map<String, String>; override lateinit var headers: Map<String, String>;
override var method: String? = null;
override var body: String? = null;
constructor(plugin: JSClient, url: String?, headers: Map<String, String>?, options: Options?, originalUrl: String?, originalHeaders: Map<String, String>?) { constructor(plugin: JSClient, url: String?, headers: Map<String, String>?, method: String?, body: String?, options: Options?, originalUrl: String?, originalHeaders: Map<String, String>?, originalMethod: String?, originalBody: String?) {
_v8Url = url; _v8Url = url;
_v8Headers = headers; _v8Headers = headers;
_v8Method = method;
_v8Body = body;
_v8Options = options; _v8Options = options;
initialize(plugin, originalUrl, originalHeaders); initialize(plugin, originalUrl, originalHeaders, originalMethod, originalBody);
} }
constructor(plugin: JSClient, obj: V8ValueObject, originalUrl: String?, originalHeaders: Map<String, String>?, applyOtherHeadersByDefault: Boolean = false) { constructor(plugin: JSClient, obj: V8ValueObject, originalUrl: String?, originalHeaders: Map<String, String>?, originalMethod: String?, originalBody: String?, applyOtherHeadersByDefault: Boolean = false) {
val contextName = "ModifyRequestResponse"; val contextName = "ModifyRequestResponse";
val config = plugin.config; val config = plugin.config;
_v8Url = obj.getOrDefault<String>(config, "url", contextName, null); _v8Url = obj.getOrDefault<String>(config, "url", contextName, null);
_v8Headers = obj.getOrDefault<Map<String, String>>(config, "headers", contextName, null); _v8Headers = obj.getOrDefault<Map<String, String>>(config, "headers", contextName, null);
_v8Method = obj.getOrDefault<String>(config, "method", contextName, null);
_v8Body = obj.getOrDefault<String>(config, "body", contextName, null);
_v8Options = obj.getOrDefault<V8ValueObject>(config, "options", "JSRequestModifier.options", null)?.let { _v8Options = obj.getOrDefault<V8ValueObject>(config, "options", "JSRequestModifier.options", null)?.let {
Options(config, it, applyOtherHeadersByDefault); Options(config, it, applyOtherHeadersByDefault);
} ?: Options(null, null, applyOtherHeadersByDefault); } ?: Options(null, null, applyOtherHeadersByDefault);
initialize(plugin, originalUrl, originalHeaders); initialize(plugin, originalUrl, originalHeaders, originalMethod, originalBody);
} }
private fun initialize(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?) { private fun initialize(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?, originalMethod: String?, originalBody: String?) {
val config = plugin.config;
url = _v8Url ?: originalUrl; url = _v8Url ?: originalUrl;
method = _v8Method ?: originalMethod;
body = _v8Body ?: originalBody;
if(_v8Options?.applyOtherHeaders ?: false) { if(_v8Options?.applyOtherHeaders ?: false) {
val headersToSet = _v8Headers?.toMutableMap() ?: mutableMapOf(); val headersToSet = _v8Headers?.toMutableMap() ?: mutableMapOf();
@ -69,8 +78,8 @@ class JSRequest : IRequest {
} }
} }
fun modify(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?): JSRequest { fun modify(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?, originalMethod: String?, originalBody: String?): JSRequest {
return JSRequest(plugin, _v8Url, _v8Headers, _v8Options, originalUrl, originalHeaders); return JSRequest(plugin, _v8Url, _v8Headers, _v8Method, _v8Body, _v8Options, originalUrl, originalHeaders, originalMethod, originalBody);
} }

View file

@ -1,6 +1,5 @@
package com.futo.platformplayer.api.media.platforms.js.models package com.futo.platformplayer.api.media.platforms.js.models
import android.net.Uri
import com.caoccao.javet.values.reference.V8ValueObject import com.caoccao.javet.values.reference.V8ValueObject
import com.futo.platformplayer.api.media.models.modifier.IRequest import com.futo.platformplayer.api.media.models.modifier.IRequest
import com.futo.platformplayer.api.media.models.modifier.IRequestModifier import com.futo.platformplayer.api.media.models.modifier.IRequestModifier
@ -8,9 +7,7 @@ import com.futo.platformplayer.api.media.platforms.js.JSClient
import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.IV8PluginConfig
import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.V8Plugin
import com.futo.platformplayer.engine.exceptions.ScriptImplementationException import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
import com.futo.platformplayer.getOrDefault
import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrNull
import com.futo.platformplayer.getOrThrow
class JSRequestModifier: IRequestModifier { class JSRequestModifier: IRequestModifier {
private val _plugin: JSClient; private val _plugin: JSClient;
@ -30,20 +27,20 @@ class JSRequestModifier: IRequestModifier {
throw ScriptImplementationException(config, "RequestModifier is missing modifyRequest", null); throw ScriptImplementationException(config, "RequestModifier is missing modifyRequest", null);
} }
override fun modifyRequest(url: String, headers: Map<String, String>): IRequest { override fun modifyRequest(url: String, headers: Map<String, String>, method: String, body: String?): IRequest {
if (_modifier.isClosed) { if (_modifier.isClosed) {
return Request(url, headers); return Request(url, headers, method, body);
} }
val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSRequestModifier", "builder.modifyRequest()") { val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSRequestModifier", "builder.modifyRequest()") {
_modifier.invoke("modifyRequest", url, headers); _modifier.invoke("modifyRequest", url, headers, method, body);
} as V8ValueObject; } as V8ValueObject;
val req = JSRequest(_plugin, result, url, headers); val req = JSRequest(_plugin, result, url, headers, method, body);
result.close(); result.close();
return req; return req;
} }
data class Request(override val url: String, override val headers: Map<String, String>) : IRequest; data class Request(override val url: String, override val headers: Map<String, String>, override val method: String, override val body: String?) : IRequest;
} }

View file

@ -1,7 +1,5 @@
package com.futo.platformplayer.api.media.platforms.js.models.sources package com.futo.platformplayer.api.media.platforms.js.models.sources
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.datasource.HttpDataSource
import com.caoccao.javet.values.V8Value import com.caoccao.javet.values.V8Value
import com.caoccao.javet.values.reference.V8ValueObject import com.caoccao.javet.values.reference.V8ValueObject
import com.futo.platformplayer.api.media.models.modifier.AdhocRequestModifier import com.futo.platformplayer.api.media.models.modifier.AdhocRequestModifier
@ -15,7 +13,6 @@ import com.futo.platformplayer.engine.IV8PluginConfig
import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.V8Plugin
import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrDefault
import com.futo.platformplayer.orNull import com.futo.platformplayer.orNull
import com.futo.platformplayer.views.video.datasources.JSHttpDataSource
abstract class JSSource { abstract class JSSource {
protected val _plugin: JSClient; protected val _plugin: JSClient;
@ -33,15 +30,15 @@ abstract class JSSource {
this.type = type; this.type = type;
_requestModifier = obj.getOrDefault<V8ValueObject>(_config, "requestModifier", "JSSource.requestModifier", null)?.let { _requestModifier = obj.getOrDefault<V8ValueObject>(_config, "requestModifier", "JSSource.requestModifier", null)?.let {
JSRequest(plugin, it, null, null, true); JSRequest(plugin, it, null, null, null, null, true);
} }
hasRequestModifier = _requestModifier != null || obj.has("getRequestModifier"); hasRequestModifier = _requestModifier != null || obj.has("getRequestModifier");
} }
fun getRequestModifier(): IRequestModifier? { fun getRequestModifier(): IRequestModifier? {
if(_requestModifier != null) if(_requestModifier != null)
return AdhocRequestModifier { url, headers -> return AdhocRequestModifier { url, headers, method, body ->
return@AdhocRequestModifier _requestModifier.modify(_plugin, url, headers); return@AdhocRequestModifier _requestModifier.modify(_plugin, url, headers, method, body);
}; };
if (!hasRequestModifier || _obj.isClosed) { if (!hasRequestModifier || _obj.isClosed) {

View file

@ -6,11 +6,13 @@ import static androidx.media3.datasource.HttpUtil.buildRangeRequestHeader;
import static java.lang.Math.min; import static java.lang.Math.min;
import android.net.Uri; import android.net.Uri;
import android.util.Base64;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.futo.platformplayer.api.http.ManagedHttpClient;
import com.futo.platformplayer.api.media.models.modifier.IRequest; import com.futo.platformplayer.api.media.models.modifier.IRequest;
import com.futo.platformplayer.api.media.models.modifier.IRequestModifier; import com.futo.platformplayer.api.media.models.modifier.IRequestModifier;
import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier; import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier;
@ -24,6 +26,7 @@ import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.HttpDataSource; import androidx.media3.datasource.HttpDataSource;
import androidx.media3.datasource.HttpUtil; import androidx.media3.datasource.HttpUtil;
import androidx.media3.datasource.TransferListener; import androidx.media3.datasource.TransferListener;
import androidx.work.impl.utils.PackageManagerHelper;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ForwardingMap; import com.google.common.collect.ForwardingMap;
@ -39,12 +42,16 @@ import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.NoRouteToHostException; import java.net.NoRouteToHostException;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import okhttp3.OkHttpClient;
/* /*
* Based on the default ExoPlayer DefaultHttpDataSource * Based on the default ExoPlayer DefaultHttpDataSource
*/ */
@ -315,6 +322,12 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource {
responseMessage = connection.getResponseMessage(); responseMessage = connection.getResponseMessage();
} catch (IOException e) { } catch (IOException e) {
closeConnectionQuietly(); closeConnectionQuietly();
Log.e(TAG, "Failed to open: " + dataSpec.uri, e);
ManagedHttpClient client = new ManagedHttpClient(new OkHttpClient.Builder());
ManagedHttpClient.Response response = client.head(dataSpec.uri.toString(), new HashMap<>());
Log.i(TAG, "ManagedHttpClient response code: " + response.getCode());
throw HttpDataSourceException.createForIOException( throw HttpDataSourceException.createForIOException(
e, dataSpec, HttpDataSourceException.TYPE_OPEN); e, dataSpec, HttpDataSourceException.TYPE_OPEN);
} }
@ -574,12 +587,26 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource {
requestHeaders.put(HttpHeaders.ACCEPT_ENCODING, allowGzip ? "gzip" : "identity"); requestHeaders.put(HttpHeaders.ACCEPT_ENCODING, allowGzip ? "gzip" : "identity");
String requestMethod = DataSpec.getStringForHttpMethod(httpMethod);
String requestUrl = url.toString(); String requestUrl = url.toString();
if (requestModifier != null) { if (requestModifier != null) {
IRequest result = requestModifier.modifyRequest(requestUrl, requestHeaders); IRequest result = requestModifier.modifyRequest(requestUrl, requestHeaders, requestMethod, httpBody != null ? new String(httpBody, StandardCharsets.UTF_8) : null);
String modifiedUrl = result.getUrl(); String modifiedUrl = result.getUrl();
requestUrl = (modifiedUrl != null) ? modifiedUrl : requestUrl; if (modifiedUrl != null)
requestHeaders = result.getHeaders(); requestUrl = modifiedUrl;
Map<String, String> modifiedHeaders = result.getHeaders();
if (modifiedHeaders != null)
requestHeaders = modifiedHeaders;
String modifiedMethod = result.getMethod();
if (modifiedMethod != null)
requestMethod = modifiedMethod;
String modifiedBody = result.getBody();
if (modifiedBody != null)
httpBody = modifiedBody.getBytes(StandardCharsets.UTF_8);
} }
HttpURLConnection connection = openConnection(new URL(requestUrl)); HttpURLConnection connection = openConnection(new URL(requestUrl));
@ -592,7 +619,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource {
connection.setInstanceFollowRedirects(followRedirects); connection.setInstanceFollowRedirects(followRedirects);
connection.setDoOutput(httpBody != null); connection.setDoOutput(httpBody != null);
connection.setRequestMethod(DataSpec.getStringForHttpMethod(httpMethod)); connection.setRequestMethod(requestMethod);
if (httpBody != null) { if (httpBody != null) {
connection.setFixedLengthStreamingMode(httpBody.length); connection.setFixedLengthStreamingMode(httpBody.length);

@ -1 +1 @@
Subproject commit c86c73db0cdde3371c7944dd82c34ea4e5c725d9 Subproject commit 512c76a52bb39f2c9280cbd0d99d8e334bd71f5f