보안상의 문제로 기존에 존재하는 정해진 api 서버로 bypass 하는 서비스를 구현해야 했다.
지금은 bypass 하지만 시간이 지나서 앞에 bypass하는 서비스가 없어질수도 있단 생각을 하면서 방법을 찾아보았다.
간단하게 구현하기 위해서 resttemplate로 요청을 그대로 다음 서비스로 넘겨주게 구현했다.
@RequestMapping("/proxy/**")
@RequiredArgsConstructor
public class ProxyController {
private final HttpApiRequest httpApiRequest;
@GetMapping
public ResponseEntity<ApiResponseModel> getProxy(HttpServletRequest request, HttpServletResponse response,
@RequestBody(required = false) Object body) throws URISyntaxException {
return ResponseEntity.ok(ApiResponseModel.success(httpApiRequest.exchange(request, body).getBody()));
}
@PostMapping
public ResponseEntity<ApiResponseModel> postProxy(HttpServletRequest request, HttpServletResponse response,
@RequestBody(required = false) Object body) throws URISyntaxException {
return ResponseEntity.ok(ApiResponseModel.success(httpApiRequest.exchange(request, body).getBody()));
}
@PutMapping
public ResponseEntity<ApiResponseModel> putProxy(HttpServletRequest request, HttpServletResponse response,
@RequestBody(required = false) Object body) throws URISyntaxException {
return ResponseEntity.ok(ApiResponseModel.success(httpApiRequest.exchange(request, body).getBody()));
}
@DeleteMapping
public ResponseEntity<ApiResponseModel> deleteProxy(HttpServletRequest request, HttpServletResponse response,
@RequestBody(required = false) Object body) throws URISyntaxException {
return ResponseEntity.ok(ApiResponseModel.success(httpApiRequest.exchange(request, body).getBody()));
}
}
RequestBody의 타입을 byte[]로 해서 json 구조가 아닌 요청도 proxy 서비스의 변경없이 처리할 수 있도록 구현했다. 하지만 resttemplate.exchange() 메소드로 넘겼을 때, 예상과 달리 처리하지 못해서 현재 서비스에서는 json 구조외에 없을것으로 예상하고 Object타입을 body로 받게 수정했다. public ResponseEntity<?> exchange(HttpServletRequest request,
@RequestBody(required = false) Object body) throws URISyntaxException {
String originReqURL = request.getRequestURI().replaceAll("^/la-lms", "");
String originQueryString = request.getQueryString();
String urlStr = LMS_API_DOMAIN_NAME + originReqURL + (StringUtils.isEmpty(originQueryString) ? "" : "?"+originQueryString);
URI url = new URI(urlStr);
// header
Enumeration<String> headerNames = request.getHeaderNames();
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
while(headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
if (headerName.equalsIgnoreCase("host")) { // host 정보는 header에서 제외
continue;
}
headers.add(headerName, request.getHeader(headerName));
}
// http entity (body, header)
HttpEntity<Object> httpEntity = new HttpEntity<>(body, headers);
return restTemplate.exchange(url, HttpMethod.valueOf(request.getMethod()), httpEntity, Object.class);
}