diff options
Diffstat (limited to 'lib/soap/sender.ts')
| -rw-r--r-- | lib/soap/sender.ts | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/lib/soap/sender.ts b/lib/soap/sender.ts index 3728429b..1dfc8730 100644 --- a/lib/soap/sender.ts +++ b/lib/soap/sender.ts @@ -35,6 +35,9 @@ export interface SoapSendResult { responseText?: string; statusCode?: number; headers?: Record<string, string>; + endpoint?: string; + requestXml?: string; + requestHeaders?: Record<string, string>; } // 기본 환경변수에서 인증 정보 가져오기 @@ -111,34 +114,46 @@ export async function sendSoapXml( console.log('📤 SOAP XML 전송 시작'); console.log('🔍 전송 XML (첫 500자):', xmlData.substring(0, 500)); + // 요청 헤더 및 fetch 옵션을 사전에 구성 + const requestHeaders: Record<string, string> = { + 'Content-Type': 'text/xml; charset=utf-8', + 'SOAPAction': config.soapAction || 'http://sap.com/xi/WebService/soap1.1', + }; + + // Basic Authentication 헤더 추가 + if (authConfig.username && authConfig.password) { + const credentials = Buffer.from(`${authConfig.username}:${authConfig.password}`).toString('base64'); + requestHeaders['Authorization'] = `Basic ${credentials}`; + console.log('🔐 Basic Authentication 헤더 추가 완료'); + } else { + console.warn('⚠️ SOAP 인증 정보가 설정되지 않았습니다.'); + } + + const fetchOptions: RequestInit = { + method: 'POST', + headers: requestHeaders, + body: xmlData, + }; + + // Body 루트 요소(p1:MT_...)에 기본 네임스페이스를 부여하여 하위 무접두사 요소들도 동일 네임스페이스로 인식되도록 처리 + const envelopeObj = soapEnvelope as Record<string, any>; + const bodyObj = envelopeObj['soap:Envelope']?.['soap:Body'] as Record<string, any> | undefined; + if (bodyObj && typeof bodyObj === 'object') { + const rootKeys = Object.keys(bodyObj); + if (rootKeys.length > 0) { + const rootKey = rootKeys[0]; + if (bodyObj[rootKey] && typeof bodyObj[rootKey] === 'object') { + bodyObj[rootKey]['@_xmlns'] = namespace; + } + } + } + const result = await withSoapLogging( logInfo.direction, logInfo.system, logInfo.interface, xmlData, async () => { - // 헤더 설정 - const headers: Record<string, string> = { - 'Content-Type': 'text/xml; charset=utf-8', - 'SOAPAction': config.soapAction || 'http://sap.com/xi/WebService/soap1.1', - }; - - // Basic Authentication 헤더 추가 - if (authConfig.username && authConfig.password) { - const credentials = Buffer.from(`${authConfig.username}:${authConfig.password}`).toString('base64'); - headers['Authorization'] = `Basic ${credentials}`; - console.log('🔐 Basic Authentication 헤더 추가 완료'); - } else { - console.warn('⚠️ SOAP 인증 정보가 설정되지 않았습니다.'); - } - - // fetch 옵션 설정 - const fetchOptions: RequestInit = { - method: 'POST', - headers, - body: xmlData, - }; - // 타임아웃 설정 if (config.timeout) { const controller = new AbortController(); @@ -171,14 +186,22 @@ export async function sendSoapXml( console.log('📥 SOAP 응답 수신:', response.status, response.statusText); console.log('🔍 응답 XML (첫 500자):', responseText.substring(0, 500)); - // HTTP 상태 코드 확인 - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - // SOAP Fault 검사 - if (responseText.includes('soap:Fault') || responseText.includes('SOAP:Fault')) { - throw new Error(`SOAP Fault: ${responseText}`); + // HTTP 상태 코드가 비정상이거나 SOAP Fault 포함 시 실패로 처리하되 본문을 그대로 반환 + if (!response.ok || responseText.includes('soap:Fault') || responseText.includes('SOAP:Fault')) { + const responseHeaders: Record<string, string> = {}; + response.headers.forEach((value, key) => { + responseHeaders[key] = value; + }); + return { + success: false, + message: !response.ok ? `HTTP ${response.status}: ${response.statusText}` : 'SOAP Fault', + responseText, + statusCode: response.status, + headers: responseHeaders, + endpoint: config.endpoint, + requestXml: xmlData, + requestHeaders + }; } // 응답 헤더 수집 @@ -192,7 +215,10 @@ export async function sendSoapXml( message: '전송 성공', responseText, statusCode: response.status, - headers: responseHeaders + headers: responseHeaders, + endpoint: config.endpoint, + requestXml: xmlData, + requestHeaders }; } catch (error) { |
