mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-02 22:30:40 +00:00
POST fix.
This commit is contained in:
parent
18150e9e15
commit
816d3c58f2
10 changed files with 70 additions and 36 deletions
6
app/src/main/assets/devportal/plugin.d.ts
vendored
6
app/src/main/assets/devportal/plugin.d.ts
vendored
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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?;
|
||||||
}
|
}
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue