mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-02 22:30:40 +00:00
Proxy support, Additional http header access support
This commit is contained in:
parent
8193234c2f
commit
819e81b7a6
11 changed files with 275 additions and 23 deletions
|
@ -262,6 +262,17 @@ function getDevLogs(lastIndex, cb) {
|
||||||
.then(x=>x.json())
|
.then(x=>x.json())
|
||||||
.then(y=> cb && cb(y));
|
.then(y=> cb && cb(y));
|
||||||
}
|
}
|
||||||
|
function getDevHttpExchanges(cb) {
|
||||||
|
fetch("/plugin/getDevHttpExchanges", {
|
||||||
|
timeout: 1000
|
||||||
|
})
|
||||||
|
.then(x=>x.json())
|
||||||
|
.then(y=> cb && cb(y));
|
||||||
|
}
|
||||||
|
function setDevHttpProxy(url, port) {
|
||||||
|
return fetch("/dev/setDevProxy?url=" + encodeURIComponent(url) + "&port=" + port)
|
||||||
|
.then(x=>x.json());
|
||||||
|
}
|
||||||
function sendFakeDevLog(devId, msg) {
|
function sendFakeDevLog(devId, msg) {
|
||||||
return syncGET("/plugin/fakeDevLog?devId=" + devId + "&msg=" + msg, {});
|
return syncGET("/plugin/fakeDevLog?devId=" + devId + "&msg=" + msg, {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,6 +196,79 @@
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
.httpContainer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.httpLine {
|
||||||
|
}
|
||||||
|
.httpLine .request {
|
||||||
|
height: 50px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.httpLine .request .status {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
width: 40px;
|
||||||
|
top: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #333;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.httpLine .request .status.error {
|
||||||
|
background-color: #880000;
|
||||||
|
}
|
||||||
|
.httpLine .request .status.success {
|
||||||
|
background-color: #008800;
|
||||||
|
}
|
||||||
|
.httpLine .request .status.warn {
|
||||||
|
background-color: #803500;
|
||||||
|
}
|
||||||
|
.httpLine .request .method {
|
||||||
|
position: absolute;
|
||||||
|
left: 55px;
|
||||||
|
top: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #333;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.httpLine .request .url {
|
||||||
|
position: absolute;
|
||||||
|
left: 110px;
|
||||||
|
top: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #333;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.httpLine .response {
|
||||||
|
background-color: #111;
|
||||||
|
margin-left: 55px;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.httpLine .response .body{
|
||||||
|
white-space: pre-wrap;
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: black;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.httpLine .response .headers {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.httpLine .response .headers .key {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
.httpLine .response .headers .value {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -547,7 +620,62 @@
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn>Clear</v-btn>
|
<v-btn @click="Integration.logs = []">Clear</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
<v-card style="margin: 20px;" v-if="Plugin.currentPlugin && Integration.httpExchanges">
|
||||||
|
<v-card-title>
|
||||||
|
Http Logs
|
||||||
|
</v-card-title>
|
||||||
|
</v-card-header>
|
||||||
|
<v-card-text>
|
||||||
|
<div style="position: absolute; top: 0px; right: 15px;">
|
||||||
|
<v-checkbox v-model="Integration.showHttpRequests" label="Show Http Requests"></v-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="httpContainer" v-if="Integration.showHttpRequests">
|
||||||
|
<div class="httpLine" v-for="exchange of Integration.httpExchanges">
|
||||||
|
<div class="request" @click="toggleHttpExchange(exchange)">
|
||||||
|
<div :class="[{ success: exchange.response.status < 300, warn: exchange.response.status >= 300 && exchange.response.status < 400, error: exchange.response.status >= 400 }, 'status']">
|
||||||
|
{{exchange.response.status}}
|
||||||
|
</div>
|
||||||
|
<div class="method">
|
||||||
|
{{exchange.request.method}}
|
||||||
|
</div>
|
||||||
|
<div class="url">
|
||||||
|
{{exchange.request.url}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="response" v-if="exchange.response.show">
|
||||||
|
<h2>Request Headers</h2>
|
||||||
|
<div class="headers">
|
||||||
|
<div class="header" v-for="(headerValue, header) in exchange.request.headers">
|
||||||
|
<div class="key">
|
||||||
|
{{header}}
|
||||||
|
</div>
|
||||||
|
<div class="value">
|
||||||
|
{{headerValue}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Response</h2>
|
||||||
|
<div class="headers">
|
||||||
|
<div class="header" v-for="(headerValue, header) in exchange.response.headers">
|
||||||
|
<div class="key">
|
||||||
|
{{header}}
|
||||||
|
</div>
|
||||||
|
<div class="value">
|
||||||
|
{{headerValue}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="body">{{exchange.response.body}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn v-if="Integration.showHttpRequests" @click="Integration.httpExchanges = []">Clear</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -604,7 +732,9 @@
|
||||||
lastLogIndex: -1,
|
lastLogIndex: -1,
|
||||||
lastLogDevID: "",
|
lastLogDevID: "",
|
||||||
logs: [],
|
logs: [],
|
||||||
lastInjectTime: ""
|
httpExchanges: [],
|
||||||
|
lastInjectTime: "",
|
||||||
|
showHttpRequests: false
|
||||||
},
|
},
|
||||||
Plugin: {
|
Plugin: {
|
||||||
loadUsingTag: false,
|
loadUsingTag: false,
|
||||||
|
@ -688,6 +818,16 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if(this.Integration.showHttpRequests) {
|
||||||
|
getDevHttpExchanges((exchanges)=>{
|
||||||
|
Vue.nextTick(()=>{
|
||||||
|
for(i = 0; i < exchanges.length; i++) {
|
||||||
|
exchanges[i].response.show = false;
|
||||||
|
this.Integration.httpExchanges.unshift(exchanges[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(ex) {
|
catch(ex) {
|
||||||
console.error("Failed update", ex);
|
console.error("Failed update", ex);
|
||||||
|
@ -970,6 +1110,9 @@
|
||||||
},
|
},
|
||||||
showTestResults(results) {
|
showTestResults(results) {
|
||||||
|
|
||||||
|
},
|
||||||
|
toggleHttpExchange(exchange) {
|
||||||
|
exchange.response.show = !exchange.response.show;
|
||||||
},
|
},
|
||||||
copyClipboard(cpy) {
|
copyClipboard(cpy) {
|
||||||
if(navigator.clipboard)
|
if(navigator.clipboard)
|
||||||
|
|
|
@ -46,7 +46,8 @@ class SourcePluginConfig(
|
||||||
var enableInHome: Boolean = true,
|
var enableInHome: Boolean = true,
|
||||||
var supportedClaimTypes: List<Int> = listOf(),
|
var supportedClaimTypes: List<Int> = listOf(),
|
||||||
var primaryClaimFieldType: Int? = null,
|
var primaryClaimFieldType: Int? = null,
|
||||||
var developerSubmitUrl: String? = null
|
var developerSubmitUrl: String? = null,
|
||||||
|
var allowAllHttpHeaderAccess: Boolean = false,
|
||||||
) : IV8PluginConfig {
|
) : IV8PluginConfig {
|
||||||
|
|
||||||
val absoluteIconUrl: String? get() = resolveAbsoluteUrl(iconUrl, sourceUrl);
|
val absoluteIconUrl: String? get() = resolveAbsoluteUrl(iconUrl, sourceUrl);
|
||||||
|
@ -143,6 +144,11 @@ class SourcePluginConfig(
|
||||||
list.add(Pair(
|
list.add(Pair(
|
||||||
"Unrestricted Web Access",
|
"Unrestricted Web Access",
|
||||||
"This plugin requires access to all URLs, this may include malicious URLs."));
|
"This plugin requires access to all URLs, this may include malicious URLs."));
|
||||||
|
if(allowAllHttpHeaderAccess)
|
||||||
|
list.add(Pair(
|
||||||
|
"Unrestricted Http Header access",
|
||||||
|
"Allows this plugin to access all headers (including cookies and authorization headers) for unauthenticated requests."
|
||||||
|
))
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,22 @@ package com.futo.platformplayer.api.media.platforms.js.internal
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.futo.platformplayer.api.http.ManagedHttpClient
|
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.DevJSClient
|
||||||
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourceAuth
|
import com.futo.platformplayer.api.media.platforms.js.SourceAuth
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourceCaptchaData
|
import com.futo.platformplayer.api.media.platforms.js.SourceCaptchaData
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSRequest
|
import com.futo.platformplayer.api.media.platforms.js.models.JSRequest
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier
|
import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier
|
||||||
|
import com.futo.platformplayer.developer.DeveloperEndpoints
|
||||||
import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
|
import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
|
||||||
import com.futo.platformplayer.matchesDomain
|
import com.futo.platformplayer.matchesDomain
|
||||||
|
import com.futo.platformplayer.states.StateDeveloper
|
||||||
|
import com.google.common.net.MediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okio.GzipSource
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.net.Proxy
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class JSHttpClient : ManagedHttpClient {
|
class JSHttpClient : ManagedHttpClient {
|
||||||
|
@ -28,7 +36,15 @@ class JSHttpClient : ManagedHttpClient {
|
||||||
private var _currentCookieMap: HashMap<String, HashMap<String, String>>;
|
private var _currentCookieMap: HashMap<String, HashMap<String, String>>;
|
||||||
private var _otherCookieMap: HashMap<String, HashMap<String, String>>;
|
private var _otherCookieMap: HashMap<String, HashMap<String, String>>;
|
||||||
|
|
||||||
constructor(jsClient: JSClient?, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, config: SourcePluginConfig? = null) : super() {
|
constructor(jsClient: JSClient?, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, config: SourcePluginConfig? = null) : super(
|
||||||
|
//Temporary ugly solution for DevPortal proxy support
|
||||||
|
(if(jsClient?.config?.id == StateDeveloper.DEV_ID && StateDeveloper.instance.devProxy != null)
|
||||||
|
OkHttpClient.Builder().proxy(Proxy(Proxy.Type.HTTP,
|
||||||
|
InetSocketAddress(StateDeveloper.instance.devProxy!!.url, StateDeveloper.instance.devProxy!!.port)
|
||||||
|
))
|
||||||
|
else
|
||||||
|
OkHttpClient.Builder())
|
||||||
|
) {
|
||||||
_jsClient = jsClient;
|
_jsClient = jsClient;
|
||||||
_jsConfig = config;
|
_jsConfig = config;
|
||||||
_auth = auth;
|
_auth = auth;
|
||||||
|
@ -201,6 +217,16 @@ class JSHttpClient : ManagedHttpClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(_jsClient is DevJSClient) {
|
||||||
|
//val peekBody = resp.peekBody(1000 * 1000).string();
|
||||||
|
StateDeveloper.instance.addDevHttpExchange(
|
||||||
|
StateDeveloper.DevHttpExchange(
|
||||||
|
StateDeveloper.DevHttpRequest(resp.request.method, resp.request.url.toString(), mapOf(*resp.request.headers.map { Pair(it.first, it.second) }.toTypedArray()), ""),
|
||||||
|
StateDeveloper.DevHttpRequest("RESP", resp.request.url.toString(), mapOf(*resp.headers.map { Pair(it.first, it.second) }.toTypedArray()), "", resp.code)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,12 +116,6 @@ class DeveloperEndpoints(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dependencies
|
//Dependencies
|
||||||
//@HttpGET("/dependencies/vue.js", "application/javascript")
|
|
||||||
//val depVue = StateAssets.readAsset(context, "devportal/dependencies/vue.js", true);
|
|
||||||
//@HttpGET("/dependencies/vuetify.js", "application/javascript")
|
|
||||||
//val depVuetify = StateAssets.readAsset(context, "devportal/dependencies/vuetify.js", true);
|
|
||||||
//@HttpGET("/dependencies/vuetify.min.css", "text/css")
|
|
||||||
//val depVuetifyCss = StateAssets.readAsset(context, "devportal/dependencies/vuetify.min.css", true);
|
|
||||||
@HttpGET("/dependencies/FutoMainLogo.svg", "image/svg+xml")
|
@HttpGET("/dependencies/FutoMainLogo.svg", "image/svg+xml")
|
||||||
val depFutoLogo = StateAssets.readAsset(context, "devportal/dependencies/FutoMainLogo.svg");
|
val depFutoLogo = StateAssets.readAsset(context, "devportal/dependencies/FutoMainLogo.svg");
|
||||||
@HttpGET("/favicon.svg", "image/svg+xml")
|
@HttpGET("/favicon.svg", "image/svg+xml")
|
||||||
|
@ -450,6 +444,25 @@ class DeveloperEndpoints(private val context: Context) {
|
||||||
context.respondCode(500, ex::class.simpleName + ":" + ex.message, "text/plain")
|
context.respondCode(500, ex::class.simpleName + ":" + ex.message, "text/plain")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@HttpGET("/dev/setDevProxy")
|
||||||
|
fun devSetDevProxy(context: HttpContext) {
|
||||||
|
try {
|
||||||
|
val url = context.query.getOrDefault("url", "");
|
||||||
|
val port = context.query.getOrDefault("port", "");
|
||||||
|
if(url.isNullOrEmpty() || port.isNullOrEmpty() || port.toIntOrNull() == null)
|
||||||
|
{
|
||||||
|
StateDeveloper.instance.devProxy = null;
|
||||||
|
context.respondCode(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StateDeveloper.instance.devProxy = StateDeveloper.DevProxySettings(url, port.toInt());
|
||||||
|
context.respondCode(200, "true", "application/json");
|
||||||
|
}
|
||||||
|
catch(ex: Exception) {
|
||||||
|
Logger.e("DeveloperEndpoints", ex.message, ex);
|
||||||
|
context.respondCode(500, ex::class.simpleName + ":" + ex.message, "text/plain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@HttpGET("/plugin/getDevLogs")
|
@HttpGET("/plugin/getDevLogs")
|
||||||
fun pluginGetDevLogs(context: HttpContext) {
|
fun pluginGetDevLogs(context: HttpContext) {
|
||||||
|
@ -461,6 +474,15 @@ class DeveloperEndpoints(private val context: Context) {
|
||||||
context.respondCode(500, ex.message ?: "", "text/plain")
|
context.respondCode(500, ex.message ?: "", "text/plain")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@HttpGET("/plugin/getDevHttpExchanges")
|
||||||
|
fun pluginGetDevExchanges(context: HttpContext) {
|
||||||
|
try {
|
||||||
|
context.respondJson(200, StateDeveloper.instance.getHttpExchangesAndClear());
|
||||||
|
}
|
||||||
|
catch(ex: Exception) {
|
||||||
|
context.respondCode(500, ex.message ?: "", "text/plain")
|
||||||
|
}
|
||||||
|
}
|
||||||
@HttpGET("/plugin/fakeDevLog")
|
@HttpGET("/plugin/fakeDevLog")
|
||||||
fun pluginFakeDevLog(context: HttpContext) {
|
fun pluginFakeDevLog(context: HttpContext) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.caoccao.javet.interop.V8Runtime
|
||||||
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.http.ManagedHttpClient
|
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
|
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
|
||||||
import com.futo.platformplayer.engine.IV8PluginConfig
|
import com.futo.platformplayer.engine.IV8PluginConfig
|
||||||
import com.futo.platformplayer.engine.V8Plugin
|
import com.futo.platformplayer.engine.V8Plugin
|
||||||
|
@ -242,7 +243,8 @@ class PackageHttp: V8Package {
|
||||||
val resp = client.requestMethod(method, url, headers);
|
val resp = client.requestMethod(method, url, headers);
|
||||||
val responseBody = resp.body?.string();
|
val responseBody = resp.body?.string();
|
||||||
//logResponse(method, url, resp.code, resp.headers, responseBody);
|
//logResponse(method, url, resp.code, resp.headers, responseBody);
|
||||||
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers));
|
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers,
|
||||||
|
_client !is JSHttpClient || _client.isLoggedIn || _package._config !is SourcePluginConfig || !_package._config.allowAllHttpHeaderAccess));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -256,7 +258,8 @@ class PackageHttp: V8Package {
|
||||||
val resp = client.requestMethod(method, url, body, headers);
|
val resp = client.requestMethod(method, url, body, headers);
|
||||||
val responseBody = resp.body?.string();
|
val responseBody = resp.body?.string();
|
||||||
//logResponse(method, url, resp.code, resp.headers, responseBody);
|
//logResponse(method, url, resp.code, resp.headers, responseBody);
|
||||||
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers));
|
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers,
|
||||||
|
_client !is JSHttpClient || _client.isLoggedIn || _package._config !is SourcePluginConfig || !_package._config.allowAllHttpHeaderAccess));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -271,7 +274,8 @@ class PackageHttp: V8Package {
|
||||||
val resp = client.get(url, headers);
|
val resp = client.get(url, headers);
|
||||||
val responseBody = resp.body?.string();
|
val responseBody = resp.body?.string();
|
||||||
//logResponse("GET", url, resp.code, resp.headers, responseBody);
|
//logResponse("GET", url, resp.code, resp.headers, responseBody);
|
||||||
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers));
|
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers,
|
||||||
|
_client !is JSHttpClient || _client.isLoggedIn || _package._config !is SourcePluginConfig || !_package._config.allowAllHttpHeaderAccess));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -285,7 +289,8 @@ class PackageHttp: V8Package {
|
||||||
val resp = client.post(url, body, headers);
|
val resp = client.post(url, body, headers);
|
||||||
val responseBody = resp.body?.string();
|
val responseBody = resp.body?.string();
|
||||||
//logResponse("POST", url, resp.code, resp.headers, responseBody);
|
//logResponse("POST", url, resp.code, resp.headers, responseBody);
|
||||||
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers));
|
return@catchHttp BridgeHttpResponse(resp.url, resp.code, responseBody, sanitizeResponseHeaders(resp.headers,
|
||||||
|
_client !is JSHttpClient || _client.isLoggedIn || _package._config !is SourcePluginConfig || !_package._config.allowAllHttpHeaderAccess));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -305,12 +310,25 @@ class PackageHttp: V8Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sanitizeResponseHeaders(headers: Map<String, List<String>>?): Map<String, List<String>> {
|
private fun sanitizeResponseHeaders(headers: Map<String, List<String>>?, onlyWhitelisted: Boolean = false): Map<String, List<String>> {
|
||||||
val result = mutableMapOf<String, List<String>>()
|
val result = mutableMapOf<String, List<String>>()
|
||||||
headers?.forEach { (header, values) ->
|
if(onlyWhitelisted)
|
||||||
val lowerCaseHeader = header.lowercase()
|
headers?.forEach { (header, values) ->
|
||||||
if (WHITELISTED_RESPONSE_HEADERS.contains(lowerCaseHeader)) {
|
val lowerCaseHeader = header.lowercase()
|
||||||
result[lowerCaseHeader] = values
|
if (WHITELISTED_RESPONSE_HEADERS.contains(lowerCaseHeader)) {
|
||||||
|
result[lowerCaseHeader] = values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
headers?.forEach { (header, values) ->
|
||||||
|
val lowerCaseHeader = header.lowercase()
|
||||||
|
if(lowerCaseHeader == "set-cookie") {
|
||||||
|
result[lowerCaseHeader] = values.filter{
|
||||||
|
!it.lowercase().contains("httponly")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result[lowerCaseHeader] = values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -19,6 +19,9 @@ class StateDeveloper {
|
||||||
|
|
||||||
private var _devLogsIndex: Int = 0;
|
private var _devLogsIndex: Int = 0;
|
||||||
private val _devLogs: MutableList<DevLog> = mutableListOf();
|
private val _devLogs: MutableList<DevLog> = mutableListOf();
|
||||||
|
private val _devHttpExchanges: MutableList<DevHttpExchange> = mutableListOf();
|
||||||
|
|
||||||
|
var devProxy: DevProxySettings? = null;
|
||||||
|
|
||||||
fun initializeDev(id: String) {
|
fun initializeDev(id: String) {
|
||||||
currentDevID = id;
|
currentDevID = id;
|
||||||
|
@ -94,6 +97,21 @@ class StateDeveloper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addDevHttpExchange(exchange: DevHttpExchange) {
|
||||||
|
synchronized(_devHttpExchanges) {
|
||||||
|
if(_devHttpExchanges.size > 15)
|
||||||
|
_devHttpExchanges.removeAt(0);
|
||||||
|
_devHttpExchanges.add(exchange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun getHttpExchangesAndClear(): List<DevHttpExchange> {
|
||||||
|
synchronized(_devHttpExchanges) {
|
||||||
|
val data = _devHttpExchanges.toList();
|
||||||
|
_devHttpExchanges.clear();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setDevClientSettings(settings: HashMap<String, String?>) {
|
fun setDevClientSettings(settings: HashMap<String, String?>) {
|
||||||
val client = StatePlatform.instance.getDevClient();
|
val client = StatePlatform.instance.getDevClient();
|
||||||
client?.let {
|
client?.let {
|
||||||
|
@ -138,4 +156,12 @@ class StateDeveloper {
|
||||||
|
|
||||||
@kotlinx.serialization.Serializable
|
@kotlinx.serialization.Serializable
|
||||||
data class DevLog(val id: Int, val devId: String, val type: String, val log: String);
|
data class DevLog(val id: Int, val devId: String, val type: String, val log: String);
|
||||||
|
|
||||||
|
@kotlinx.serialization.Serializable
|
||||||
|
data class DevHttpRequest(val method: String, val url: String, val headers: Map<String, String>, val body: String, val status: Int = 0);
|
||||||
|
@kotlinx.serialization.Serializable
|
||||||
|
data class DevHttpExchange(val request: DevHttpRequest, val response: DevHttpRequest);
|
||||||
|
|
||||||
|
@kotlinx.serialization.Serializable
|
||||||
|
data class DevProxySettings(val url: String, val port: Int)
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3cc6d553cf840141fb5fa718a7b4a6b49282eaad
|
Subproject commit 59d2200f9220f2add3c4b7eccc314306503493a3
|
|
@ -1 +1 @@
|
||||||
Subproject commit cac27408440f5586c1c68d846456792041403d35
|
Subproject commit 37e2ed94384ff82f4cb67a2250877cb1e8e03c57
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3cc6d553cf840141fb5fa718a7b4a6b49282eaad
|
Subproject commit 59d2200f9220f2add3c4b7eccc314306503493a3
|
|
@ -1 +1 @@
|
||||||
Subproject commit d1058f0b6ccf8cbebe4eed2afba145899e6dba00
|
Subproject commit 37e2ed94384ff82f4cb67a2250877cb1e8e03c57
|
Loading…
Add table
Add a link
Reference in a new issue