/** * 처리 순서 * 1. preRequestScript 실행 -> executePreRequestScript * 2. 변수 치환 -> replacePlaceholdersWithVariables * 3. API 호출 -> sendAPIRequest * 4. postRequestScript 실행 -> executePostRequestScript */ class APIClient { CLIENT_URL = 'mgmt/api/test.do'; constructor() { window.globals = {}; this.abortController = null; this.contextPath = document.querySelector('meta[name="context-path"]').getAttribute('content'); if (!this.contextPath) { this.contextPath = '/'; } if (!this.contextPath.endsWith('/')) { this.contextPath += '/'; } } getClientUrl() { return this.contextPath + this.CLIENT_URL; } formatResponse(data) { // Format response as needed before post-request script let response = {}; response.body = data.body; response.status = data.status; response.headers = {}; response.size = data.size; _.forEach(data.headers, (header) => { response.headers[header.key] = header.value; }); return response; } abort() { if (this.abortController) { this.abortController.abort(); // abort the fetch this.abortController = null; // reset the controller } } makeAjaxRequest(processedRequest, model) { this.abortController = new AbortController(); const {signal} = this.abortController; try { return fetch(this.getClientUrl(), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-XSRF-TOKEN': $('meta[name="_csrf"]').attr('content') }, body: JSON.stringify(processedRequest), signal: signal // pass the signal to the fetch }); } catch (error) { if (error.name !== 'AbortError') { console.error('Network request failed:', error); } throw error; } } async processPreScriptAndVariables(model, value, consoleOutput){ let variables = {}; const updatedModel = await this.executePreRequestScript(model, variables, consoleOutput); return this.replacePlaceholderValueWithVariables(updatedModel, value, variables); } replacePlaceholderValueWithVariables(model, originalValue, variables) { let mergedVariables = {}; _.forEach(window.globals, (value, key) => { mergedVariables[key] = value; }); if (variables) { _.forEach(variables, (value, key) => { mergedVariables[key] = value; }); } _.forEach(mergedVariables, (value, key) => { const placeholder = `{{${key}}}`; // Replace in path originalValue = originalValue.replace(new RegExp(placeholder, 'g'), value); }); return originalValue; } async sendAPIRequest(model, preProcessCallback, consoleOutput) { try { let variables = {}; const updatedModel = await this.executePreRequestScript(model, variables, consoleOutput); let processedRequest = this.replacePlaceholdersWithVariables(updatedModel, variables); if (preProcessCallback) { preProcessCallback(processedRequest); } const response = await this.makeAjaxRequest(processedRequest, model, consoleOutput); const responseData = await response.json(); // Parse the JSON response if (!response.ok) { const errorMessage = responseData.error || 'Unknown error'; throw new Error(`API 호출 중 오류가 발생했습니다. 사유[${errorMessage}]`); } const finalResponse = this.formatResponse(responseData); return this.executePostRequestScript(model.postRequestScript, variables, processedRequest, finalResponse, consoleOutput).catch(error => { $('.toast-body').text(error); $('.toast').toast('show'); return finalResponse; // Return the original response even if there's an error in the post-request script }); } catch (error) { throw error; } } replacePlaceholdersWithVariables(original, variables) { let request = JSON.parse(JSON.stringify(original)); let mergedVariables = {}; _.forEach(window.globals, (value, key) => { mergedVariables[key] = value; }); if (variables) { _.forEach(variables, (value, key) => { mergedVariables[key] = value; }); } _.forEach(mergedVariables, (value, key) => { const placeholder = `{{${key}}}`; // Replace in path request.path = request.path.replace(new RegExp(placeholder, 'g'), value); // Replace in requestBody if (request.requestBody) { request.requestBody = request.requestBody.replace(new RegExp(placeholder, 'g'), value); } // Replace in headers if (request.headers) { let replaced = JSON.stringify(request.headers).replace(new RegExp(placeholder, 'g'), value); request.headers = JSON.parse(replaced); } // Replace in queryParams if (request.queryParams) { let replaced = JSON.stringify(request.queryParams).replace(new RegExp(placeholder, 'g'), value); request.queryParams = JSON.parse(replaced); } }); return request; } executePreRequestScript(model, variables, consoleOutput) { return new Promise((resolve, reject) => { let script = model.preRequestScript; let resultFrame = document.getElementById('preRequest'); window.preRequestComplete = (updatedModel, error) => { if (error) { reject(error); } else { resolve(updatedModel); } }; window.temp_variable = variables; window.currentRequest = model; window.consoleOutput = consoleOutput; resultFrame.srcdoc = ``; }); } executePostRequestScript(script, variables, request, response, consoleOutput) { return new Promise((resolve, reject) => { let resultFrame = document.getElementById('postRequest'); window.request = request; window.response = response; window.temp_variable = variables; window.postRequestComplete = (response, error) => { if (error) { reject(error); } else { resolve(response); } }; window.consoleOutput = consoleOutput; resultFrame.srcdoc = ``; }); } } export default APIClient;