geturl.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import http from "http";
  2. import https from "https";
  3. import { gunzipSync } from "zlib";
  4. import { assert, makeError } from "./errors.js";
  5. import { getBytes } from "./data.js";
  6. /**
  7. * @_ignore:
  8. */
  9. export function createGetUrl(options) {
  10. async function getUrl(req, signal) {
  11. // Make sure we weren't cancelled before sending
  12. assert(signal == null || !signal.cancelled, "request cancelled before sending", "CANCELLED");
  13. const protocol = req.url.split(":")[0].toLowerCase();
  14. assert(protocol === "http" || protocol === "https", `unsupported protocol ${protocol}`, "UNSUPPORTED_OPERATION", {
  15. info: { protocol },
  16. operation: "request"
  17. });
  18. assert(protocol === "https" || !req.credentials || req.allowInsecureAuthentication, "insecure authorized connections unsupported", "UNSUPPORTED_OPERATION", {
  19. operation: "request"
  20. });
  21. const method = req.method;
  22. const headers = Object.assign({}, req.headers);
  23. const reqOptions = { method, headers };
  24. if (options) {
  25. if (options.agent) {
  26. reqOptions.agent = options.agent;
  27. }
  28. }
  29. // Create a Node-specific AbortController, if available
  30. let abort = null;
  31. try {
  32. abort = new AbortController();
  33. reqOptions.abort = abort.signal;
  34. }
  35. catch (e) {
  36. console.log(e);
  37. }
  38. const request = ((protocol === "http") ? http : https).request(req.url, reqOptions);
  39. request.setTimeout(req.timeout);
  40. const body = req.body;
  41. if (body) {
  42. request.write(Buffer.from(body));
  43. }
  44. request.end();
  45. return new Promise((resolve, reject) => {
  46. if (signal) {
  47. signal.addListener(() => {
  48. if (abort) {
  49. abort.abort();
  50. }
  51. reject(makeError("request cancelled", "CANCELLED"));
  52. });
  53. }
  54. request.on("timeout", () => {
  55. reject(makeError("request timeout", "TIMEOUT"));
  56. });
  57. request.once("response", (resp) => {
  58. const statusCode = resp.statusCode || 0;
  59. const statusMessage = resp.statusMessage || "";
  60. const headers = Object.keys(resp.headers || {}).reduce((accum, name) => {
  61. let value = resp.headers[name] || "";
  62. if (Array.isArray(value)) {
  63. value = value.join(", ");
  64. }
  65. accum[name] = value;
  66. return accum;
  67. }, {});
  68. let body = null;
  69. //resp.setEncoding("utf8");
  70. resp.on("data", (chunk) => {
  71. if (signal) {
  72. try {
  73. signal.checkSignal();
  74. }
  75. catch (error) {
  76. return reject(error);
  77. }
  78. }
  79. if (body == null) {
  80. body = chunk;
  81. }
  82. else {
  83. const newBody = new Uint8Array(body.length + chunk.length);
  84. newBody.set(body, 0);
  85. newBody.set(chunk, body.length);
  86. body = newBody;
  87. }
  88. });
  89. resp.on("end", () => {
  90. if (headers["content-encoding"] === "gzip" && body) {
  91. body = getBytes(gunzipSync(body));
  92. }
  93. resolve({ statusCode, statusMessage, headers, body });
  94. });
  95. resp.on("error", (error) => {
  96. //@TODO: Should this just return nornal response with a server error?
  97. error.response = { statusCode, statusMessage, headers, body };
  98. reject(error);
  99. });
  100. });
  101. request.on("error", (error) => { reject(error); });
  102. });
  103. }
  104. return getUrl;
  105. }
  106. // @TODO: remove in v7; provided for backwards compat
  107. const defaultGetUrl = createGetUrl({});
  108. /**
  109. * @_ignore:
  110. */
  111. export async function getUrl(req, signal) {
  112. return defaultGetUrl(req, signal);
  113. }
  114. //# sourceMappingURL=geturl.js.map