mirror of
https://github.com/oven-sh/setup-bun.git
synced 2025-02-24 03:00:39 +08:00
214 lines
12 KiB
JavaScript
214 lines
12 KiB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
import { __assign, __awaiter, __generator } from "tslib";
|
|
import AbortController from "abort-controller";
|
|
import FormData from "form-data";
|
|
import { HttpHeaders } from "./httpHeaders";
|
|
import { RestError } from "./restError";
|
|
import { Transform } from "stream";
|
|
var FetchHttpClient = /** @class */ (function () {
|
|
function FetchHttpClient() {
|
|
}
|
|
FetchHttpClient.prototype.sendRequest = function (httpRequest) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var abortController, abortListener, formData, requestForm_1, appendFormValue, _i, _a, formKey, formValue, j, contentType, body, loadedBytes_1, uploadReportStream, platformSpecificRequestInit, requestInit, operationResponse, response, headers, _b, _c, onDownloadProgress_1, responseBody, loadedBytes_2, downloadReportStream, length_1, error_1, fetchError, uploadStreamDone, downloadStreamDone;
|
|
return __generator(this, function (_d) {
|
|
switch (_d.label) {
|
|
case 0:
|
|
if (!httpRequest && typeof httpRequest !== "object") {
|
|
throw new Error("'httpRequest' (WebResource) cannot be null or undefined and must be of type object.");
|
|
}
|
|
abortController = new AbortController();
|
|
if (httpRequest.abortSignal) {
|
|
if (httpRequest.abortSignal.aborted) {
|
|
throw new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, httpRequest);
|
|
}
|
|
abortListener = function (event) {
|
|
if (event.type === "abort") {
|
|
abortController.abort();
|
|
}
|
|
};
|
|
httpRequest.abortSignal.addEventListener("abort", abortListener);
|
|
}
|
|
if (httpRequest.timeout) {
|
|
setTimeout(function () {
|
|
abortController.abort();
|
|
}, httpRequest.timeout);
|
|
}
|
|
if (httpRequest.formData) {
|
|
formData = httpRequest.formData;
|
|
requestForm_1 = new FormData();
|
|
appendFormValue = function (key, value) {
|
|
// value function probably returns a stream so we can provide a fresh stream on each retry
|
|
if (typeof value === "function") {
|
|
value = value();
|
|
}
|
|
if (value && value.hasOwnProperty("value") && value.hasOwnProperty("options")) {
|
|
requestForm_1.append(key, value.value, value.options);
|
|
}
|
|
else {
|
|
requestForm_1.append(key, value);
|
|
}
|
|
};
|
|
for (_i = 0, _a = Object.keys(formData); _i < _a.length; _i++) {
|
|
formKey = _a[_i];
|
|
formValue = formData[formKey];
|
|
if (Array.isArray(formValue)) {
|
|
for (j = 0; j < formValue.length; j++) {
|
|
appendFormValue(formKey, formValue[j]);
|
|
}
|
|
}
|
|
else {
|
|
appendFormValue(formKey, formValue);
|
|
}
|
|
}
|
|
httpRequest.body = requestForm_1;
|
|
httpRequest.formData = undefined;
|
|
contentType = httpRequest.headers.get("Content-Type");
|
|
if (contentType && contentType.indexOf("multipart/form-data") !== -1) {
|
|
if (typeof requestForm_1.getBoundary === "function") {
|
|
httpRequest.headers.set("Content-Type", "multipart/form-data; boundary=" + requestForm_1.getBoundary());
|
|
}
|
|
else {
|
|
// browser will automatically apply a suitable content-type header
|
|
httpRequest.headers.remove("Content-Type");
|
|
}
|
|
}
|
|
}
|
|
body = httpRequest.body
|
|
? typeof httpRequest.body === "function"
|
|
? httpRequest.body()
|
|
: httpRequest.body
|
|
: undefined;
|
|
if (httpRequest.onUploadProgress && httpRequest.body) {
|
|
loadedBytes_1 = 0;
|
|
uploadReportStream = new Transform({
|
|
transform: function (chunk, _encoding, callback) {
|
|
loadedBytes_1 += chunk.length;
|
|
httpRequest.onUploadProgress({ loadedBytes: loadedBytes_1 });
|
|
callback(undefined, chunk);
|
|
},
|
|
});
|
|
if (isReadableStream(body)) {
|
|
body.pipe(uploadReportStream);
|
|
}
|
|
else {
|
|
uploadReportStream.end(body);
|
|
}
|
|
body = uploadReportStream;
|
|
}
|
|
return [4 /*yield*/, this.prepareRequest(httpRequest)];
|
|
case 1:
|
|
platformSpecificRequestInit = _d.sent();
|
|
requestInit = __assign({ body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, signal: abortController.signal, redirect: "manual" }, platformSpecificRequestInit);
|
|
_d.label = 2;
|
|
case 2:
|
|
_d.trys.push([2, 8, 9, 10]);
|
|
return [4 /*yield*/, this.fetch(httpRequest.url, requestInit)];
|
|
case 3:
|
|
response = _d.sent();
|
|
headers = parseHeaders(response.headers);
|
|
_b = {
|
|
headers: headers,
|
|
request: httpRequest,
|
|
status: response.status,
|
|
readableStreamBody: httpRequest.streamResponseBody
|
|
? response.body
|
|
: undefined
|
|
};
|
|
if (!!httpRequest.streamResponseBody) return [3 /*break*/, 5];
|
|
return [4 /*yield*/, response.text()];
|
|
case 4:
|
|
_c = _d.sent();
|
|
return [3 /*break*/, 6];
|
|
case 5:
|
|
_c = undefined;
|
|
_d.label = 6;
|
|
case 6:
|
|
operationResponse = (_b.bodyAsText = _c,
|
|
_b.redirected = response.redirected,
|
|
_b.url = response.url,
|
|
_b);
|
|
onDownloadProgress_1 = httpRequest.onDownloadProgress;
|
|
if (onDownloadProgress_1) {
|
|
responseBody = response.body || undefined;
|
|
if (isReadableStream(responseBody)) {
|
|
loadedBytes_2 = 0;
|
|
downloadReportStream = new Transform({
|
|
transform: function (chunk, _encoding, callback) {
|
|
loadedBytes_2 += chunk.length;
|
|
onDownloadProgress_1({ loadedBytes: loadedBytes_2 });
|
|
callback(undefined, chunk);
|
|
},
|
|
});
|
|
responseBody.pipe(downloadReportStream);
|
|
operationResponse.readableStreamBody = downloadReportStream;
|
|
}
|
|
else {
|
|
length_1 = parseInt(headers.get("Content-Length")) || undefined;
|
|
if (length_1) {
|
|
// Calling callback for non-stream response for consistency with browser
|
|
onDownloadProgress_1({ loadedBytes: length_1 });
|
|
}
|
|
}
|
|
}
|
|
return [4 /*yield*/, this.processRequest(operationResponse)];
|
|
case 7:
|
|
_d.sent();
|
|
return [2 /*return*/, operationResponse];
|
|
case 8:
|
|
error_1 = _d.sent();
|
|
fetchError = error_1;
|
|
if (fetchError.code === "ENOTFOUND") {
|
|
throw new RestError(fetchError.message, RestError.REQUEST_SEND_ERROR, undefined, httpRequest);
|
|
}
|
|
else if (fetchError.type === "aborted") {
|
|
throw new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, httpRequest);
|
|
}
|
|
throw fetchError;
|
|
case 9:
|
|
// clean up event listener
|
|
if (httpRequest.abortSignal && abortListener) {
|
|
uploadStreamDone = Promise.resolve();
|
|
if (isReadableStream(body)) {
|
|
uploadStreamDone = isStreamComplete(body);
|
|
}
|
|
downloadStreamDone = Promise.resolve();
|
|
if (isReadableStream(operationResponse === null || operationResponse === void 0 ? void 0 : operationResponse.readableStreamBody)) {
|
|
downloadStreamDone = isStreamComplete(operationResponse.readableStreamBody);
|
|
}
|
|
Promise.all([uploadStreamDone, downloadStreamDone])
|
|
.then(function () {
|
|
var _a;
|
|
(_a = httpRequest.abortSignal) === null || _a === void 0 ? void 0 : _a.removeEventListener("abort", abortListener);
|
|
return;
|
|
})
|
|
.catch(function (_e) { });
|
|
}
|
|
return [7 /*endfinally*/];
|
|
case 10: return [2 /*return*/];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
return FetchHttpClient;
|
|
}());
|
|
export { FetchHttpClient };
|
|
function isReadableStream(body) {
|
|
return body && typeof body.pipe === "function";
|
|
}
|
|
function isStreamComplete(stream) {
|
|
return new Promise(function (resolve) {
|
|
stream.on("close", resolve);
|
|
stream.on("end", resolve);
|
|
stream.on("error", resolve);
|
|
});
|
|
}
|
|
export function parseHeaders(headers) {
|
|
var httpHeaders = new HttpHeaders();
|
|
headers.forEach(function (value, key) {
|
|
httpHeaders.set(key, value);
|
|
});
|
|
return httpHeaders;
|
|
}
|
|
//# sourceMappingURL=fetchHttpClient.js.map
|