request.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. // src/request.ts
  20. var request_exports = {};
  21. __export(request_exports, {
  22. GlobalRequest: () => GlobalRequest,
  23. Request: () => Request,
  24. RequestError: () => RequestError,
  25. abortControllerKey: () => abortControllerKey,
  26. getAbortController: () => getAbortController,
  27. newRequest: () => newRequest,
  28. toRequestError: () => toRequestError,
  29. wrapBodyStream: () => wrapBodyStream
  30. });
  31. module.exports = __toCommonJS(request_exports);
  32. var import_node_http2 = require("http2");
  33. var import_node_stream = require("stream");
  34. var RequestError = class extends Error {
  35. constructor(message, options) {
  36. super(message, options);
  37. this.name = "RequestError";
  38. }
  39. };
  40. var toRequestError = (e) => {
  41. if (e instanceof RequestError) {
  42. return e;
  43. }
  44. return new RequestError(e.message, { cause: e });
  45. };
  46. var GlobalRequest = global.Request;
  47. var Request = class extends GlobalRequest {
  48. constructor(input, options) {
  49. if (typeof input === "object" && getRequestCache in input) {
  50. input = input[getRequestCache]();
  51. }
  52. if (typeof options?.body?.getReader !== "undefined") {
  53. ;
  54. options.duplex ??= "half";
  55. }
  56. super(input, options);
  57. }
  58. };
  59. var newHeadersFromIncoming = (incoming) => {
  60. const headerRecord = [];
  61. const rawHeaders = incoming.rawHeaders;
  62. for (let i = 0; i < rawHeaders.length; i += 2) {
  63. const { [i]: key, [i + 1]: value } = rawHeaders;
  64. if (key.charCodeAt(0) !== /*:*/
  65. 58) {
  66. headerRecord.push([key, value]);
  67. }
  68. }
  69. return new Headers(headerRecord);
  70. };
  71. var wrapBodyStream = Symbol("wrapBodyStream");
  72. var newRequestFromIncoming = (method, url, headers, incoming, abortController) => {
  73. const init = {
  74. method,
  75. headers,
  76. signal: abortController.signal
  77. };
  78. if (method === "TRACE") {
  79. init.method = "GET";
  80. const req = new Request(url, init);
  81. Object.defineProperty(req, "method", {
  82. get() {
  83. return "TRACE";
  84. }
  85. });
  86. return req;
  87. }
  88. if (!(method === "GET" || method === "HEAD")) {
  89. if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) {
  90. init.body = new ReadableStream({
  91. start(controller) {
  92. controller.enqueue(incoming.rawBody);
  93. controller.close();
  94. }
  95. });
  96. } else if (incoming[wrapBodyStream]) {
  97. let reader;
  98. init.body = new ReadableStream({
  99. async pull(controller) {
  100. try {
  101. reader ||= import_node_stream.Readable.toWeb(incoming).getReader();
  102. const { done, value } = await reader.read();
  103. if (done) {
  104. controller.close();
  105. } else {
  106. controller.enqueue(value);
  107. }
  108. } catch (error) {
  109. controller.error(error);
  110. }
  111. }
  112. });
  113. } else {
  114. init.body = import_node_stream.Readable.toWeb(incoming);
  115. }
  116. }
  117. return new Request(url, init);
  118. };
  119. var getRequestCache = Symbol("getRequestCache");
  120. var requestCache = Symbol("requestCache");
  121. var incomingKey = Symbol("incomingKey");
  122. var urlKey = Symbol("urlKey");
  123. var headersKey = Symbol("headersKey");
  124. var abortControllerKey = Symbol("abortControllerKey");
  125. var getAbortController = Symbol("getAbortController");
  126. var requestPrototype = {
  127. get method() {
  128. return this[incomingKey].method || "GET";
  129. },
  130. get url() {
  131. return this[urlKey];
  132. },
  133. get headers() {
  134. return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
  135. },
  136. [getAbortController]() {
  137. this[getRequestCache]();
  138. return this[abortControllerKey];
  139. },
  140. [getRequestCache]() {
  141. this[abortControllerKey] ||= new AbortController();
  142. return this[requestCache] ||= newRequestFromIncoming(
  143. this.method,
  144. this[urlKey],
  145. this.headers,
  146. this[incomingKey],
  147. this[abortControllerKey]
  148. );
  149. }
  150. };
  151. [
  152. "body",
  153. "bodyUsed",
  154. "cache",
  155. "credentials",
  156. "destination",
  157. "integrity",
  158. "mode",
  159. "redirect",
  160. "referrer",
  161. "referrerPolicy",
  162. "signal",
  163. "keepalive"
  164. ].forEach((k) => {
  165. Object.defineProperty(requestPrototype, k, {
  166. get() {
  167. return this[getRequestCache]()[k];
  168. }
  169. });
  170. });
  171. ["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
  172. Object.defineProperty(requestPrototype, k, {
  173. value: function() {
  174. return this[getRequestCache]()[k]();
  175. }
  176. });
  177. });
  178. Object.setPrototypeOf(requestPrototype, Request.prototype);
  179. var newRequest = (incoming, defaultHostname) => {
  180. const req = Object.create(requestPrototype);
  181. req[incomingKey] = incoming;
  182. const incomingUrl = incoming.url || "";
  183. if (incomingUrl[0] !== "/" && // short-circuit for performance. most requests are relative URL.
  184. (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
  185. if (incoming instanceof import_node_http2.Http2ServerRequest) {
  186. throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
  187. }
  188. try {
  189. const url2 = new URL(incomingUrl);
  190. req[urlKey] = url2.href;
  191. } catch (e) {
  192. throw new RequestError("Invalid absolute URL", { cause: e });
  193. }
  194. return req;
  195. }
  196. const host = (incoming instanceof import_node_http2.Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname;
  197. if (!host) {
  198. throw new RequestError("Missing host header");
  199. }
  200. let scheme;
  201. if (incoming instanceof import_node_http2.Http2ServerRequest) {
  202. scheme = incoming.scheme;
  203. if (!(scheme === "http" || scheme === "https")) {
  204. throw new RequestError("Unsupported scheme");
  205. }
  206. } else {
  207. scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
  208. }
  209. const url = new URL(`${scheme}://${host}${incomingUrl}`);
  210. if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
  211. throw new RequestError("Invalid host header");
  212. }
  213. req[urlKey] = url.href;
  214. return req;
  215. };
  216. // Annotate the CommonJS export names for ESM import in node:
  217. 0 && (module.exports = {
  218. GlobalRequest,
  219. Request,
  220. RequestError,
  221. abortControllerKey,
  222. getAbortController,
  223. newRequest,
  224. toRequestError,
  225. wrapBodyStream
  226. });