此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/405144/1057015/HttpRequest.js
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
(我已经安装了用户样式管理器,让我安装!)
// ==UserScript==
// @name HttpRequest
// @namespace hoehleg.userscripts.private
// @version 0.1
// @description HttpRequest for any type of request and HttpRequestHTML to request webpage. Supports caching of responses to handle status 304.
// @author Gerrit Höhle
//
// @grant GM_xmlhttpRequest
//
// ==/UserScript==
/* jslint esversion: 9 */
const HttpRequest = (() => {
const urlWithParams = (url, paramsObject) => {
const params = Object.entries(paramsObject).map(([key, value]) => key + '=' + value).join('&');
return url.length ? url + '?' + params : params;
};
const responsesCache = new Map();
const requestKey = ({ method, url, params, data }) => `${method}:${urlWithParams(url, params)}:DATA:${data}`;
return class HttpRequest {
constructor({
method,
url,
headers = {},
data = '',
keepInCacheTimoutMs = 0,
params = {}
} = {}) {
Object.assign(this, { method, url, headers, data, params, keepInCacheTimoutMs });
}
send() {
if (!this.method || !this.url) {
return Promise.reject(Error("invalid request"));
}
return new Promise((resolve, reject) => {
let method, url, onload, onerror, headers, data;
method = this.method.toUpperCase();
url = this.url;
headers = this.headers;
data = this.data;
onload = (response) => {
switch (response.status) {
case 200:
if (this.keepInCacheTimoutMs) {
const key = requestKey(this);
responsesCache.set(key, response);
if (this.keepInCacheTimoutMs > 0) {
setTimeout(() => responsesCache.delete(key), this.keepInCacheTimoutMs);
}
}
break;
case 304:
if (this.isCached()) {
response = this.readFromCache();
response.status = 304;
}
break;
default:
reject(Error(`Status: ${response.status}, Error: ${response.statusText}`));
return;
}
resolve(response);
};
onerror = () => {
reject(Error('network error'));
};
switch (method) {
case 'GET':
if (this.params) {
url = urlWithParams(url, this.params);
}
break;
case 'POST':
case 'PUT':
headers = Object.assign({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, headers || {});
if (this.params) {
data = urlWithParams(data, this.params);
}
break;
}
GM_xmlhttpRequest({ method, url, onload, onerror, headers, data });
});
}
isCached() {
return responsesCache.has(requestKey(this));
}
readFromCache() {
return responsesCache.get(requestKey(this));
}
static send(...args) {
return new HttpRequest(...args).send();
}
};
})();
class HttpRequestHtml extends HttpRequest {
constructor({ url, params, keepInCacheTimoutMs } = {}) {
super({ method: 'GET', url, params, keepInCacheTimoutMs });
}
async send() {
const response = await super.send();
return await new Promise(resolve => {
if (response.status == 200) {
response.html = new DOMParser().parseFromString(response.responseText, 'text/html');
resolve(response);
}
});
}
/**
* @param {*} args { url, params, keepInCacheTimoutMs }
* @returns Promise of response with { status, html }
*/
static send(...args) {
return new HttpRequestHtml(...args).send();
}
}