Greasy Fork

HttpRequest

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

目前为 2020-06-20 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/405144/818473/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
//
// @require      https://greasyfork.org/scripts/405143-simplecache/code/SimpleCache.js
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js
//
// ==/UserScript==

/* jshint esnext: true */
/* globals SimpleCache, $, jQuery */
const HttpRequest = (() => {
    const responsesCache = new SimpleCache({ keyExtractor: (httpRequest) => [ httpRequest.method, httpRequest.url, httpRequest.headers, httpRequest.data, httpRequest.params ].join() });

    const urlWithParams = (url, paramsObject) => {
        const params = Object.entries(paramsObject).map(([key, value]) => key + '=' + value).join('&');
        return (url.length > 0) ? url + '?' + params : params;
    };

    return class HttpRequest {
        constructor({ method, url = window.location.href, headers = {}, data = '', keepInCacheTimoutMs = 10 * 60000, params = {} } = {}) {
            Object.assign(this, { method, url, headers, data, keepInCacheTimoutMs, params });
        }

        send() {
            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 > 0) {
                                responsesCache.set(this, response, this.keepInCacheTimoutMs);
                            }
                            break;
                        case 304:
                            if (this.isCached()) {
                                response = this.getFromCache();
                                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(this);
        }

        getFromCache() {
            return responsesCache.get(this);
        }
        
        static send(...args) {
            return new HttpRequest(...args).send();
        }
    };
})();

class HttpRequestHtml extends HttpRequest {
    constructor({ url, method = "GET", headers, data, keepInCacheTimoutMs, params } = {}) {
        super({ method, url, headers, data, keepInCacheTimoutMs, params });
    }
 
    send() {
        return super.send().then(response => new Promise(resolve => {
            if (response.status == 200) {
                response.html = new DOMParser().parseFromString(response.responseText, 'text/html');
                resolve(response);
            }
        }));
    }
 
    static send(...args) {
        return new HttpRequestHtml(...args).send();
    }
}