xhr测试
Some checks failed
build / Build (push) Failing after 10s
test / Run tests (push) Failing after 10s

This commit is contained in:
王一之 2025-02-05 18:01:59 +08:00
parent 8dd5bdaa56
commit 65b231911e
11 changed files with 199 additions and 12 deletions

View File

@ -3,7 +3,7 @@ import { Message, MessageConnect } from "./server";
export async function sendMessage(msg: Message, action: string, data?: any): Promise<any> {
const res = await msg.sendMessage({ action, data });
LoggerCore.getInstance().logger().debug("sendMessage", { action, data, res });
LoggerCore.getInstance().logger().debug("sendMessage", { action, data, response: res });
if (res && res.code) {
console.error(res);
return Promise.reject(res.message);

View File

@ -1,3 +1,5 @@
import LoggerCore from "@App/app/logger/core";
export interface Message {
onConnect(callback: (data: any, con: MessageConnect) => void): void;
onMessage(callback: (data: any, sendResponse: (data: any) => void) => void): void;
@ -50,6 +52,8 @@ export class Server {
}
private messageHandle(msg: string, params: any, sendResponse: (response: any) => void) {
const logger = LoggerCore.getInstance().logger({ env: this.env, msg });
logger.debug("messageHandle", { params });
const func = this.apiFunctionMap.get(msg);
if (func) {
try {
@ -65,6 +69,9 @@ export class Server {
} catch (e: any) {
sendResponse({ code: -1, message: e.message });
}
} else {
sendResponse({ code: -1, message: "no such api" });
logger.error("no such api");
}
}
}

View File

@ -20,5 +20,5 @@ export function proxyUpdateRunStatus(
msg: WindowMessage,
data: { uuid: string; runStatus: SCRIPT_RUN_STATUS; error?: any; nextruntime?: number }
) {
return sendMessageToServiceWorker(msg, "updateRunStatus", data);
return sendMessageToServiceWorker(msg, "serviceWorker/script/updateRunStatus", data);
}

View File

@ -37,7 +37,7 @@ export class OffscreenManager {
return sendMessage(this.extensionMessage, data.action, data.data);
}
initManager() {
async initManager() {
// 监听消息
const group = this.api.group("offscreen");
this.windowApi.on("logger", this.logger.bind(this));
@ -53,5 +53,19 @@ export class OffscreenManager {
script.init();
// 转发gm api请求
forwardMessage("serviceWorker/runtime/gmApi", this.windowApi, this.extensionMessage);
// 处理gm xhr请求
this.api.on("gmXhr", (data) => {
console.log("123");
});
// 测试xhr
const ret = await sendMessage(this.extensionMessage, "serviceWorker/testGmApi");
console.log("test xhr", ret);
const xhr = new XMLHttpRequest();
xhr.onload = () => {
console.log(xhr);
};
xhr.open("GET", "https://scriptcat.org/zh-CN");
xhr.send();
}
}

View File

@ -31,5 +31,79 @@ export default class ServiceWorkerManager {
script.init();
const runtime = new RuntimeService(group.group("runtime"), this.mq, value);
runtime.init();
// 测试xhr
setTimeout(() => {
chrome.tabs.query(
{
url: chrome.runtime.getURL("src/offscreen.html"),
},
(result) => {
console.log(result);
}
);
}, 2000);
group.on("testGmApi", () => {
console.log(chrome.runtime.getURL("src/offscreen.html"));
return new Promise((resolve) => {
chrome.tabs.query({}, (tabs) => {
const excludedTabIds: number[] = [];
tabs.forEach((tab) => {
if (tab.id) {
excludedTabIds.push(tab.id);
}
});
chrome.declarativeNetRequest.updateSessionRules(
{
removeRuleIds: [100],
addRules: [
{
id: 100,
priority: 1,
action: {
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
requestHeaders: [
{
header: "cookie",
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: "test=1234314",
},
{
header: "origin",
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: "https://learn.scriptcat.org",
},
{
header: "user-agent",
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: "test",
},
],
},
condition: {
resourceTypes: [chrome.declarativeNetRequest.ResourceType.XMLHTTPREQUEST],
urlFilter: "https://scriptcat.org/zh-CN",
excludedTabIds: excludedTabIds,
},
},
],
},
() => {
resolve(1);
}
);
});
});
});
chrome.webRequest.onHeadersReceived.addListener(
(details) => {
console.log(details);
},
{
urls: ["<all_urls>"],
types: ["xmlhttprequest"],
},
["responseHeaders", "extraHeaders"]
);
}
}

View File

@ -236,12 +236,17 @@ export class ScriptService {
async updateRunStatus(params: { uuid: string; runStatus: SCRIPT_RUN_STATUS; error?: string; nextruntime?: number }) {
this.mq.publish("updateRunStatus", params);
return this.scriptDAO.update(params.uuid, {
if (
(await this.scriptDAO.update(params.uuid, {
runStatus: params.runStatus,
lastruntime: new Date().getTime(),
error: params.error,
nextruntime: params.nextruntime,
});
})) === false
) {
return Promise.reject("update error");
}
return Promise.resolve(true);
}
getCode(uuid: string) {

View File

@ -22,6 +22,7 @@
},
"default_locale": "zh_CN",
"permissions": [
"tabs",
"storage",
"offscreen",
"scripting",

View File

@ -3,7 +3,7 @@ import { getMetadataStr, getUserConfigStr, parseUserConfig } from "@App/pkg/util
import { ValueUpdateData } from "./exec_script";
import { ExtVersion } from "@App/app/const";
import { storageKey } from "../utils";
import { Message } from "@Packages/message/server";
import { Message, MessageConnect } from "@Packages/message/server";
interface ApiParam {
depend?: string[];
@ -178,4 +178,53 @@ export default class GMApi {
}
return this.sendMessage("GM_log", [message, level, labels]);
}
// 用于脚本跨域请求,需要@connect domain指定允许的域名
@GMContext.API({
depend: ["CAT_fetchBlob", "CAT_createBlobUrl", "CAT_fetchDocument"],
})
public GM_xmlhttpRequest(details: GMTypes.XHRDetails) {
const u = new URL(details.url, window.location.href);
if (details.headers) {
Object.keys(details.headers).forEach((key) => {
if (key.toLowerCase() === "cookie") {
details.cookie = details.headers![key];
delete details.headers![key];
}
});
}
const param: GMSend.XHRDetails = {
method: details.method,
timeout: details.timeout,
url: u.href,
headers: details.headers,
cookie: details.cookie,
context: details.context,
responseType: details.responseType,
overrideMimeType: details.overrideMimeType,
anonymous: details.anonymous,
user: details.user,
password: details.password,
maxRedirects: details.maxRedirects,
};
if (!param.headers) {
param.headers = {};
}
if (details.nocache) {
param.headers["Cache-Control"] = "no-cache";
}
let connect: MessageConnect;
this.connect("GM_xmlhttpRequest", [param]).then((con) => {
connect = con;
});
return {
abort: () => {
if (connect) {
connect.disconnect();
}
},
};
}
}

View File

@ -29,7 +29,8 @@ export default class GMApi {
}
handlerRequest(params: Request) {
console.log(params);
console.log(params, arguments);
return null;
}
@PermissionVerify.API()
@ -43,5 +44,12 @@ export default class GMApi {
return this.value.setValue(request.script.uuid, key, value);
}
@PermissionVerify.API()
GM_xmlhttpRequest(request: Request) {
// 发送到offscreen, 处理请求
console.log(request, arguments);
return null;
}
start() {}
}

View File

@ -14,7 +14,6 @@ async function hasDocument() {
contextTypes: [chrome.runtime.ContextType.OFFSCREEN_DOCUMENT],
documentUrls: [offscreenUrl],
});
return existingContexts.length > 0;
}
@ -28,6 +27,7 @@ async function setupOffscreenDocument() {
creating = chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [
chrome.offscreen.Reason.BLOBS,
chrome.offscreen.Reason.CLIPBOARD,
chrome.offscreen.Reason.DOM_SCRAPING,
chrome.offscreen.Reason.LOCAL_STORAGE,

29
src/types/main.d.ts vendored
View File

@ -4,3 +4,32 @@ declare module "*.json";
declare module "*.yaml";
declare let sandbox: Window;
declare namespace GMSend {
interface XHRDetails {
method?: "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
url: string;
headers?: { [key: string]: string };
data?: string | Array<XHRFormData>;
cookie?: string;
binary?: boolean;
timeout?: number;
context?: CONTEXT_TYPE;
responseType?: "text" | "arraybuffer" | "blob" | "json" | "document" | "stream";
overrideMimeType?: string;
anonymous?: boolean;
fetch?: boolean;
user?: string;
password?: string;
nocache?: boolean;
dataType?: "FormData" | "Blob";
maxRedirects?: number;
}
interface XHRFormData {
type?: "file" | "text";
key: string;
val: string;
filename?: string;
}
}