새 컬렉션 추가, 로딩, 새 요청 추가

This commit is contained in:
현성필
2023-05-15 15:47:33 +09:00
parent f12352db52
commit 78277d271d
22 changed files with 653 additions and 87 deletions
@@ -2,13 +2,9 @@ package com.eactive.httpmockserver.client.controller;
import com.eactive.httpmockserver.client.dto.ApiRequestDTO;
import com.eactive.httpmockserver.client.dto.ApiResponse;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.entity.Server;
import com.eactive.httpmockserver.client.repository.ServerRepository;
import com.eactive.httpmockserver.client.service.ApiTesterService;
import com.eactive.httpmockserver.client.service.NettyApiClient;
import com.eactive.httpmockserver.common.security.CurrentUser;
import com.eactive.httpmockserver.user.entity.StaffUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
@@ -25,13 +21,10 @@ public class ApiClientController {
@Autowired
private ServerRepository serverRepository;
@Autowired
private ApiTesterService apiTesterService;
@Autowired
private NettyApiClient nettyApiClient;
@PostMapping("/api/test.do")
@PostMapping("/mgmt/api/test.do")
@ResponseBody
public ApiResponse handleApiRequest(@RequestBody ApiRequestDTO request) {
@@ -43,14 +36,10 @@ public class ApiClientController {
}
@GetMapping("/mgmt/api_tester.do")
public String testView(ModelMap model,
@CurrentUser StaffUser user) {
public String testView(ModelMap model) {
List<Server> servers = serverRepository.findAll();
List<ApiCollection> collections = apiTesterService.findMyCollections(user.getEsntlId());
model.addAttribute("servers", servers);
model.addAttribute("collections", collections);
return "page/apiTester";
}
@@ -0,0 +1,75 @@
package com.eactive.httpmockserver.client.controller;
import com.eactive.httpmockserver.client.dto.ApiCollectionDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestDTO;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.entity.ApiRequestInfo;
import com.eactive.httpmockserver.client.mapper.ApiRequestMapper;
import com.eactive.httpmockserver.client.service.ApiRequestMgmtService;
import com.eactive.httpmockserver.common.security.CurrentUser;
import com.eactive.httpmockserver.user.entity.StaffUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class ApiRequestMgmtController {
@Autowired
ApiRequestMgmtService apiRequestMgmtService;
@Autowired
ApiRequestMapper apiRequestMapper;
@GetMapping("/mgmt/collections/list.do")
public ResponseEntity<List<ApiCollectionDTO>> listApiRequests(@CurrentUser StaffUser user) {
List<ApiCollection> collections = apiRequestMgmtService.getMyApis(user);
return ResponseEntity.ok(apiRequestMapper.mapCollections(collections));
}
@PostMapping("/mgmt/collections/create.do")
public ResponseEntity<String> createApiCollection(
@CurrentUser StaffUser user,
@RequestBody ApiCollectionDTO dto) {
ApiCollection collection = apiRequestMapper.map(dto);
collection.setOwner(user);
apiRequestMgmtService.createNewApiCollection(collection);
return ResponseEntity.ok("success");
}
@PutMapping("/mgmt/collections/update.do")
public ResponseEntity<String> updateApiCollection(@RequestBody ApiCollectionDTO dto) {
ApiCollection updated = apiRequestMapper.map(dto);
apiRequestMgmtService.updateApiCollection(updated.getId(), updated);
return ResponseEntity.ok("success");
}
@PostMapping("/mgmt/collections/delete.do")
public ResponseEntity<String> deleteApiCollection(@RequestBody ApiCollectionDTO dto) {
apiRequestMgmtService.deleteApiCollection(dto.getId());
return ResponseEntity.ok("success");
}
@PostMapping("/mgmt/collections/{id}/apis/save.do")
public ResponseEntity<String> addApiToCollection(@PathVariable(name = "id") String id,
@RequestBody ApiRequestDTO dto,
@CurrentUser StaffUser user) {
ApiRequestInfo apiRequestInfo = apiRequestMapper.map(dto);
apiRequestInfo.setOwner(user);
String apiId = apiRequestMgmtService.saveApiToCollection(id, apiRequestInfo);
return ResponseEntity.ok(apiId);
}
@PostMapping("/mgmt/collections/{id}/apis/delete.do")
public ResponseEntity<String> removeApiFromCollection(@PathVariable(name = "id") String id,
@RequestBody ApiRequestDTO dto) {
apiRequestMgmtService.removeApiFromCollection(id, dto.getId());
return ResponseEntity.ok("success");
}
}
@@ -0,0 +1,39 @@
package com.eactive.httpmockserver.client.dto;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
public class ApiCollectionDTO {
private String id;
@NotEmpty
private String name;
private List<ApiRequestDTO> apis = new ArrayList<>();
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setApis(List<ApiRequestDTO> apis) {
this.apis = apis;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public List<ApiRequestDTO> getApis() {
return apis;
}
}
@@ -1,17 +1,40 @@
package com.eactive.httpmockserver.client.dto;
import java.util.ArrayList;
import java.util.List;
public class ApiRequestDTO {
private String id;
private String name;
private String path;
private String method;
private Long server;
private List<ApiHeaderDTO> headers;
private List<ApiRequestKeyValueDTO> headers = new ArrayList<>();
private List<ApiRequestKeyValueDTO> queryParams = new ArrayList<>();
private String requestBody;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
@@ -36,14 +59,22 @@ public class ApiRequestDTO {
this.method = method;
}
public List<ApiHeaderDTO> getHeaders() {
public List<ApiRequestKeyValueDTO> getHeaders() {
return headers;
}
public void setHeaders(List<ApiHeaderDTO> headers) {
public void setHeaders(List<ApiRequestKeyValueDTO> headers) {
this.headers = headers;
}
public List<ApiRequestKeyValueDTO> getQueryParams() {
return queryParams;
}
public void setQueryParams(List<ApiRequestKeyValueDTO> queryParams) {
this.queryParams = queryParams;
}
public String getRequestBody() {
return requestBody;
}
@@ -1,6 +1,6 @@
package com.eactive.httpmockserver.client.dto;
public class ApiHeaderDTO {
public class ApiRequestKeyValueDTO {
private boolean enabled;
@@ -30,4 +30,8 @@ public class ApiHeaderDTO {
public void setValue(String value) {
this.value = value;
}
public String toString() {
return (enabled?"//":"")+ key + "=" + value;
}
}
@@ -6,7 +6,7 @@ public class ApiResponse {
private int status;
private List<ApiHeaderDTO> headers;
private List<ApiRequestKeyValueDTO> headers;
private String body;
@@ -20,11 +20,11 @@ public class ApiResponse {
this.status = status;
}
public List<ApiHeaderDTO> getHeaders() {
public List<ApiRequestKeyValueDTO> getHeaders() {
return headers;
}
public void setHeaders(List<ApiHeaderDTO> headers) {
public void setHeaders(List<ApiRequestKeyValueDTO> headers) {
this.headers = headers;
}
@@ -3,6 +3,7 @@ package com.eactive.httpmockserver.client.entity;
import com.eactive.httpmockserver.user.entity.StaffUser;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@@ -20,11 +21,11 @@ public class ApiCollection {
@ManyToMany
@JoinTable(
name = "API_COLLECTION_API_REQUEST_INFO",
joinColumns = @JoinColumn(name = "API_COLLECTION_ID"),
inverseJoinColumns = @JoinColumn(name = "API_REQUEST_INFO_ID")
name = "API_COLLECTION_API_REQUEST_INFO",
joinColumns = @JoinColumn(name = "API_COLLECTION_ID"),
inverseJoinColumns = @JoinColumn(name = "API_REQUEST_INFO_ID")
)
private List<ApiRequestInfo> apis;
private List<ApiRequestInfo> apis = new ArrayList<>();
public String getId() {
return id;
@@ -3,6 +3,7 @@ package com.eactive.httpmockserver.client.entity;
import com.eactive.httpmockserver.user.entity.StaffUser;
import javax.persistence.*;
import java.util.Objects;
@Entity
@@ -20,6 +21,8 @@ public class ApiRequestInfo {
@JoinColumn(name = "USER_ID")
private StaffUser owner;
private String name;
private String method;
private String path;
@@ -30,6 +33,14 @@ public class ApiRequestInfo {
private String requestBody;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
@@ -93,4 +104,26 @@ public class ApiRequestInfo {
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ApiRequestInfo that = (ApiRequestInfo) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id, server, owner, method, path, headers, queryParams, requestBody);
}
public static void main(String[] args) {
ApiRequestInfo a= new ApiRequestInfo();
a.setId("a");
ApiRequestInfo b = new ApiRequestInfo();
a.setId("a");
System.out.println(a.equals(b));
}
}
@@ -0,0 +1,34 @@
package com.eactive.httpmockserver.client.mapper;
import com.eactive.httpmockserver.client.dto.ApiCollectionDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestKeyValueDTO;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.entity.ApiRequestInfo;
import com.eactive.httpmockserver.common.mapper.CommonMapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper(componentModel = "spring",
uses = {CommonMapper.class, ServerMapper.class},
unmappedTargetPolicy = ReportingPolicy.IGNORE)
@Component
public interface ApiRequestMapper {
ApiCollection map(ApiCollectionDTO dto);
ApiRequestInfo map(ApiRequestDTO dto);
ApiRequestDTO map(ApiRequestInfo entity);
List<ApiRequestInfo> mapApis(List<ApiRequestDTO> apis);
List<ApiCollectionDTO> mapCollections(List<ApiCollection> apis);
}
@@ -0,0 +1,30 @@
package com.eactive.httpmockserver.client.mapper;
import com.eactive.httpmockserver.client.entity.Server;
import com.eactive.httpmockserver.client.repository.ServerRepository;
import com.eactive.httpmockserver.common.exception.NotFoundException;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Mapper(componentModel = "spring",
unmappedTargetPolicy = ReportingPolicy.IGNORE)
@Component
public class ServerMapper {
@Autowired
ServerRepository serverRepository;
Server map(Long id) {
if (id == null) return null;
return serverRepository.findById(id).orElseThrow(() -> new NotFoundException("Server[" + id + "] not found"));
}
Long map(Server server) {
if (server == null) return null;
return server.getId();
}
}
@@ -1,8 +1,13 @@
package com.eactive.httpmockserver.client.repository;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.entity.ApiRequestInfo;
import com.eactive.httpmockserver.user.entity.StaffUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface ApiRequestRepository extends JpaRepository<ApiRequestInfo, String>, JpaSpecificationExecutor<ApiRequestInfo> {
}
@@ -0,0 +1,84 @@
package com.eactive.httpmockserver.client.service;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.entity.ApiRequestInfo;
import com.eactive.httpmockserver.client.repository.ApiCollectionRepository;
import com.eactive.httpmockserver.client.repository.ApiRequestRepository;
import com.eactive.httpmockserver.common.exception.NotFoundException;
import com.eactive.httpmockserver.user.entity.StaffUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;
import javax.transaction.Transactional;
import java.util.List;
import java.util.UUID;
@Service
@Transactional
public class ApiRequestMgmtService {
@Autowired
ApiCollectionRepository apiCollectionRepository;
@Autowired
ApiRequestRepository apiRequestRepository;
public List<ApiCollection> getMyApis(StaffUser user) {
return apiCollectionRepository.findAllByOwner(user);
}
public void deleteApiCollection(String id) {
apiCollectionRepository.deleteById(id);
}
public void createNewApiCollection(ApiCollection collection) {
collection.setId(UUID.randomUUID().toString());
apiCollectionRepository.save(collection);
}
public void updateApiCollection(String id, ApiCollection updated) {
ApiCollection collection = apiCollectionRepository.findById(id).orElseThrow(() -> new NotFoundException("api collection[" + id + "] not found"));
collection.setName(updated.getName());
apiCollectionRepository.save(collection);
}
public String saveApiToCollection(String id, ApiRequestInfo api) {
ApiCollection collection = apiCollectionRepository.findById(id).orElseThrow(() -> new NotFoundException("api collection[" + id + "] not found"));
if (StringUtils.isEmpty(api.getId())) {
api.setId(UUID.randomUUID().toString());
apiRequestRepository.save(api);
} else {
String apiId = api.getId();
ApiRequestInfo existing = apiRequestRepository.findById(apiId).orElseThrow(() -> new NotFoundException("api[" + apiId + "] not found"));
existing.setName(api.getName());
existing.setMethod(api.getMethod());
existing.setPath(api.getPath());
existing.setHeaders(api.getHeaders());
existing.setQueryParams(api.getQueryParams());
existing.setServer(api.getServer());
existing.setRequestBody(api.getRequestBody());
apiRequestRepository.save(existing);
api = existing;
}
if (!collection.getApis().contains(api)) {
collection.getApis().add(api);
apiCollectionRepository.save(collection);
}
return api.getId();
}
public void removeApiFromCollection(String id, String apiId) {
ApiCollection collection = apiCollectionRepository.findById(id).orElseThrow(() -> new NotFoundException("api collection[" + id + "] not found"));
ApiRequestInfo api = apiRequestRepository.findById(apiId).orElseThrow(() -> new NotFoundException("api[" + apiId + "] not found"));
collection.getApis().remove(api);
apiCollectionRepository.save(collection);
}
}
@@ -1,25 +0,0 @@
package com.eactive.httpmockserver.client.service;
import com.eactive.httpmockserver.client.entity.ApiCollection;
import com.eactive.httpmockserver.client.repository.ApiCollectionRepository;
import com.eactive.httpmockserver.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@Service
@Transactional
public class ApiTesterService {
@Autowired
private UserService userService;
@Autowired
ApiCollectionRepository apiCollectionRepository;
public List<ApiCollection> findMyCollections(String esntlId) {
return apiCollectionRepository.findAllByOwner(userService.findByEsntlId(esntlId));
}
}
@@ -1,6 +1,6 @@
package com.eactive.httpmockserver.client.service;
import com.eactive.httpmockserver.client.dto.ApiHeaderDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestKeyValueDTO;
import com.eactive.httpmockserver.client.dto.ApiResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@@ -49,10 +49,10 @@ public class HttptHandler extends SimpleChannelInboundHandler<FullHttpResponse>
return headerSize;
}
public List<ApiHeaderDTO> convertHttpHeadersToList(HttpHeaders headers) {
List<ApiHeaderDTO> headerList = new ArrayList<>();
public List<ApiRequestKeyValueDTO> convertHttpHeadersToList(HttpHeaders headers) {
List<ApiRequestKeyValueDTO> headerList = new ArrayList<>();
for (Map.Entry<String, String> entry : headers.entries()) {
ApiHeaderDTO header = new ApiHeaderDTO();
ApiRequestKeyValueDTO header = new ApiRequestKeyValueDTO();
header.setKey(entry.getKey());
header.setValue(entry.getValue());
headerList.add(header);
@@ -1,6 +1,6 @@
package com.eactive.httpmockserver.client.service;
import com.eactive.httpmockserver.client.dto.ApiHeaderDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestKeyValueDTO;
import com.eactive.httpmockserver.client.dto.ApiRequestDTO;
import com.eactive.httpmockserver.client.dto.ApiResponse;
import com.eactive.httpmockserver.client.entity.Server;
@@ -91,7 +91,7 @@ public class NettyApiClient {
if (apiRequest.getHeaders().size() > 0) {
HttpHeaders customHeaders = new DefaultHttpHeaders();
apiRequest.getHeaders().stream().filter(ApiHeaderDTO::isEnabled).forEach((header) -> {
apiRequest.getHeaders().stream().filter(ApiRequestKeyValueDTO::isEnabled).forEach((header) -> {
if(StringUtils.isNotEmpty(header.getKey()) && StringUtils.isNotEmpty(header.getValue())){
customHeaders.set(header.getKey(), header.getValue());
}
@@ -0,0 +1,34 @@
package com.eactive.httpmockserver.common.exception;
import java.time.LocalDateTime;
public class CustomErrorResponse {
private LocalDateTime timestamp;
private String error;
private int status;
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
@@ -0,0 +1,24 @@
package com.eactive.httpmockserver.common.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.time.LocalDateTime;
@RestControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<CustomErrorResponse> customHandleNotFound(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
}
}
@@ -1,5 +1,6 @@
package com.eactive.httpmockserver.common.mapper;
import com.eactive.httpmockserver.client.dto.ApiRequestKeyValueDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
@@ -41,4 +42,40 @@ public class CommonMapper {
return grantedAuthorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
}
public String mapKeyValue(List<ApiRequestKeyValueDTO> list) {
if (list == null) return "";
StringBuilder result = new StringBuilder();
for (ApiRequestKeyValueDTO dto : list) {
result.append(dto.toString()).append("||");
}
if (result.length() > 0) {
result.setLength(result.length() - 2); // Remove the last "||"
}
return result.toString();
}
public List<ApiRequestKeyValueDTO> keyValueToList(String keyValue) {
List<ApiRequestKeyValueDTO> list = new ArrayList<>();
if (!StringUtils.hasLength(keyValue)) return list;
String[] pairs = keyValue.split("\\|\\|");
for (String pair : pairs) {
ApiRequestKeyValueDTO dto = new ApiRequestKeyValueDTO();
if (pair.startsWith("//")) {
dto.setEnabled(false);
pair = pair.substring(2);
} else {
dto.setEnabled(true);
}
String[] keyValueArray = pair.split("=");
if (keyValueArray.length == 2) {
dto.setKey(keyValueArray[0]);
dto.setValue(keyValueArray[1]);
list.add(dto);
}
}
return list;
}
}