restapi 여러개 띄우는거 작업 가능하게 하는거 진행중
This commit is contained in:
@@ -606,16 +606,32 @@ export class DashboardController {
|
||||
}
|
||||
});
|
||||
|
||||
// 외부 API 호출
|
||||
// 외부 API 호출 (타임아웃 30초)
|
||||
// @ts-ignore - node-fetch dynamic import
|
||||
const fetch = (await import("node-fetch")).default;
|
||||
const response = await fetch(urlObj.toString(), {
|
||||
method: method.toUpperCase(),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...headers,
|
||||
},
|
||||
});
|
||||
|
||||
// 타임아웃 설정 (Node.js 글로벌 AbortController 사용)
|
||||
const controller = new (global as any).AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 60000); // 60초 (기상청 API는 느림)
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(urlObj.toString(), {
|
||||
method: method.toUpperCase(),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...headers,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(timeoutId);
|
||||
} catch (err: any) {
|
||||
clearTimeout(timeoutId);
|
||||
if (err.name === 'AbortError') {
|
||||
throw new Error('외부 API 요청 타임아웃 (30초 초과)');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
@@ -623,7 +639,40 @@ export class DashboardController {
|
||||
);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
// Content-Type에 따라 응답 파싱
|
||||
const contentType = response.headers.get("content-type");
|
||||
let data: any;
|
||||
|
||||
// 한글 인코딩 처리 (EUC-KR → UTF-8)
|
||||
const isKoreanApi = urlObj.hostname.includes('kma.go.kr') ||
|
||||
urlObj.hostname.includes('data.go.kr');
|
||||
|
||||
if (isKoreanApi) {
|
||||
// 한국 정부 API는 EUC-KR 인코딩 사용
|
||||
const buffer = await response.arrayBuffer();
|
||||
const decoder = new TextDecoder('euc-kr');
|
||||
const text = decoder.decode(buffer);
|
||||
|
||||
try {
|
||||
data = JSON.parse(text);
|
||||
} catch {
|
||||
data = { text, contentType };
|
||||
}
|
||||
} else if (contentType && contentType.includes("application/json")) {
|
||||
data = await response.json();
|
||||
} else if (contentType && contentType.includes("text/")) {
|
||||
// 텍스트 응답 (CSV, 일반 텍스트 등)
|
||||
const text = await response.text();
|
||||
data = { text, contentType };
|
||||
} else {
|
||||
// 기타 응답 (JSON으로 시도)
|
||||
try {
|
||||
data = await response.json();
|
||||
} catch {
|
||||
const text = await response.text();
|
||||
data = { text, contentType };
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
|
||||
@@ -28,7 +28,7 @@ export class ExternalRestApiConnectionService {
|
||||
try {
|
||||
let query = `
|
||||
SELECT
|
||||
id, connection_name, description, base_url, default_headers,
|
||||
id, connection_name, description, base_url, endpoint_path, default_headers,
|
||||
auth_type, auth_config, timeout, retry_count, retry_delay,
|
||||
company_code, is_active, created_date, created_by,
|
||||
updated_date, updated_by, last_test_date, last_test_result, last_test_message
|
||||
@@ -110,7 +110,7 @@ export class ExternalRestApiConnectionService {
|
||||
try {
|
||||
const query = `
|
||||
SELECT
|
||||
id, connection_name, description, base_url, default_headers,
|
||||
id, connection_name, description, base_url, endpoint_path, default_headers,
|
||||
auth_type, auth_config, timeout, retry_count, retry_delay,
|
||||
company_code, is_active, created_date, created_by,
|
||||
updated_date, updated_by, last_test_date, last_test_result, last_test_message
|
||||
@@ -167,10 +167,10 @@ export class ExternalRestApiConnectionService {
|
||||
|
||||
const query = `
|
||||
INSERT INTO external_rest_api_connections (
|
||||
connection_name, description, base_url, default_headers,
|
||||
connection_name, description, base_url, endpoint_path, default_headers,
|
||||
auth_type, auth_config, timeout, retry_count, retry_delay,
|
||||
company_code, is_active, created_by
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
@@ -178,6 +178,7 @@ export class ExternalRestApiConnectionService {
|
||||
data.connection_name,
|
||||
data.description || null,
|
||||
data.base_url,
|
||||
data.endpoint_path || null,
|
||||
JSON.stringify(data.default_headers || {}),
|
||||
data.auth_type,
|
||||
encryptedAuthConfig ? JSON.stringify(encryptedAuthConfig) : null,
|
||||
@@ -261,6 +262,12 @@ export class ExternalRestApiConnectionService {
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (data.endpoint_path !== undefined) {
|
||||
updateFields.push(`endpoint_path = $${paramIndex}`);
|
||||
params.push(data.endpoint_path);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (data.default_headers !== undefined) {
|
||||
updateFields.push(`default_headers = $${paramIndex}`);
|
||||
params.push(JSON.stringify(data.default_headers));
|
||||
|
||||
@@ -41,7 +41,7 @@ export class RiskAlertService {
|
||||
disp: 0,
|
||||
authKey: apiKey,
|
||||
},
|
||||
timeout: 10000,
|
||||
timeout: 30000, // 30초로 증가
|
||||
responseType: 'arraybuffer', // 인코딩 문제 해결
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface ExternalRestApiConnection {
|
||||
connection_name: string;
|
||||
description?: string;
|
||||
base_url: string;
|
||||
endpoint_path?: string;
|
||||
default_headers: Record<string, string>;
|
||||
auth_type: AuthType;
|
||||
auth_config?: {
|
||||
|
||||
Reference in New Issue
Block a user