스크립트 추가
This commit is contained in:
@@ -22,6 +22,10 @@ public class ApiRequestDTO {
|
||||
|
||||
private String requestBody;
|
||||
|
||||
private String preRequestScript;
|
||||
|
||||
private String postRequestScript;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -93,4 +97,20 @@ public class ApiRequestDTO {
|
||||
public void setRequestBody(String requestBody) {
|
||||
this.requestBody = requestBody;
|
||||
}
|
||||
|
||||
public String getPreRequestScript() {
|
||||
return preRequestScript;
|
||||
}
|
||||
|
||||
public void setPreRequestScript(String preRequestScript) {
|
||||
this.preRequestScript = preRequestScript;
|
||||
}
|
||||
|
||||
public String getPostRequestScript() {
|
||||
return postRequestScript;
|
||||
}
|
||||
|
||||
public void setPostRequestScript(String postRequestScript) {
|
||||
this.postRequestScript = postRequestScript;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,13 @@ public class ApiRequestInfo {
|
||||
@Lob
|
||||
private String requestBody;
|
||||
|
||||
@Lob
|
||||
private String preRequestScript;
|
||||
|
||||
@Lob
|
||||
private String postRequestScript;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -120,6 +127,22 @@ public class ApiRequestInfo {
|
||||
this.requestBody = requestBody;
|
||||
}
|
||||
|
||||
public String getPreRequestScript() {
|
||||
return preRequestScript;
|
||||
}
|
||||
|
||||
public void setPreRequestScript(String preRequestScript) {
|
||||
this.preRequestScript = preRequestScript;
|
||||
}
|
||||
|
||||
public String getPostRequestScript() {
|
||||
return postRequestScript;
|
||||
}
|
||||
|
||||
public void setPostRequestScript(String postRequestScript) {
|
||||
this.postRequestScript = postRequestScript;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -130,7 +153,7 @@ public class ApiRequestInfo {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, server, owner, method, path, headers, queryParams, requestBody);
|
||||
return Objects.hash(id, server, owner, method, path, headers, queryParams, requestBody, preRequestScript, postRequestScript);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,6 +70,9 @@ public class ApiRequestMgmtService {
|
||||
existing.setVariables(api.getVariables());
|
||||
existing.setServer(api.getServer());
|
||||
existing.setRequestBody(api.getRequestBody());
|
||||
existing.setPreRequestScript(api.getPreRequestScript());
|
||||
existing.setPostRequestScript(api.getPostRequestScript());
|
||||
|
||||
apiRequestRepository.save(existing);
|
||||
api = existing;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class NettyApiClient {
|
||||
ServerRepository serverRepository;
|
||||
|
||||
public CompletableFuture<ApiResponse> handleRequest(ApiRequestDTO originalRequest) throws InterruptedException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
|
||||
ApiRequestDTO apiRequest = replacePlaceholdersWithVariables(originalRequest);
|
||||
ApiRequestDTO apiRequest = originalRequest;
|
||||
Server server = serverRepository.findById(apiRequest.getServer()).orElseThrow(() -> new ServerNotFoundException("Server not found"));
|
||||
String host = server.getHostname();
|
||||
int port = server.getPort();
|
||||
@@ -108,37 +108,4 @@ public class NettyApiClient {
|
||||
return responseFuture;
|
||||
}
|
||||
|
||||
private ApiRequestDTO replacePlaceholdersWithVariables(ApiRequestDTO original) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
|
||||
ApiRequestDTO request = (ApiRequestDTO) BeanUtils.cloneBean(original);
|
||||
if (request.getVariables() != null) {
|
||||
for (ApiRequestKeyValueDTO variable : request.getVariables()) {
|
||||
if (variable.isEnabled()) {
|
||||
String placeholder = "{{" + variable.getKey() + "}}";
|
||||
// Replace in path
|
||||
request.setPath(request.getPath().replace(placeholder, variable.getValue()));
|
||||
// Replace in requestBody
|
||||
if (request.getRequestBody() != null) {
|
||||
request.setRequestBody(request.getRequestBody().replace(placeholder, variable.getValue()));
|
||||
}
|
||||
|
||||
// Replace in headers
|
||||
if (request.getHeaders() != null) {
|
||||
for (ApiRequestKeyValueDTO header : request.getHeaders()) {
|
||||
header.setKey(header.getKey().replace(placeholder, variable.getValue()));
|
||||
header.setValue(header.getValue().replace(placeholder, variable.getValue()));
|
||||
}
|
||||
}
|
||||
// Replace in queryParams
|
||||
if (request.getQueryParams() != null) {
|
||||
for (ApiRequestKeyValueDTO queryParam : request.getQueryParams()) {
|
||||
queryParam.setKey(queryParam.getKey().replace(placeholder, variable.getValue()));
|
||||
queryParam.setValue(queryParam.getValue().replace(placeholder, variable.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,11 @@ class APITester {
|
||||
this.collections = []; //API 컬렉션
|
||||
this.requestEditors = []; //API request body editor
|
||||
this.responseEditors = []; //API response body editor
|
||||
|
||||
this.preRequestEditors = [];
|
||||
this.postRequestEditors = [];
|
||||
window.globals = {};
|
||||
this.globalVariables = window.globals;
|
||||
this.variables = {};
|
||||
}
|
||||
|
||||
renderServers(selectedServer) {
|
||||
@@ -36,7 +40,7 @@ class APITester {
|
||||
|
||||
apiRequestTemplate(apiRequest, index) {
|
||||
return `
|
||||
<div class="tab-pane fade mt-1 api_request" id="api_request_${apiRequest.id}" data-index="${index}">
|
||||
<div class="tab-pane fade mt-1 api_request" id="api_request_${apiRequest.id}">
|
||||
<div><span class="collection_name">${apiRequest.collectionName}</span> > <span class="api_name">${apiRequest.name}</span></div>
|
||||
<div class="d-flex align-items-center api_request_info">
|
||||
<div class="form-floating col-md-1 me-1">
|
||||
@@ -60,13 +64,12 @@ class APITester {
|
||||
<div class="form-floating col-md-2 me-1">
|
||||
<div class="form-floating col-md">
|
||||
<input type="text" name="basePath" class="form-control" value="${this.basePath(apiRequest.server)}" readonly>
|
||||
<label class="must">base path</label>
|
||||
<label class="must">기본 경로</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group col-md me-1">
|
||||
<div class="form-floating col-md">
|
||||
<input type="text" name="path" class="form-control path" value="${apiRequest.path}" placeholder="호출할 경로 (/부터 입력)"
|
||||
required>
|
||||
<input type="text" name="path" class="form-control path" value="${apiRequest.path}" placeholder="호출할 경로 (/부터 입력)">
|
||||
<label class="must">Path</label>
|
||||
</div>
|
||||
<button class="btn btn-primary send">Send</button>
|
||||
@@ -98,6 +101,19 @@ class APITester {
|
||||
aria-selected="false">Variables
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link btn_prerequest_tab" data-bs-toggle="tab"
|
||||
type="button" role="tab" aria-controls="preScrit" data-bs-target="#preRequestTab_${apiRequest.id}"
|
||||
aria-selected="false">Pre-Request
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link btn_postrequest_tab" data-bs-toggle="tab"
|
||||
type="button" role="tab" aria-controls="postScript" data-bs-target="#postRequestTab_${apiRequest.id}"
|
||||
aria-selected="false">Post-Request
|
||||
</button>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="tab-content border-bottom" style="min-height: 300px;">
|
||||
<div class="tab-pane fade show request_param_tab" role="tabpanel" id="requestParamTab_${apiRequest.id}"
|
||||
@@ -164,6 +180,14 @@ class APITester {
|
||||
</select>
|
||||
<div class="request_body mt-1" style="width:100%;height:250px;border:1px solid grey;"></div>
|
||||
</div>
|
||||
<div class="tab-pane fade pre_script_tab" role="tabpanel" id="preRequestTab_${apiRequest.id}"
|
||||
aria-labelledby="preScrit-tab">
|
||||
<div class="pre-request mt-1" style="width:100%;height:250px;border:1px solid grey;"></div>
|
||||
</div>
|
||||
<div class="tab-pane fade post_script_tab" role="tabpanel" id="postRequestTab_${apiRequest.id}"
|
||||
aria-labelledby="postScrit-tab">
|
||||
<div class="post-request mt-1" style="width:100%;height:250px;border:1px solid grey;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<span>Response</span>
|
||||
@@ -467,8 +491,7 @@ class APITester {
|
||||
//console.log(fieldName);
|
||||
const newValue = this.getFieldValue(element);
|
||||
//console.log(newValue);
|
||||
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
|
||||
if (fieldName !== '') {
|
||||
@@ -479,7 +502,7 @@ class APITester {
|
||||
}
|
||||
|
||||
handleUpdateServer(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
let target = $('#api_request_' + model.id);
|
||||
//console.log('model.server: ' + model.server);
|
||||
@@ -505,7 +528,7 @@ class APITester {
|
||||
|
||||
for (let idx = 0; idx < this.apiRequests.length; idx++) {
|
||||
let li = `<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="api_request_tab_${this.apiRequests[idx].id}" data-index="${idx}" data-bs-toggle="tab" type="button" role="tab" aria-controls="api_request_${this.apiRequests[idx].id}" data-bs-target="#api_request_${this.apiRequests[idx].id}" aria-selected="false">${this.apiRequests[idx].name}
|
||||
<button class="nav-link" id="api_request_tab_${this.apiRequests[idx].id}" data-bs-toggle="tab" type="button" role="tab" aria-controls="api_request_${this.apiRequests[idx].id}" data-bs-target="#api_request_${this.apiRequests[idx].id}" aria-selected="false">${this.apiRequests[idx].name}
|
||||
<span class="close_tab"><i class="fa fa-light fa-close"></i></span>
|
||||
</button>
|
||||
</li>`;
|
||||
@@ -524,7 +547,7 @@ class APITester {
|
||||
this.openTab(model.id);
|
||||
let target = $('#api_request_' + model.id);
|
||||
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
require(['vs/editor/editor.main'], () => {
|
||||
let requestBodyEditor = monaco.editor.create(target.find(".request_body")[0], {
|
||||
value: model.requestBody,
|
||||
language: 'json',
|
||||
@@ -532,15 +555,15 @@ class APITester {
|
||||
automaticLayout: true
|
||||
});
|
||||
me.requestEditors.push(requestBodyEditor);
|
||||
target.find(".request_body")[0].addEventListener('shown.bs.tab', function () {
|
||||
target.find(".request_body")[0].addEventListener('shown.bs.tab', () => {
|
||||
me.requestEditors[index].layout();
|
||||
});
|
||||
|
||||
me.requestEditors[index].onDidChangeModelContent(function (e) {
|
||||
me.requestEditors[index].onDidChangeModelContent( (e) => {
|
||||
model.requestBody = requestBodyEditor.getValue();
|
||||
});
|
||||
|
||||
target.find('.request_body_type').on('change', function () {
|
||||
target.find('.request_body_type').on('change', () => {
|
||||
let model = requestBodyEditor.getModel();
|
||||
monaco.editor.setModelLanguage(model, $(this).val());
|
||||
});
|
||||
@@ -552,6 +575,40 @@ class APITester {
|
||||
automaticLayout: true
|
||||
});
|
||||
me.responseEditors.push(responseBodyEditor);
|
||||
|
||||
let preRequestEditor = monaco.editor.create(target.find(".pre-request")[0], {
|
||||
value: model.preRequestScript,
|
||||
language: 'javascript',
|
||||
theme: 'vs-light',
|
||||
automaticLayout: true
|
||||
});
|
||||
me.preRequestEditors.push(preRequestEditor);
|
||||
target.find(".pre-request")[0].addEventListener('shown.bs.tab', () => {
|
||||
me.preRequestEditors[index].layout();
|
||||
});
|
||||
|
||||
me.preRequestEditors[index].onDidChangeModelContent( (e) => {
|
||||
model.preRequestScript = preRequestEditor.getValue();
|
||||
});
|
||||
|
||||
let postRequestEditor = monaco.editor.create(target.find(".post-request")[0], {
|
||||
value: model.postRequestScript,
|
||||
language: 'javascript',
|
||||
theme: 'vs-light',
|
||||
automaticLayout: true
|
||||
});
|
||||
me.postRequestEditors.push(postRequestEditor);
|
||||
target.find(".post-request")[0].addEventListener('shown.bs.tab', () => {
|
||||
me.postRequestEditors[index].layout();
|
||||
});
|
||||
|
||||
me.postRequestEditors[index].onDidChangeModelContent( (e) => {
|
||||
model.postRequestScript = postRequestEditor.getValue();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -621,7 +678,7 @@ class APITester {
|
||||
}
|
||||
|
||||
addHeader(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.headers.push({
|
||||
enabled: true,
|
||||
@@ -632,7 +689,7 @@ class APITester {
|
||||
}
|
||||
|
||||
removeHeader(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
const index = $(event.currentTarget).closest('tr').data('index');
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.headers.splice(index, 1);
|
||||
@@ -649,7 +706,7 @@ class APITester {
|
||||
|
||||
|
||||
addQueryParam(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
//console.log('addQueryParam');
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.queryParams.push({
|
||||
@@ -663,7 +720,7 @@ class APITester {
|
||||
|
||||
removeQueryParam(event) {
|
||||
//console.log('removeQueryParam');
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
const index = $(event.currentTarget).closest('tr').data('index');
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.queryParams.splice(index, 1);
|
||||
@@ -680,7 +737,7 @@ class APITester {
|
||||
|
||||
addVariable(event) {
|
||||
//console.log('addVariable');
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.variables.push({
|
||||
enabled: true,
|
||||
@@ -692,7 +749,7 @@ class APITester {
|
||||
|
||||
removeVariable(event) {
|
||||
//console.log('removeVariable');
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
const index = $(event.currentTarget).closest('tr').data('index');
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.variables.splice(index, 1);
|
||||
@@ -707,7 +764,7 @@ class APITester {
|
||||
target.find('.variables').append(this.renderVariables(model.variables));
|
||||
}
|
||||
parseParam(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
model.path = $(event.currentTarget).val();
|
||||
//console.log(model.path);
|
||||
@@ -729,7 +786,7 @@ class APITester {
|
||||
}
|
||||
}
|
||||
buildPath(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[tabIndex];
|
||||
let queryString = model.path.split('?')[0];
|
||||
if (model.queryParams.length > 0) {
|
||||
@@ -757,41 +814,65 @@ class APITester {
|
||||
}
|
||||
|
||||
sendApiRequest(event) {
|
||||
const tabIndex = $(event.currentTarget).closest('.api_request').data('index');
|
||||
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
console.log(tabIndex);
|
||||
const me = this;
|
||||
|
||||
let model = this.apiRequests[tabIndex];
|
||||
|
||||
if (!model.server){
|
||||
$('.toast-body').text('서버를 등록해주세요.');
|
||||
$('.toast').toast('show');
|
||||
return;
|
||||
}
|
||||
|
||||
let target = $('#api_request_' + model.id);
|
||||
target.find('.response_headers').empty();
|
||||
this.responseEditors[tabIndex].setValue('');
|
||||
let startTime = new Date().getTime();
|
||||
|
||||
if (model.path !== '') {
|
||||
this.showLoadingOverlay();
|
||||
model.responseModel = {};
|
||||
|
||||
let processedRequest = this.executePreRequestScript(model, tabIndex,() => {
|
||||
processedRequest = this.replacePlaceholdersWithVariables(processedRequest, tabIndex);
|
||||
this.currentAjaxRequest = $.ajax({
|
||||
url: '/mgmt/api/test.do',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(model),
|
||||
success: function (data) {
|
||||
data: JSON.stringify(processedRequest),
|
||||
success: (data) => {
|
||||
model.responseModel.status = data.status;
|
||||
model.responseModel.body = data.body;
|
||||
model.responseModel.headers = data.headers;
|
||||
model.responseModel.size = data.size;
|
||||
},
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
me.hideLoadingOverlay();
|
||||
$('.toast-body').text(response.responseJSON.error);
|
||||
$('.toast').toast('show');
|
||||
},
|
||||
complete: function () {
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
this.executePostRequestScript(model.postRequestScript, tabIndex, response, ()=> {
|
||||
let endTime = new Date().getTime();
|
||||
model.responseModel.time = endTime - startTime;
|
||||
me.renderResponse(tabIndex);
|
||||
me.hideLoadingOverlay();
|
||||
});
|
||||
},
|
||||
error: (response, textStatus, errorThrown) => {
|
||||
me.hideLoadingOverlay();
|
||||
$('.toast-body').text(response.responseJSON.error);
|
||||
$('.toast').toast('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -917,7 +998,7 @@ class APITester {
|
||||
|
||||
saveAPIRequest(event) {
|
||||
const me = this;
|
||||
const index = $(event.currentTarget).data('index');
|
||||
const index = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
||||
let model = this.apiRequests[index];
|
||||
me.showLoadingOverlay();
|
||||
|
||||
@@ -946,6 +1027,11 @@ class APITester {
|
||||
|
||||
addAPIRequest(event) {
|
||||
const collectionId = $('#modal_collection').val();
|
||||
let newApiName = $('#new_api_name').val();
|
||||
if (newApiName === '') {
|
||||
newApiName = '새로운 API';
|
||||
}
|
||||
|
||||
const collection = this.collections.filter(function (collection) {
|
||||
return collection.id === collectionId;
|
||||
})[0];
|
||||
@@ -954,12 +1040,14 @@ class APITester {
|
||||
id: '',
|
||||
server: null,
|
||||
method: 'GET',
|
||||
name: 'New Request',
|
||||
name: newApiName,
|
||||
path: '',
|
||||
headers: [],
|
||||
queryParams: [],
|
||||
variables: [],
|
||||
requestBody: '',
|
||||
preRequestScript :'',
|
||||
postRequestScript :'',
|
||||
collectionId: collectionId,
|
||||
responseModel: {
|
||||
status: 0,
|
||||
@@ -991,7 +1079,7 @@ class APITester {
|
||||
|
||||
me.renderTabHeader();
|
||||
me.renderTabContent(me.currentIndex);
|
||||
|
||||
$('#new_api_name').val('');
|
||||
me.hideLoadingOverlay();
|
||||
$('#new_api_request_modal').modal('hide');
|
||||
}
|
||||
@@ -1078,28 +1166,123 @@ class APITester {
|
||||
me.hideLoadingOverlay();
|
||||
me.loadCollections();
|
||||
$('#confirm_delete_api_modal').modal('hide');
|
||||
// $('#confirm_delete_api_modal').find('.confirm_delete_api').removeAttr('data-id');
|
||||
// $('#confirm_delete_api_modal').find('.confirm_delete_api').removeAttr('data-collection');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closeTabWithApiIndex(index) {
|
||||
console.log(index);
|
||||
if (index !== undefined){
|
||||
//console.log('closeTabWithApiIndex: ' + index);
|
||||
const model = this.apiRequests[index];
|
||||
console.log(model);
|
||||
this.apiRequests.splice(index, 1);
|
||||
|
||||
let apiRequestTabTitle = $(this.apiTabTitleTarget);
|
||||
apiRequestTabTitle.empty();
|
||||
this.renderTabHeader();
|
||||
$(`#api_request_${model.id}`).remove();
|
||||
$(`#apiRequestTabTitle li:eq(${this.apiRequests.length - 1}) button`).tab('show');
|
||||
// $(`#apiRequestTabTitle li:eq(${this.apiRequests.length - 1}) button`).tab('show');
|
||||
$(`#apiRequestTabTitle li:eq(0) button`).tab('show');
|
||||
}
|
||||
}
|
||||
closeTab(event) {
|
||||
let index = $(event.currentTarget).closest('button').data('index');
|
||||
//console.log('closeTab: ' + index);
|
||||
const index = $('#apiRequestTabTitle').children().index($(event.currentTarget).closest('.nav-item'));
|
||||
this.closeTabWithApiIndex(index);
|
||||
}
|
||||
|
||||
replacePlaceholdersWithVariables(original, index) {
|
||||
let request = JSON.parse(JSON.stringify(original));
|
||||
|
||||
let mergedVariables = {};
|
||||
_.forEach(this.globalVariables, (value, key) => {
|
||||
mergedVariables[key] = value;
|
||||
});
|
||||
|
||||
if (this.variables[index]) {
|
||||
_.forEach(this.variables[index], (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) {
|
||||
request.headers = request.headers.map(header => {
|
||||
return {
|
||||
...header,
|
||||
key: header.key.replace(new RegExp(placeholder, 'g'), value),
|
||||
value: header.value.replace(new RegExp(placeholder, 'g'), value)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Replace in queryParams
|
||||
if (request.queryParams) {
|
||||
request.queryParams = request.queryParams.map(queryParam => {
|
||||
return {
|
||||
...queryParam,
|
||||
key: queryParam.key.replace(new RegExp(placeholder, 'g'), value),
|
||||
value: queryParam.value.replace(new RegExp(placeholder, 'g'), value)
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
executePreRequestScript(model, index, callback) {
|
||||
let script = model.preRequestScript;
|
||||
let resultFrame = document.getElementById('preRequest');
|
||||
let {headers, method, path, queryParams, requestBody} = model;
|
||||
window.request = {headers, method, path, queryParams, requestBody};
|
||||
this.variables[index] = {};
|
||||
model.variables.forEach((item) =>{
|
||||
if (item.enabled) {
|
||||
this.variables[index][item.key] = item.value;
|
||||
}
|
||||
});
|
||||
|
||||
window.preRequestComplete = function(updatedModel) {
|
||||
callback(updatedModel);
|
||||
};
|
||||
window.temp_variable = this.variables[index];
|
||||
|
||||
resultFrame.srcdoc = `<script>
|
||||
window.globals = window.parent.globals;
|
||||
window.variables = window.parent.temp_variable;
|
||||
window.request = window.parent.request;
|
||||
${script}
|
||||
window.parent.preRequestComplete(window.request);
|
||||
</script>`;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
executePostRequestScript(script, index, response, callback) {
|
||||
let resultFrame = document.getElementById('postRequest');
|
||||
window.response = response;
|
||||
window.parent.temp_variable = this.variables[index];
|
||||
window.postRequestComplete = function(updatedModel) {
|
||||
callback(updatedModel);
|
||||
};
|
||||
window.temp_variable = this.variables[index];
|
||||
resultFrame.srcdoc = `<script>
|
||||
window.globals = window.parent.globals;
|
||||
window.variables = window.parent.temp_variable;
|
||||
window.response = window.parent.response;
|
||||
${script}
|
||||
window.parent.postRequestComplete(window.request);
|
||||
</script>`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
class LayoutUtil {
|
||||
static flattenObject(obj, prefix = '') {
|
||||
return _.reduce(obj, (acc, value, key) => {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key;
|
||||
if (_.isObject(value) && !_.isArray(value)) {
|
||||
_.assign(acc, this.flattenObject(value, fullKey));
|
||||
} else if (_.isArray(value)) {
|
||||
// Process each item in the array
|
||||
value.forEach((item, index) => {
|
||||
// If the item is an object, recurse, otherwise assign directly
|
||||
if (_.isObject(item)) {
|
||||
_.assign(acc, this.flattenObject(item, `${fullKey}[${index}]`));
|
||||
} else {
|
||||
acc[`${fullKey}[${index}]`] = item;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
acc[fullKey] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
static createGroup(groupModel) {
|
||||
let groupHtml = `<div><h6>${groupModel.groupTitle}</h6>`;
|
||||
|
||||
groupModel.fields.forEach(item => {
|
||||
groupHtml += this.createFormElement(item);
|
||||
});
|
||||
|
||||
groupHtml += '</div>';
|
||||
return groupHtml;
|
||||
}
|
||||
|
||||
static createTextInput(elementModel) {
|
||||
return `
|
||||
<div class="form-floating mb-2">
|
||||
<input type="text" name="${elementModel.path}" class="form-control mb-2" id="${elementModel.path}" placeholder="${elementModel.placeholder}">
|
||||
<label for="${elementModel.path}" class="form-label">${elementModel.label}</label>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static createBooleanInput(elementModel) {
|
||||
return `
|
||||
<div class="form-floating mb-2">
|
||||
<div class="form-check form-check-inline">
|
||||
<input type="checkbox" name="${elementModel.path}" class="form-check-input mb-2" id="${elementModel.path}" placeholder="${elementModel.placeholder}">
|
||||
<label class="form-check-label" for="${elementModel.path}" class="form-label">${elementModel.label}</label>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static createSelectInput(elementModel) {
|
||||
const optionsHtml = elementModel.options.map(optionValue => `<option value="${optionValue}">${optionValue}</option>`).join('');
|
||||
|
||||
return `
|
||||
<div class="form-floating mb-2">
|
||||
<select class="form-select mb-2" id="${elementModel.path}" name="${elementModel.path}">
|
||||
${optionsHtml}
|
||||
</select>
|
||||
<label for="${elementModel.path}" class="form-label">${elementModel.label}</label>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static createTextAreaInput(elementModel) {
|
||||
return `
|
||||
<div class="form-floating mb-2">
|
||||
<textarea class="form-control mb-2" name="${elementModel.path}" id="${elementModel.path}" placeholder="${elementModel.placeholder}"></textarea>
|
||||
<label for="${elementModel.path}" class="form-label">${elementModel.label}</label>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
static createFormElement(elementModel) {
|
||||
switch (elementModel.type) {
|
||||
case "boolean":
|
||||
return this.createBooleanInput(elementModel);
|
||||
case "text":
|
||||
return this.createTextInput(elementModel);
|
||||
case "select":
|
||||
return this.createSelectInput(elementModel);
|
||||
case "textarea":
|
||||
return this.createTextAreaInput(elementModel);
|
||||
default:
|
||||
console.error("Unsupported element type: " + elementModel.type);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static createForm(model) {
|
||||
let formHtml = '';
|
||||
model.forEach(group => {
|
||||
formHtml += this.createGroup(group);
|
||||
});
|
||||
return formHtml;
|
||||
}
|
||||
|
||||
static getFieldValue(element) {
|
||||
if ($(element).is('select') || $(element).is('input[type="text"]') || $(element).is('textarea')) {
|
||||
return $(element).val();
|
||||
}
|
||||
if ($(element).is('input[type="checkbox"]')) {
|
||||
return $(element).is(':checked');
|
||||
}
|
||||
}
|
||||
|
||||
static echartReplacer(key, value) {
|
||||
if (key === 'echart' || key === 'series') {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,10 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<select class="form-select" id="modal_collection"></select>
|
||||
<div class="input-group mt-2">
|
||||
<span class="input-group-text">API 이름</span>
|
||||
<input type="text" class="form-control" id="new_api_name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
|
||||
@@ -61,11 +65,14 @@
|
||||
<li th:each="server : ${servers}" th:data-id="${server.id}" th:data-name="${server.name}" th:data-path="${server.basePath}"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<iframe id="preRequest" class="preRequest"></iframe>
|
||||
<iframe id="postRequest" class="postRequest"></iframe>
|
||||
</section>
|
||||
</body>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:src="@{/js/APITester.js}"></script>
|
||||
<script th:src="@{/js/LayoutUtil.js}"></script>
|
||||
<script>
|
||||
$(document).ajaxError(function(event, jqxhr, settings, exception) {
|
||||
if (jqxhr.status === 401) {
|
||||
|
||||
Reference in New Issue
Block a user