Greasy Fork

来自缓存

Greasy Fork is available in English.

HttpRequest

HttpRequest for any type of request and HttpRequestHTML to request webpage. Supports caching of responses to handle status 304.

当前为 2022-06-02 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/405144/1057015/HttpRequest.js

// ==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();
    }
}