HttpRequest Library

HttpRequest for any type of request and HttpRequestHTML to request webpage. Supports caching of responses for a given period and paging.

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

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

  1. // ==UserScript==
  2. // @name HttpRequest Library
  3. // @namespace hoehleg.userscripts.private
  4. // @version 0.6
  5. // @description HttpRequest for any type of request and HttpRequestHTML to request webpage. Supports caching of responses for a given period and paging.
  6. // @author Gerrit Höhle
  7. //
  8. // @grant GM_xmlhttpRequest
  9. //
  10. // ==/UserScript==
  11.  
  12. // https://gf.qytechs.cn/de/scripts/405144
  13.  
  14. /* jslint esversion: 9 */
  15. class HttpRequest {
  16. constructor({
  17. method,
  18. url,
  19. headers = {},
  20. data = '',
  21. params = {},
  22. contentType = 'application/x-www-form-urlencoded; charset=UTF-8',
  23. responseType = null,
  24. } = {}) {
  25. const urlWithParams = (url, paramsObject) => {
  26. const params = Object.entries(paramsObject).map(([key, value]) => key + '=' + value).join('&');
  27. return params.length ? url + '?' + params : url;
  28. };
  29.  
  30. switch (method.toUpperCase()) {
  31. case 'GET':
  32. case 'HEAD':
  33. if (params) {
  34. url = urlWithParams(url, params);
  35. }
  36. break;
  37. default:
  38. headers = Object.assign({ 'Content-Type': contentType }, headers || {});
  39.  
  40. if (params) {
  41. if (typeof data === 'string') {
  42. try {
  43. data = JSON.parse(data);
  44. } catch (e) {
  45. console.log(e);
  46. }
  47. }
  48.  
  49. data = { ...(data || {}), ...this.params };
  50. }
  51. break;
  52. }
  53.  
  54. /** @type {string} */
  55. this.method = method.toUpperCase();
  56.  
  57. /** @type {string} */
  58. this.url = encodeURI(url);
  59.  
  60. /** @type {object} */
  61. this.headers = headers;
  62.  
  63. /** @type {string} */
  64. this.data = typeof data === 'string' ? data : JSON.stringify(data);
  65.  
  66. /** @type {string} */
  67. this.responseType = responseType;
  68. }
  69.  
  70. async send() {
  71. if (!this.method || !this.url) {
  72. return await Promise.reject("invalid request");
  73. }
  74.  
  75. return await new Promise((resolve, reject) => {
  76. const { method, url, headers, data, responseType } = this;
  77.  
  78. const onload = (response) => {
  79. resolve(response);
  80. };
  81.  
  82. const onerror = (errorEvent) => {
  83. console.log(errorEvent);
  84. reject("network error");
  85. };
  86.  
  87. GM_xmlhttpRequest({ method, url, onload, onerror, headers, data, responseType });
  88. });
  89. }
  90.  
  91. static async send(...args) {
  92. return await new HttpRequest(...args).send();
  93. }
  94. }
  95.  
  96. class HttpRequestHtml extends HttpRequest {
  97.  
  98. /**
  99. * @param {HttpRequestHtmlParams} param0
  100. */
  101. constructor({
  102. url,
  103. params = {},
  104. pageNr = 0,
  105. pagesMaxCount = 1,
  106. resultTransformer = (resp, _httpRequestHtml) => resp,
  107. hasNextPage = (_resp, _httpRequestHtml, _lastResult) => false,
  108. urlConfiguratorForPageNr = (url, _pageNr) => url,
  109. paramsConfiguratorForPageNr = (params, _pageNr) => params,
  110. } = {}) {
  111. super({ method: 'GET', url, params });
  112.  
  113. Object.assign(this, {
  114. pageNr,
  115. pagesMaxCount: Math.max(0, pagesMaxCount),
  116. resultTransformer,
  117. hasNextPage,
  118. urlConfiguratorForPageNr,
  119. paramsConfiguratorForPageNr,
  120. });
  121. }
  122.  
  123. clone() {
  124. return new HttpRequestHtml({ ...this });
  125. }
  126.  
  127. /**
  128. * @returns {Promise<HttpRequestHtmlResponse|object|Array<object>}
  129. */
  130. async send() {
  131. const results = [];
  132.  
  133. let response = null, requestForPage = null;
  134.  
  135. for (let pageNr = this.pageNr; pageNr < this.pageNr + this.pagesMaxCount; pageNr++) {
  136. requestForPage = Object.assign(this.clone(), {
  137. url: this.urlConfiguratorForPageNr(this.url, pageNr),
  138. params: this.paramsConfiguratorForPageNr({ ...this.params }, pageNr)
  139. });
  140.  
  141. response = await HttpRequest.prototype.send.call(requestForPage);
  142. if (response.status == 200 || response.status == 304) {
  143. response.html = new DOMParser().parseFromString(response.responseText, 'text/html');
  144. }
  145.  
  146. const resultForPage = this.resultTransformer(response, requestForPage);
  147. results.push(resultForPage);
  148.  
  149. if (!this.hasNextPage(response, requestForPage, resultForPage)) {
  150. break;
  151. }
  152. }
  153.  
  154. return this.pagesMaxCount > 1 ? results : results[0];
  155. }
  156.  
  157. /**
  158. * @param {HttpRequestHtmlParams} param0
  159. * @returns {Promise<HttpRequestHtmlResponse|object|Array<object>}
  160. */
  161. static async send(...args) {
  162. return await new HttpRequestHtml(...args).send();
  163. }
  164. }
  165.  
  166. class HttpRequestJSON extends HttpRequest {
  167. /** @param {HttpRequestJSONParams} param0 */
  168. constructor({
  169. method = 'GET',
  170. url,
  171. headers,
  172. data,
  173. params = {},
  174. fallbackResult = null,
  175. contentType = 'application/json',
  176. }) {
  177. super({ method, url: url.href, headers, data, params, contentType, responseType: "json" });
  178. this.fallbackResult = fallbackResult;
  179. }
  180.  
  181. /** @returns {Promise<any>} */
  182. async send() {
  183. const response = await super.send();
  184. if (!response || !response.responseText) {
  185. return this.fallbackResult;
  186. }
  187.  
  188. try {
  189. return JSON.parse(response.responseText);
  190. } catch (error) {
  191. console.log(error);
  192. return this.fallbackResult;
  193. }
  194. }
  195.  
  196. /**
  197. *
  198. * @param {HttpRequestJSONParams} param0
  199. * @returns {Promise<any>}
  200. */
  201. static async send(param0) {
  202. return await new HttpRequestJSON(param0).send();
  203. }
  204. }
  205.  
  206. class HttpRequestBlob extends HttpRequest {
  207. constructor({
  208. method = 'GET',
  209. url,
  210. headers,
  211. data,
  212. params = {},
  213. contentType,
  214. }) {
  215. super({ method, url, headers, data, params, contentType, responseType: 'blob' });
  216. }
  217.  
  218. async send() {
  219. const response = await super.send();
  220.  
  221. /** @type {Blob} */
  222. const blob = response.response;
  223. const data = await new Promise((resolve, reject) => {
  224. const reader = Object.assign(new FileReader(), {
  225.  
  226. onload: (load) => {
  227. resolve(load.target.result);
  228. },
  229.  
  230. onerror: (error) => {
  231. console.log(error);
  232. reject(reader.result);
  233. }
  234.  
  235. });
  236. reader.readAsDataURL(blob);
  237. });
  238. return data;
  239. }
  240.  
  241. static async send(param0) {
  242. return await new HttpRequestBlob(param0).send();
  243. }
  244. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址