요청 관리 에러처리 수정
This commit is contained in:
@@ -842,19 +842,19 @@ a.btn.btn-primary {
|
||||
}
|
||||
|
||||
.drawflow .drawflow-node.current-execution {
|
||||
border: 2px solid blue;
|
||||
border: 4px solid lightskyblue;
|
||||
}
|
||||
|
||||
.drawflow .drawflow-node.result-success {
|
||||
border: 2px solid green;
|
||||
border: 4px solid forestgreen;
|
||||
}
|
||||
|
||||
.drawflow .drawflow-node.result-error {
|
||||
border: 2px solid red;
|
||||
border: 4px solid lightcoral;
|
||||
}
|
||||
|
||||
.drawflow .drawflow-node.result-abort {
|
||||
border: 2px solid grey;
|
||||
border: 4px solid lightslategrey;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
|
||||
@@ -14,17 +14,39 @@ class APIClient {
|
||||
this.abortController = null;
|
||||
}
|
||||
|
||||
async sendAPIRequest(model, callback) {
|
||||
try {
|
||||
async sendAPIRequest(model, preProcessCallback) {
|
||||
// try {
|
||||
const updatedModel = await this.executePreRequestScript(model);
|
||||
let processedRequest = this.replacePlaceholdersWithVariables(updatedModel);
|
||||
if (callback){
|
||||
callback(processedRequest);
|
||||
if (preProcessCallback) {
|
||||
preProcessCallback(processedRequest);
|
||||
}
|
||||
return this.makeAjaxRequest(processedRequest, model);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
return this.makeAjaxRequest(processedRequest, model)
|
||||
.then(async response => {
|
||||
const responseData = await response.json(); // Parse the JSON response
|
||||
if (!response.ok) {
|
||||
// If response is not OK, use the parsed error information
|
||||
const errorMessage = responseData.error || 'Unknown error';
|
||||
throw new Error(`API 호출 중 오류가 발생했습니다. 사유[${errorMessage}]`);
|
||||
}
|
||||
return responseData;
|
||||
})
|
||||
.then(data => {
|
||||
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 this.executePostRequestScript(model.postRequestScript, response)
|
||||
.catch(error => {
|
||||
$('.toast-body').text(error);
|
||||
$('.toast').toast('show');
|
||||
return response; // Return the original response even if there's an error
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
abort() {
|
||||
@@ -46,38 +68,7 @@ class APIClient {
|
||||
},
|
||||
body: JSON.stringify(processedRequest),
|
||||
signal: signal // pass the signal to the fetch
|
||||
})
|
||||
.then(async response => {
|
||||
const responseData = await response.json(); // Parse the JSON response
|
||||
if (!response.ok) {
|
||||
// If response is not OK, use the parsed error information
|
||||
const errorMessage = responseData.error || 'Unknown error';
|
||||
throw new Error(`API 호출 중 오류가 발생했습니다. 사유[${errorMessage}]`);
|
||||
}
|
||||
return responseData;
|
||||
})
|
||||
.then(data => {
|
||||
try {
|
||||
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 this.executePostRequestScript(model.postRequestScript, response);
|
||||
} catch (error) {
|
||||
console.log('error1')
|
||||
$('.toast-body').text(error);
|
||||
$('.toast').toast('show');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +126,7 @@ class APIClient {
|
||||
|
||||
window.preRequestComplete = (updatedModel, error) => {
|
||||
if (error) {
|
||||
reject('PreRequestScript error:', error);
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(updatedModel);
|
||||
}
|
||||
@@ -152,7 +143,7 @@ class APIClient {
|
||||
${script}
|
||||
window.parent.preRequestComplete(window.request, null);
|
||||
} catch (error) {
|
||||
window.parent.preRequestComplete(null, error.toString());
|
||||
window.parent.preRequestComplete(null, error);
|
||||
}
|
||||
</script>`;
|
||||
});
|
||||
@@ -163,11 +154,12 @@ class APIClient {
|
||||
let resultFrame = document.getElementById('postRequest');
|
||||
window.response = response;
|
||||
window.temp_variable = this.variables;
|
||||
window.postRequestComplete = (updatedModel, error) => {
|
||||
window.postRequestComplete = (response, error) => {
|
||||
console.log(response)
|
||||
if (error) {
|
||||
reject('PreRequestScript error:', error);
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(updatedModel);
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -179,7 +171,7 @@ class APIClient {
|
||||
${script}
|
||||
window.parent.postRequestComplete(window.response, null);
|
||||
} catch (error) {
|
||||
window.parent.postRequestComplete(null, error.toString());
|
||||
window.parent.postRequestComplete(window.response, error.toString());
|
||||
}
|
||||
</script>`;
|
||||
});
|
||||
|
||||
@@ -32,63 +32,6 @@ class APIScenarioExecutor {
|
||||
});
|
||||
}
|
||||
|
||||
// Method to execute the current node's API request if it's an 'api' node
|
||||
executeCurrentNode2() {
|
||||
console.log(this.currentNodeId)
|
||||
|
||||
let allNodes = document.querySelector('#drawflow').querySelectorAll('.drawflow-node');
|
||||
allNodes.forEach(node => {
|
||||
node.classList.remove('current-execution');
|
||||
});
|
||||
|
||||
if (!this.currentNodeId) {
|
||||
console.log('No current node to execute.');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentNode = this.graph[this.currentNodeId];
|
||||
|
||||
if (currentNode) {
|
||||
this.isRunning = true;
|
||||
|
||||
let nodeElement = document.querySelector('#drawflow').querySelector(`.drawflow-node[id="node-${this.currentNodeId}"]`);
|
||||
if (nodeElement) {
|
||||
nodeElement.classList.add('current-execution');
|
||||
} else {
|
||||
console.error('Node with ID ' + this.currentNodeId + ' not found');
|
||||
}
|
||||
|
||||
if (currentNode.class === 'api') {
|
||||
let model = JSON.parse(JSON.stringify(this.apiTester.getApiRequestModel(currentNode.data.id)));
|
||||
model.responseModel = {};
|
||||
this.apiClient.sendAPIRequest(model, this.logHttpRequest.bind(this))
|
||||
.then(response => {
|
||||
this.isRunning = false;
|
||||
this.logHttpResponse(response);
|
||||
if (response.status === 200 || response.status === 201) {
|
||||
nodeElement.classList.add('result-success');
|
||||
} else {
|
||||
nodeElement.classList.add('result-error');
|
||||
}
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
nodeElement.classList.add('result-abort');
|
||||
$('.toast-body').text(error.message);
|
||||
$('.toast').toast('show');
|
||||
this.appendLog(error.message);
|
||||
});
|
||||
console.log(`Executing API request for node: ${currentNode.id} - ${currentNode.name}`);
|
||||
} else if (currentNode.class === 'start') {
|
||||
this.appendLog('Starting API scenario execution...');
|
||||
nodeElement.classList.add('result-success');
|
||||
} else {
|
||||
console.log(`Executing script for node: ${currentNode.id} - ${currentNode.name}`);
|
||||
}
|
||||
this.visitedNodes.add(this.currentNodeId); // Mark this node as visited
|
||||
}
|
||||
}
|
||||
|
||||
executeCurrentNode() {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(this.currentNodeId)
|
||||
@@ -119,6 +62,7 @@ class APIScenarioExecutor {
|
||||
if (currentNode.class === 'api') {
|
||||
let model = JSON.parse(JSON.stringify(this.apiTester.getApiRequestModel(currentNode.data.id)));
|
||||
model.responseModel = {};
|
||||
this.appendLog(`Executing API [${model.name}]`);
|
||||
this.apiClient.sendAPIRequest(model, this.logHttpRequest.bind(this))
|
||||
.then(response => {
|
||||
this.isRunning = false;
|
||||
@@ -139,7 +83,7 @@ class APIScenarioExecutor {
|
||||
});
|
||||
console.log(`Executing API request for node: ${currentNode.id} - ${currentNode.name}`);
|
||||
} else if (currentNode.class === 'start') {
|
||||
this.appendLog('Starting API scenario execution...');
|
||||
this.appendLog('Starting API scenario\n');
|
||||
nodeElement.classList.add('result-success');
|
||||
resolve();
|
||||
} else {
|
||||
@@ -160,15 +104,28 @@ class APIScenarioExecutor {
|
||||
}
|
||||
|
||||
logHttpRequest(model) {
|
||||
let log = `${model.method} ${model.path} HTTP/1.1\n${model.requestBody}`;
|
||||
console.log(model);
|
||||
let log = `[API Request]\n${model.method} ${model.path} HTTP/1.1\n[Request Headers]\n${this.parseRequestHeaders(model.headers)}\n[Request Body]\n${model.requestBody}`;
|
||||
this.appendLog(log);
|
||||
}
|
||||
|
||||
logHttpResponse(response) {
|
||||
let log = `HTTP/1.1 ${response.status}\n${this.parseHeaders(response.headers)}\nBody: ${response.body}`;
|
||||
let log = `[Response]\nHTTP/1.1 ${response.status}\n[Response Headers]\n${this.parseHeaders(response.headers)}\n[Response Body]\n${response.body}`;
|
||||
this.appendLog(log);
|
||||
}
|
||||
|
||||
parseRequestHeaders(headers) {
|
||||
let parsedHeaders = '';
|
||||
headers.forEach(header => {
|
||||
if (header.enabled){
|
||||
parsedHeaders += `${header.key}: ${header.value}\n`;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return parsedHeaders;
|
||||
}
|
||||
|
||||
parseHeaders(headers) {
|
||||
//convert object to string with \n separation
|
||||
//sort header by key
|
||||
@@ -203,15 +160,6 @@ class APIScenarioExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// Method to execute the entire scenario from start to end
|
||||
// async executeAll() {
|
||||
// while (this.currentNodeId) {
|
||||
// console.log(this.currentNodeId)
|
||||
// this.executeCurrentNode(); //TODO: how can I make sure this call wait until response is received
|
||||
// await this.moveToNextNodeWithDelay(250);
|
||||
// }
|
||||
// console.log('Completed execution of all API nodes.');
|
||||
// }
|
||||
async executeAll() {
|
||||
while (this.currentNodeId) {
|
||||
console.log(this.currentNodeId);
|
||||
|
||||
@@ -928,14 +928,11 @@ class APITester {
|
||||
this.hideLoadingOverlay();
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error.name)
|
||||
if (error.name === 'AbortError') {
|
||||
console.log('Fetch aborted');
|
||||
} else {
|
||||
console.log('error3')
|
||||
// if (error.name === 'AbortError') {
|
||||
// console.log('Fetch aborted');
|
||||
// }
|
||||
$('.toast-body').text(error);
|
||||
$('.toast').toast('show');
|
||||
}
|
||||
this.hideLoadingOverlay();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<!-- csrf -->
|
||||
<input id="csrf" type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; right: 0;">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; left: 0;">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto">알림</strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</div>
|
||||
<button class="w-100 btn btn-lg btn-primary" type="button" id="actionLogin" th:text="#{loginForm.login}">Sign in</button>
|
||||
</form>
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; right: 0;">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; left: 0;">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto">알림</strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
require.config({paths: {'vs': '/plugins/vs'}});
|
||||
</script>
|
||||
<div class="container-fluid mt-2">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; right: 0;">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; left: 0;">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto">알림</strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; right: 0;">
|
||||
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" style="position: absolute; top: 0; left: 0;">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto">알림</strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
|
||||
Reference in New Issue
Block a user