Issue
The aim of my application is listening all requests. Then URL have to be changed and send absolutely the same request to changed URL. Any request params, headers, body(I don't know if there are anythnig else).... everything have to be the same.
I don't know anything about request. It might GET or POST or even PUT or PATCH etc.
Also I don't know anything about body content. Iy might be json or binary.
Now I wrote following code:
@RequestMapping(value = "/**")
public ResponseEntity proxy(HttpServletRequest reqt) throws IOException {
String body = IOUtils.toString(reqt.getReader());
HttpEntity httpEntity = new HttpEntity<>(body)
try {
ResponseEntity<Object> ex = restTemplate.exchange(someUrl+ request.getRequestURI(),
HttpMethod.valueOf(reqt.getMethod()),
httpEntity ,
Object.class,
reqt.getParameterMap());
return ex;
} catch (final HttpClientErrorException excep) {
return new ResponseEntity<>(excep.getResponseBodyAsByteArray(), excep.getResponseHeaders(), excep.getStatusCode());
}
}
What do you think about solution like this?
Is it working idea for my requirements?
Is there better approach?
Solution
I have a similar proxy in a project. But you have to remove the CONNECTION and TRANSFER_ENCODING headers from the response, because these are properties of the actual response what will be generated by YOUR server and the settings could be different than the remote server. (If these headers are present in your responseEntity then the server won't override them with the proper value, so the returned header and the actual state of the response could be inconsistent. Eg.: the remote server returns CLOSED connection but your apache settings allows KEEP-ALIVE)
Maybe you need to alter some other headers too, but for me these two were enough.
@RequestMapping(value = "/**")
public ResponseEntity route(HttpServletRequest reqt) throws IOException {
String body = IOUtils.toString(reqt.getReader());
try {
ResponseEntity<Object> response = restTemplate.exchange(someUrl+ request.getRequestURI(),
HttpMethod.valueOf(request.getMethod()),
new HttpEntity<>(body),
Object.class,
request.getParameterMap());
final HttpHeaders responseHeaders = new HttpHeaders();
response.getHeaders().entrySet().stream().forEach(e -> responseHeaders.put(e.getKey(), e.getValue()));
responseHeaders.remove(HttpHeaders.CONNECTION);
responseHeaders.remove(HttpHeaders.TRANSFER_ENCODING);
return new ResponseEntity<>(response.getBody(), responseHeaders, response.getStatusCode());
} catch (final HttpClientErrorException e) {
return new ResponseEntity<>(e.getResponseBodyAsByteArray(), e.getResponseHeaders(), e.getStatusCode());
}
}
one more thing. If you turn off the error handling in the Resttemplate then you don't have to handle the client exceptions. All responses - including 401,404,etc will be forwarded as is.
@PostConstruct
public void init() {
restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// Response is forwarded to the client without any error handling.
}
});
}
Answered By - Selindek Answer Checked By - Katrina (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.