feat: complete Ancestor quote bot with production-ready Docker support
This commit is contained in:
109
node_modules/matrix-js-sdk/lib/http-api/utils.js
generated
vendored
109
node_modules/matrix-js-sdk/lib/http-api/utils.js
generated
vendored
@@ -1,5 +1,18 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.anySignal = anySignal;
|
||||
exports.parseErrorResponse = parseErrorResponse;
|
||||
exports.retryNetworkOperation = retryNetworkOperation;
|
||||
exports.timeoutSignal = timeoutSignal;
|
||||
var _contentType3 = require("content-type");
|
||||
var _logger = require("../logger");
|
||||
var _utils = require("../utils");
|
||||
var _errors = require("./errors");
|
||||
/*
|
||||
Copyright 2022 - 2024 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,20 +27,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { parse as parseContentType } from "content-type";
|
||||
import { logger } from "../logger.js";
|
||||
import { sleep } from "../utils.js";
|
||||
import { ConnectionError, HTTPError, MatrixError, MatrixSafetyError, MatrixSafetyErrorCode, safeGetRetryAfterMs } from "./errors.js";
|
||||
|
||||
// Ponyfill for https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout
|
||||
export function timeoutSignal(ms) {
|
||||
function timeoutSignal(ms) {
|
||||
const controller = new AbortController();
|
||||
setTimeout(() => {
|
||||
controller.abort();
|
||||
}, ms);
|
||||
return controller.signal;
|
||||
}
|
||||
export function anySignal(signals) {
|
||||
function anySignal(signals) {
|
||||
const controller = new AbortController();
|
||||
function cleanup() {
|
||||
for (const signal of signals) {
|
||||
@@ -61,35 +69,28 @@ export function anySignal(signals) {
|
||||
* @param body - raw body of the response
|
||||
* @returns
|
||||
*/
|
||||
export function parseErrorResponse(response, body) {
|
||||
const httpHeaders = isXhr(response) ? new Headers(response.getAllResponseHeaders().trim().split(/[\r\n]+/).map(header => {
|
||||
const colonIdx = header.indexOf(":");
|
||||
return [header.substring(0, colonIdx), header.substring(colonIdx + 1)];
|
||||
})) : response.headers;
|
||||
function parseErrorResponse(response, body) {
|
||||
var _contentType, _contentType2;
|
||||
let contentType;
|
||||
try {
|
||||
contentType = getResponseContentType(httpHeaders);
|
||||
contentType = getResponseContentType(response);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
if (contentType?.type === "application/json" && body) {
|
||||
const errorBody = JSON.parse(body);
|
||||
if (errorBody.errcode && MatrixSafetyErrorCode.matches(errorBody.errcode)) {
|
||||
return new MatrixSafetyError(errorBody, response.status, isXhr(response) ? response.responseURL : response.url, undefined, httpHeaders);
|
||||
}
|
||||
return new MatrixError(errorBody, response.status, isXhr(response) ? response.responseURL : response.url, undefined, httpHeaders);
|
||||
if (((_contentType = contentType) === null || _contentType === void 0 ? void 0 : _contentType.type) === "application/json" && body) {
|
||||
return new _errors.MatrixError(JSON.parse(body), response.status, isXhr(response) ? response.responseURL : response.url);
|
||||
}
|
||||
if (contentType?.type === "text/plain") {
|
||||
return new HTTPError(`Server returned ${response.status} error: ${body}`, response.status, httpHeaders);
|
||||
if (((_contentType2 = contentType) === null || _contentType2 === void 0 ? void 0 : _contentType2.type) === "text/plain") {
|
||||
return new _errors.HTTPError(`Server returned ${response.status} error: ${body}`, response.status);
|
||||
}
|
||||
return new HTTPError(`Server returned ${response.status} error`, response.status, httpHeaders);
|
||||
return new _errors.HTTPError(`Server returned ${response.status} error`, response.status);
|
||||
}
|
||||
function isXhr(response) {
|
||||
return "getResponseHeader" in response;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract the Content-Type header from response headers, and
|
||||
* extract the Content-Type header from the response object, and
|
||||
* parse it to a `{type, parameters}` object.
|
||||
*
|
||||
* returns null if no content-type header could be found.
|
||||
@@ -97,10 +98,19 @@ function isXhr(response) {
|
||||
* @param response - response object
|
||||
* @returns parsed content-type header, or null if not found
|
||||
*/
|
||||
function getResponseContentType(headers) {
|
||||
const contentType = headers.get("Content-Type");
|
||||
if (contentType === null) return null;
|
||||
return parseContentType(contentType);
|
||||
function getResponseContentType(response) {
|
||||
let contentType;
|
||||
if (isXhr(response)) {
|
||||
contentType = response.getResponseHeader("Content-Type");
|
||||
} else {
|
||||
contentType = response.headers.get("Content-Type");
|
||||
}
|
||||
if (!contentType) return null;
|
||||
try {
|
||||
return (0, _contentType3.parse)(contentType);
|
||||
} catch (e) {
|
||||
throw new Error(`Error parsing Content-Type '${contentType}': ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,19 +120,19 @@ function getResponseContentType(headers) {
|
||||
* @returns the result of the network operation
|
||||
* @throws {@link ConnectionError} If after maxAttempts the callback still throws ConnectionError
|
||||
*/
|
||||
export async function retryNetworkOperation(maxAttempts, callback) {
|
||||
async function retryNetworkOperation(maxAttempts, callback) {
|
||||
let attempts = 0;
|
||||
let lastConnectionError = null;
|
||||
while (attempts < maxAttempts) {
|
||||
try {
|
||||
if (attempts > 0) {
|
||||
const timeout = 1000 * Math.pow(2, attempts);
|
||||
logger.log(`network operation failed ${attempts} times, retrying in ${timeout}ms...`);
|
||||
await sleep(timeout);
|
||||
_logger.logger.log(`network operation failed ${attempts} times, retrying in ${timeout}ms...`);
|
||||
await (0, _utils.sleep)(timeout);
|
||||
}
|
||||
return await callback();
|
||||
} catch (err) {
|
||||
if (err instanceof ConnectionError) {
|
||||
if (err instanceof _errors.ConnectionError) {
|
||||
attempts += 1;
|
||||
lastConnectionError = err;
|
||||
} else {
|
||||
@@ -132,39 +142,4 @@ export async function retryNetworkOperation(maxAttempts, callback) {
|
||||
}
|
||||
throw lastConnectionError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the backoff time for a request retry attempt.
|
||||
* This produces wait times of 2, 4, 8, and 16 seconds (30s total) after which we give up. If the
|
||||
* failure was due to a rate limited request, the time specified in the error is returned.
|
||||
*
|
||||
* Returns -1 if the error is not retryable, or if we reach the maximum number of attempts.
|
||||
*
|
||||
* @param err - The error thrown by the http call
|
||||
* @param attempts - The number of attempts made so far, including the one that just failed.
|
||||
* @param retryConnectionError - Whether to retry on {@link ConnectionError} (CORS, connection is down, etc.)
|
||||
*/
|
||||
export function calculateRetryBackoff(err, attempts, retryConnectionError) {
|
||||
if (attempts > 4) {
|
||||
return -1; // give up
|
||||
}
|
||||
if (err instanceof ConnectionError && !retryConnectionError) {
|
||||
return -1;
|
||||
}
|
||||
if (err.httpStatus && Math.floor(err.httpStatus / 100) === 4 && err.httpStatus !== 429) {
|
||||
// client error; no amount of retrying will save you now (except for rate limiting which is handled below)
|
||||
return -1;
|
||||
}
|
||||
if (err.name === "AbortError") {
|
||||
// this is a client timeout, that is already very high 60s/80s
|
||||
// we don't want to retry, as it could do it for very long
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If we are trying to send an event (or similar) that is too large in any way, then retrying won't help
|
||||
if (err.name === "M_TOO_LARGE") {
|
||||
return -1;
|
||||
}
|
||||
return safeGetRetryAfterMs(err, 1000 * Math.pow(2, attempts));
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
Reference in New Issue
Block a user