GM Requests

Imitating Python's Requests library based on GM_xmlHttpRequest.

目前为 2023-07-03 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/470000/1214515/GM%20Requests.js

  1. // ==UserScript==
  2. // @name GM Requests
  3. // @description Imitating Python's Requests library based on GM_xmlHttpRequest.
  4. // @version 0.0.2
  5. // @author 大碗宽面wtw
  6. // @homepage https://github.com/bigbowl-wtw/gm-requests/
  7. // @supportURL https://github.com/bigbowl-wtw/gm-requests/issues
  8. // @match *://*/*
  9. // @grant GM_xmlhttpRequest
  10. // @license MIT
  11. // @namespace com.github.bigbowl-wtw
  12. // ==/UserScript==
  13.  
  14. (function webpackUniversalModuleDefinition(root, factory) {
  15. if (typeof exports === "object" && typeof module === "object") module.exports = factory(); else if (typeof define === "function" && define.amd) define([], factory); else if (typeof exports === "object") exports["requests"] = factory(); else root["requests"] = factory();
  16. })(self, (() => (() => {
  17. "use strict";
  18. var __webpack_require__ = {};
  19. (() => {
  20. __webpack_require__.d = (exports, definition) => {
  21. for (var key in definition) {
  22. if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  23. Object.defineProperty(exports, key, {
  24. enumerable: true,
  25. get: definition[key]
  26. });
  27. }
  28. }
  29. };
  30. })();
  31. (() => {
  32. __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
  33. })();
  34. (() => {
  35. __webpack_require__.r = exports => {
  36. if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
  37. Object.defineProperty(exports, Symbol.toStringTag, {
  38. value: "Module"
  39. });
  40. }
  41. Object.defineProperty(exports, "__esModule", {
  42. value: true
  43. });
  44. };
  45. })();
  46. var __webpack_exports__ = {};
  47. __webpack_require__.r(__webpack_exports__);
  48. __webpack_require__.d(__webpack_exports__, {
  49. Session: () => Session,
  50. get: () => get,
  51. post: () => post,
  52. session: () => session
  53. });
  54. var ErrorStatus;
  55. (function(ErrorStatus) {
  56. ErrorStatus[ErrorStatus["BadRequest"] = 400] = "BadRequest";
  57. ErrorStatus[ErrorStatus["Unauthorized"] = 401] = "Unauthorized";
  58. ErrorStatus[ErrorStatus["Forbidden"] = 403] = "Forbidden";
  59. ErrorStatus[ErrorStatus["NotFound"] = 404] = "NotFound";
  60. ErrorStatus[ErrorStatus["MethodNotAllowed"] = 405] = "MethodNotAllowed";
  61. ErrorStatus[ErrorStatus["RequestTimeout"] = 408] = "RequestTimeout";
  62. ErrorStatus[ErrorStatus["TooManyRequests"] = 429] = "TooManyRequests";
  63. ErrorStatus[ErrorStatus["InternalServerError"] = 500] = "InternalServerError";
  64. ErrorStatus[ErrorStatus["BadGateway"] = 502] = "BadGateway";
  65. ErrorStatus[ErrorStatus["ServiceUnavailable"] = 503] = "ServiceUnavailable";
  66. })(ErrorStatus || (ErrorStatus = {}));
  67. function utils_assign(target, ...rest) {
  68. const __assign = Object.assign || function(t, ...others) {
  69. for (let s, i = 0, n = others.length; i < n; i++) {
  70. s = others[i];
  71. for (const p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  72. }
  73. return t;
  74. };
  75. return __assign.call(this, target, ...rest);
  76. }
  77. function assignDeepCopy(target, ...rest) {
  78. rest = rest.filter((r => r !== undefined));
  79. utils_assign(target, ...rest);
  80. return utils_assign.call(this, target, ...JSON.parse(JSON.stringify(rest)));
  81. }
  82. function bodyToString(data) {
  83. if (Object.values(data).some((v => typeof v.toString !== "function"))) throw new TypeError("value must has `.toString`");
  84. return Object.entries(data).map((([key, value]) => `${key}=${encodeURIComponent(value.toString())}`)).join("&");
  85. }
  86. class SimpleCookieJar {
  87. get empty() {
  88. return !Object.keys(this.cookies).length;
  89. }
  90. constructor(cookies) {
  91. var _a;
  92. this.never = new Set;
  93. this.setCookies((_a = cookies) !== null && _a !== void 0 ? _a : {});
  94. }
  95. update(cookies) {
  96. utils_assign(this.cookies, this.normalizeCookie(cookies));
  97. }
  98. updateFromString(cookieStringArray) {
  99. if (typeof cookieStringArray === "string") cookieStringArray = [ cookieStringArray ];
  100. this.update(cookieStringArray);
  101. }
  102. differenceUpdate(cookies) {
  103. let cookieEntries;
  104. if (Array.isArray(cookies)) cookieEntries = cookies.map(this.stringToEntry); else cookieEntries = Object.entries(isCookieJar(cookies) ? cookies.cookies : cookies);
  105. const set = new Set(Object.keys(this.cookies));
  106. cookieEntries = cookieEntries.filter((([name]) => !set.has(name)));
  107. this.update(Object.fromEntries(cookieEntries));
  108. }
  109. deleteFromString(cookieStringArray) {
  110. if (typeof cookieStringArray === "string") cookieStringArray = [ cookieStringArray ];
  111. const names = cookieStringArray.map(this.stringToEntry).map((([name]) => name));
  112. names.forEach((name => {
  113. this.never.add(name);
  114. delete this.cookies[name];
  115. }));
  116. }
  117. setCookies(cookies) {
  118. this.cookies = new Proxy(this.normalizeCookie(cookies), {
  119. set: (target, name, value) => {
  120. if (this.never.has(name)) return true;
  121. target[name] = value;
  122. return true;
  123. }
  124. });
  125. }
  126. toString() {
  127. return Object.entries(this.cookies).map((([k, v]) => `${k}=${v}`)).join(";");
  128. }
  129. parseCookieString(cookieStrings) {
  130. return Object.fromEntries(cookieStrings.map(this.stringToEntry));
  131. }
  132. normalizeCookie(cookies) {
  133. if (Array.isArray(cookies)) return this.parseCookieString(cookies);
  134. if (isCookieJar(cookies)) return cookies.cookies;
  135. return cookies;
  136. }
  137. stringToEntry(cookieString) {
  138. return cookieString.slice(0, cookieString.indexOf(";")).split("=");
  139. }
  140. }
  141. function isCookieJar(obj) {
  142. return typeof obj.update === "function";
  143. }
  144. var __rest = undefined && undefined.__rest || function(s, e) {
  145. var t = {};
  146. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  147. if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  148. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  149. }
  150. return t;
  151. };
  152. class Header {
  153. constructor(headers) {
  154. this.cookies = new SimpleCookieJar;
  155. if (!headers) {
  156. this.headers = {};
  157. return;
  158. }
  159. const {cookie} = headers, others = __rest(headers, [ "cookie" ]);
  160. this.headers = others;
  161. if (cookie) {
  162. this.cookies.update(cookie);
  163. }
  164. }
  165. setFromString(headerString) {
  166. const entrise = headerString.split("\r\n").map((kv => kv.split(":"))).map((([k, v]) => [ k.toLowerCase(), v.trim() ]));
  167. for (const [name, value] of entrise) {
  168. const header = this.headers[name];
  169. if (header) {
  170. if (typeof header === "string") this.headers[name] = [ header ];
  171. this.headers[name].push(value);
  172. } else {
  173. this.headers[name] = value;
  174. }
  175. }
  176. return this;
  177. }
  178. update(headers) {
  179. if (isIHeader(headers)) {
  180. this.cookies.update(headers.cookies);
  181. this.update(headers.headers);
  182. } else {
  183. const _a = headers !== null && headers !== void 0 ? headers : {}, {cookie} = _a, others = __rest(_a, [ "cookie" ]);
  184. utils_assign(this.headers, others);
  185. if (cookie) {
  186. this.cookies.update(cookie);
  187. }
  188. }
  189. }
  190. getHeaders() {
  191. if (!Object.keys(this.headers).length) {
  192. if (this.cookies.empty) return {};
  193. return {
  194. cookie: this.cookies.toString()
  195. };
  196. }
  197. const headers = {};
  198. for (const [name, value] of Object.entries(this.headers)) headers[name] = value.toString();
  199. return Object.assign(Object.assign({}, headers), {
  200. cookie: this.cookies.toString()
  201. });
  202. }
  203. append(header, value) {
  204. if (header === "cookie") this.cookies.update([ header ]); else if (!this[header]) this[header] = value; else if (!Array.isArray(header)) this[header] = [ value ].concat(this[header]); else this[header].concat(value);
  205. }
  206. get(name) {
  207. return this.headers[name];
  208. }
  209. }
  210. function isIHeader(obj) {
  211. return typeof obj.update === "function";
  212. }
  213. var __awaiter = undefined && undefined.__awaiter || function(thisArg, _arguments, P, generator) {
  214. function adopt(value) {
  215. return value instanceof P ? value : new P((function(resolve) {
  216. resolve(value);
  217. }));
  218. }
  219. return new (P || (P = Promise))((function(resolve, reject) {
  220. function fulfilled(value) {
  221. try {
  222. step(generator.next(value));
  223. } catch (e) {
  224. reject(e);
  225. }
  226. }
  227. function rejected(value) {
  228. try {
  229. step(generator["throw"](value));
  230. } catch (e) {
  231. reject(e);
  232. }
  233. }
  234. function step(result) {
  235. result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
  236. }
  237. step((generator = generator.apply(thisArg, _arguments || [])).next());
  238. }));
  239. };
  240. var session_rest = undefined && undefined.__rest || function(s, e) {
  241. var t = {};
  242. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  243. if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  244. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  245. }
  246. return t;
  247. };
  248. class Details {
  249. constructor(url, method, options) {
  250. this.pendings = [];
  251. this.url = url;
  252. this.method = method;
  253. this.finalHeader = new Header;
  254. if (options) {
  255. const {query, json, data, cookie, auth, headers} = options, others = session_rest(options, [ "query", "json", "data", "cookie", "auth", "headers" ]);
  256. this.query = query;
  257. this.json = json;
  258. this.data = data;
  259. this.cookie = cookie;
  260. this.auth = auth;
  261. this.headers = headers;
  262. this.others = others;
  263. }
  264. }
  265. build(session) {
  266. return __awaiter(this, void 0, void 0, (function*() {
  267. this.buildURL().buildHeaderAndCookie(session).buildAuth(session);
  268. this.pendings.concat(session.buildHooks.map((hook => hook.call(this, session))));
  269. return this.toDetails();
  270. }));
  271. }
  272. buildURL() {
  273. this.parseQuery(this.query);
  274. return this;
  275. }
  276. buildHeaderAndCookie(session) {
  277. const finalCookie = this.finalHeader.cookies;
  278. if (!session.cookies.empty) finalCookie.update(session.cookies);
  279. if (this.cookie) finalCookie.update(this.cookie);
  280. this.finalHeader.update(session.headers);
  281. if (this.headers) this.finalHeader.update(this.headers);
  282. return this;
  283. }
  284. buildAuth(session) {
  285. var _a;
  286. this.pendings.push((_a = session.auth) === null || _a === void 0 ? void 0 : _a.build(this.finalHeader));
  287. return this;
  288. }
  289. buildBody() {
  290. if (this.json) {
  291. const contentType = "application/json";
  292. this.finalHeader.update({
  293. "Content-Type": contentType
  294. });
  295. const data = JSON.stringify(this.json);
  296. this.finalData = data;
  297. return this;
  298. }
  299. if (this.data) {
  300. if (typeof this.data === "string") {
  301. this.finalData = this.data;
  302. return this;
  303. }
  304. if (this.data instanceof FormData) return this;
  305. const contentType = "application/x-www-form-urlencoded";
  306. this.finalHeader.update({
  307. "Content-Type": contentType
  308. });
  309. this.finalData = bodyToString(this.data);
  310. return this;
  311. }
  312. return this;
  313. }
  314. toDetails() {
  315. return __awaiter(this, void 0, void 0, (function*() {
  316. yield Promise.all(this.pendings);
  317. const url = this.url.toString();
  318. this.buildBody();
  319. const details = Object.assign({
  320. url,
  321. method: this.method,
  322. headers: this.finalHeader.getHeaders()
  323. }, this.others);
  324. if (this.finalData) details.data = this.finalData;
  325. return details;
  326. }));
  327. }
  328. parseQuery(query) {
  329. let url;
  330. if (typeof this.url === "string") url = new URL(this.url); else url = this.url;
  331. if (query) Object.entries(query).filter((([_, v]) => typeof v === "string")).forEach((([k, v]) => url.searchParams.append(k, v.toString())));
  332. this.url = url;
  333. }
  334. }
  335. class Session {
  336. constructor() {
  337. this.buildHooks = [];
  338. const headers = new Header;
  339. Object.defineProperty(this, "headers", {
  340. get: () => headers,
  341. set(value) {
  342. headers.update(value);
  343. }
  344. });
  345. Object.defineProperty(this, "cookies", {
  346. get: () => headers.cookies,
  347. set(value) {
  348. headers.cookies.setCookies(value);
  349. }
  350. });
  351. }
  352. get(url, options) {
  353. return __awaiter(this, void 0, void 0, (function*() {
  354. return this.request("GET", url, options);
  355. }));
  356. }
  357. post(url, options) {
  358. return __awaiter(this, void 0, void 0, (function*() {
  359. return this.request("POST", url, options);
  360. }));
  361. }
  362. request(method, url, options) {
  363. return __awaiter(this, void 0, void 0, (function*() {
  364. const details = new Details(url, method, options);
  365. return new Promise(((resolve, reject) => {
  366. if (!options.onload) {
  367. details.others.onload = resp => {
  368. if (!this.cookies.empty) {
  369. const respHeaders = (new Header).setFromString(resp.responseHeaders);
  370. this.cookies.deleteFromString(respHeaders["set-cookie"]);
  371. }
  372. if (resp.status === 200 && !(resp.status in ErrorStatus)) resolve((options === null || options === void 0 ? void 0 : options.responseType) ? resp.response : resp); else reject(resp);
  373. };
  374. }
  375. if (!options.onerror) details.others.onerror = resp => reject(resp);
  376. details.build(this).then((dtl => GM_xmlhttpRequest(dtl)));
  377. }));
  378. }));
  379. }
  380. registerBuildHook(hook) {
  381. this.buildHooks.push(hook);
  382. }
  383. }
  384. function get(url, query, options) {
  385. return (new Session).get(url, Object.assign({
  386. query
  387. }, options));
  388. }
  389. function post(url, options) {
  390. return (new Session).post(url, Object.assign({}, options));
  391. }
  392. function session() {
  393. return new Session;
  394. }
  395. return __webpack_exports__;
  396. })()));