Harden Tahesab HTTP client against keep-alive hangs and retry health on alt ports.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import { randomBytes } from 'crypto';
|
||||
import type { TahesabHttpClient, TahesabCallOptions } from './tahesab-http.client';
|
||||
import {
|
||||
tahesabHealthBaseCandidates,
|
||||
type TahesabHttpClient,
|
||||
type TahesabCallOptions,
|
||||
} from './tahesab-http.client';
|
||||
|
||||
export type ConnCreds = {
|
||||
baseUrl: string;
|
||||
@@ -178,46 +182,67 @@ export class TahesabApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* تست سلامت مطابق Postman تهحساب:
|
||||
* ابتدا ریشهٔ baseUrl، بعد /CheckHealth، در نهایت مسیر SSL یا No-SSL بر اساس پروتکل.
|
||||
* تست سلامت مطابق Postman تهحساب (ریشه + CheckHealth).
|
||||
* روی تایماوت، پورت/پروتکل جایگزین (8081/9550) و در صورت نیاز TLS بدون verify را هم امتحان میکند.
|
||||
*/
|
||||
async checkHealth() {
|
||||
const isHttps = /^https:/i.test(this.creds.baseUrl.trim());
|
||||
const timeoutMs = 12_000;
|
||||
async checkHealth(): Promise<{
|
||||
Status?: string;
|
||||
Api_Status?: string;
|
||||
usedBaseUrl?: string;
|
||||
usedPath?: string;
|
||||
usedInsecureTls?: boolean;
|
||||
}> {
|
||||
const timeoutMs = 8_000;
|
||||
type Health = { Status?: string; Api_Status?: string };
|
||||
const attempts: Array<{
|
||||
path: string;
|
||||
bodyKey?: string;
|
||||
method: 'GET' | 'POST';
|
||||
}> = [
|
||||
{ path: '', method: 'GET' },
|
||||
{ path: '', bodyKey: 'CheckHealth', method: 'POST' },
|
||||
{ path: 'CheckHealth', method: 'GET' },
|
||||
{
|
||||
path: isHttps ? 'CheckHealth-SSL' : 'CheckHealth-No-SSL',
|
||||
method: 'GET',
|
||||
},
|
||||
];
|
||||
const bases = tahesabHealthBaseCandidates(this.creds.baseUrl);
|
||||
const insecureFlags = this.creds.allowInsecureTls
|
||||
? [true]
|
||||
: [false, true];
|
||||
|
||||
let lastErr: unknown;
|
||||
for (const attempt of attempts) {
|
||||
try {
|
||||
return await this.call<Health>(
|
||||
attempt.path,
|
||||
attempt.bodyKey,
|
||||
attempt.bodyKey ? [] : undefined,
|
||||
attempt.method,
|
||||
timeoutMs,
|
||||
);
|
||||
} catch (err) {
|
||||
lastErr = err;
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
// خطای گواهی با تلاشهای بعدی روی همان https حل نمیشود
|
||||
if (/certificate|UNABLE_TO_VERIFY|self-signed|CERT_/i.test(msg)) {
|
||||
throw err;
|
||||
for (const baseUrl of bases) {
|
||||
const isHttps = /^https:/i.test(baseUrl);
|
||||
const pathAttempts: Array<{
|
||||
path: string;
|
||||
bodyKey?: string;
|
||||
method: 'GET' | 'POST';
|
||||
}> = [
|
||||
{ path: '', method: 'GET' },
|
||||
{ path: '', bodyKey: 'CheckHealth', method: 'POST' },
|
||||
{ path: 'CheckHealth', method: 'GET' },
|
||||
{
|
||||
path: isHttps ? 'CheckHealth-SSL' : 'CheckHealth-No-SSL',
|
||||
method: 'GET',
|
||||
},
|
||||
];
|
||||
|
||||
for (const allowInsecureTls of insecureFlags) {
|
||||
if (!isHttps && allowInsecureTls) continue;
|
||||
for (const attempt of pathAttempts) {
|
||||
try {
|
||||
const health = await this.http.call<Health>({
|
||||
...this.creds,
|
||||
baseUrl,
|
||||
allowInsecureTls,
|
||||
path: attempt.path,
|
||||
bodyKey: attempt.bodyKey,
|
||||
args: attempt.bodyKey ? [] : undefined,
|
||||
method: attempt.method,
|
||||
timeoutMs,
|
||||
});
|
||||
return {
|
||||
...health,
|
||||
usedBaseUrl: baseUrl,
|
||||
usedPath: attempt.path || '(root)',
|
||||
usedInsecureTls: allowInsecureTls,
|
||||
};
|
||||
} catch (err) {
|
||||
lastErr = err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastErr instanceof Error
|
||||
? lastErr
|
||||
: new Error('تست اتصال تهحساب ناموفق بود.');
|
||||
|
||||
Reference in New Issue
Block a user