mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-16 08:10:58 +00:00
fix(frontend): preserve cancellation and reject invalid query data (#6143)
* fix(frontend): preserve request cancellation and schema failures * fix(frontend): limit schema failures to query boundaries * fix(frontend): keep invalid settings recoverable Keep settings payload validation tolerant so values accepted by the backend remain editable, while paged clients still fail closed. Add an AbortSignal.any fallback and make timeout tests event-driven. --------- Co-authored-by: PathGao <gaoyanbo@gaoyanbodeMacBook-Air.local>
This commit is contained in:
@@ -88,6 +88,28 @@ function encodeForm(data: unknown): string {
|
||||
return parts.join('&');
|
||||
}
|
||||
|
||||
function appendQuery(url: string, query: string): string {
|
||||
if (query === '') return url;
|
||||
const hashIndex = url.indexOf('#');
|
||||
const path = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
||||
const hash = hashIndex === -1 ? '' : url.slice(hashIndex);
|
||||
const hasQuery = path.includes('?');
|
||||
const separator = !hasQuery ? '?' : path.endsWith('?') || path.endsWith('&') ? '' : '&';
|
||||
return `${path}${separator}${query}${hash}`;
|
||||
}
|
||||
|
||||
function requestSignal(options: HttpRequestOptions): AbortSignal | undefined {
|
||||
if (!options.timeout) return options.signal;
|
||||
const timeout = AbortSignal.timeout(options.timeout);
|
||||
if (!options.signal) return timeout;
|
||||
if (typeof AbortSignal.any === 'function') return AbortSignal.any([options.signal, timeout]);
|
||||
const controller = new AbortController();
|
||||
const abort = () => controller.abort();
|
||||
options.signal.addEventListener('abort', abort, { once: true });
|
||||
timeout.addEventListener('abort', abort, { once: true });
|
||||
return controller.signal;
|
||||
}
|
||||
|
||||
async function performFetch(
|
||||
method: string,
|
||||
url: string,
|
||||
@@ -121,8 +143,8 @@ async function performFetch(
|
||||
}
|
||||
|
||||
const query = encodeForm(options.params);
|
||||
const fullUrl = basePathPrefix + url + (query ? `?${query}` : '');
|
||||
const signal = options.timeout ? AbortSignal.timeout(options.timeout) : options.signal;
|
||||
const fullUrl = basePathPrefix + appendQuery(url, query);
|
||||
const signal = requestSignal(options);
|
||||
|
||||
return fetch(fullUrl, { method: upper, headers, body, credentials: 'same-origin', signal });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user