-
Notifications
You must be signed in to change notification settings - Fork 310
Closed
Description
问题描述
如下封装了GM_xmlhttpRequest
const tools = {
sleep: t => new Promise(res => setTimeout(res, t)),// 箭头函数体只有一句,可以省略return
net: {
change: (str, withCookie, autoFollow302) => {
str = str.trim(); //去除文本首位\s
let method = str.match(/(.*?)\s/)[1];
let url = str.match(/\s(.*?)\s/)[1];
str = str.replace(/.*?\n/, ''); //去除第一行
let data = /\n\s*\n\s*(.*)$/m.test(str) ? str.slice(str.match(/\n\s*\n\s*(.*)$/m).index).trim() : ''; //获取请求体,没有则返回'', 用slice截取防止请求体含有\n时出错
str = str.replace(new RegExp(data), '').trim(); //去除data
str = str.replace(/^(\s*?)(\S.*)/gm, `$2`); //去除每行行首的\s
str = str.replace(/\sContent-Length:.*/im, ''); //去除Content-Length所在行,不用/^\sContent-Length:./im, 这样做会多一个空白行避免一些问题
str = str.replace(/\sHOST.*/im, ''); //去除host可以避免请求为302时后续自动跟随的问题
str = withCookie ? str : str.replace(/\s*cookie:.*/im, '') //去除cookie所在行,不用/^\s*cookie.*/im, 这样做会多一个空白行
str = str.replace(/\sHOST.*/im, '');
if (!autoFollow302) {
str = str.replace(/\sReferer.*/im, '');
str = str.replace(/\sOrigin.*/im, '');
str = str.replace(/\scache-control.*/im, '');
}
let headers = {}, h = str.match(/(\S*?):\s*(\S.*)/mg);
// GM_log(h)
h.forEach(e => {
let t = e.match(/(\S*?):\s*(.*)/);
headers[t[1]] = t[2].replace(/\s*$/, '');//去除行尾\s,避免一下总没错吧
});
//去除浏览器默认携带的请求头
// if (!/dnt/i.test(str)) headers.dnt = '';
// //if (!/accept/i.test(str)) headers.accept='';
// if (!/user-agent/i.test(str)) headers['user-agent'] = '';
// if (!/sec-ch-ua/i.test(str)) headers['sec-ch-ua'] = '';
// if (!/sec-ch-ua-mobile/i.test(str)) headers['sec-ch-ua-mobile'] = '';
// if (!/sec-ch-ua-platform/i.test(str)) headers['sec-ch-ua-platform'] = '';
// if (!/sec-fetch-dest/i.test(str)) headers['sec-fetch-dest'] = '';
// if (!/sec-fetch-mode/i.test(str)) headers['sec-fetch-mode'] = '';
// if (!/sec-fetch-site/i.test(str)) headers['sec-fetch-site'] = '';
// //if (!/accept-language/i.test(str)) headers['accept-language']='';
// if (!/accept-encoding/i.test(str)) headers['accept-encoding'] = '';
return { url, method, data, headers }
},
},
waitForSpecificTime: async (expectedTime, timestamp) => {
if (timestamp == undefined) {
timestamp = await tools.net.send(`
GET https://time.is/t/?zh.0.347.2464.0p.480.43d.1574683214663.1594044507830. HTTP/1.1
`, onload = (xhr => {
let timestamp = xhr.response.substring(0, 13);
console.log(`timestamp: ${timestamp}`);
return timestamp
}), anonymous = true, withCookie = true);
}
// 定义一个将 HH:mm:ss 格式的时间字符串转换为今日的 Date 对象的函数
const parseTimeToTodayDate = (timeString) => {
const now = new Date();
const [hours, minutes, seconds] = timeString.split(':').map(Number);
return (new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes, seconds)).getTime()
};
// 计算预期执行时间与当前时间的差异(毫秒)
const currentTime = timestamp;
const expectedDateTime = parseTimeToTodayDate(expectedTime);
const millisecondsToWait = expectedDateTime - currentTime;
(typeof GM_log === "function" ? GM_log : console.log)('脚本启动......');
// 如果当前时间小于预期时间,则等待差异时间
if (millisecondsToWait > 0) {
(typeof GM_log === "function" ? GM_log : console.log)(`等待 ${millisecondsToWait / 1000} 秒后执行脚本......`);
await new Promise(resolve => setTimeout(resolve, millisecondsToWait));
} else {
(typeof GM_log === "function" ? GM_log : console.log)('立即执行脚本');
}
},
};
tools.net.send = (str, onload = (xhr => xhr), anonymous = false, withCookie = false, autoFollow302 = true) => {
let t = tools.net.change(str, withCookie, autoFollow302);
return new Promise((resolve, reject) => {
t.anonymous = anonymous;
t.onload = (xhr) => {
resolve(onload(xhr))
};
t.onerror = _ => { console.log(_);GM_log('some errors:' + _) };
t.onreadystatechange = _ => {
if (_.status == 0) resolve('联系服务器之前发生了错误')
}
GM_xmlhttpRequest(t)
})
};
执行await tools.waitForSpecificTime('7:04:20')时t.onerror = _ => { console.log(_);GM_log('some errors:' + _) }打印出来错误
{
"DONE": 4,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"OPENED": 1,
"UNSENT": 0,
"RESPONSE_TYPE_TEXT": "text",
"RESPONSE_TYPE_ARRAYBUFFER": "arraybuffer",
"RESPONSE_TYPE_BLOB": "blob",
"RESPONSE_TYPE_DOCUMENT": "document",
"RESPONSE_TYPE_JSON": "json",
"RESPONSE_TYPE_STREAM": "stream",
"error": "Failed to execute 'fetch' on 'WorkerGlobalScope': Request with GET/HEAD method cannot have body.",
"readyState": 4,
"response": null,
"responseHeaders": "",
"responseText": "",
"status": 0,
"statusText": ""
}
这个应该请求体为""导致的,修复:
tools.net.send = (str, onload = (xhr => xhr), anonymous = false, withCookie = false, autoFollow302 = true) => {
let t = tools.net.change(str, withCookie, autoFollow302);
// ✅ 关键:GET/HEAD 不要传 data(哪怕是 '')
if (/^(GET|HEAD)$/i.test(t.method) && (t.data === '' || t.data == null)) {
delete t.data;
}
return new Promise((resolve, reject) => {
t.anonymous = anonymous;
t.onload = (xhr) => resolve(onload(xhr));
t.onerror = _ => { console.log(_); (typeof GM_log === "function" ? GM_log : console.log)('some errors:' + JSON.stringify(_, null, 2)); };
t.onreadystatechange = _ => {
if (_.status == 0) resolve('联系服务器之前发生了错误')
}
GM_xmlhttpRequest(t);
});
};
另外
t.onreadystatechange = _ => {
if (_.status == 0) resolve('联系服务器之前发生了错误')
}
新版本应该发生了变化,导致直接resolve('联系服务器之前发生了错误'),注释掉就好了,但是就没办法判断是否是不是在外网里导致的。
重现步骤
...
脚本猫版本
v1.2.1
操作系统以及浏览器信息
edge最新版
补充信息 (选填)
No response
Metadata
Metadata
Assignees
Labels
No labels