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

QingJ © 2025

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