0

I have a SpringBoot application which simply acts as a middleman. It receives an API request in JSON and forwards this to another server S by calling S's API with the exact same body.

I was exploring the solutions and came across a solution which involved the usage of RestTemplate and MultiValueMap. However, since the json body contains objects rather than simple String, I believe I have to create a DTO with corresponding POJO for the solution to work.

May I ask is the above the only solution, or there is a simple way to forward the request over and get back the response?

xcoder
  • 1,336
  • 2
  • 17
  • 44
  • is another Server S simply a different server or different app ( than middleman ) on different server ? is server S also under your control ? – Sabir Khan Dec 13 '18 at 06:21
  • Server S is a completely different app on a different server, and is not under any of my control. – xcoder Dec 13 '18 at 06:23
  • I think, you are looking for something like [this](https://stackoverflow.com/questions/12130992/forward-httpservletrequest-to-a-different-server) – Sabir Khan Dec 13 '18 at 06:30

2 Answers2

0

The middleman server can expose a endpoint that accepts a @RequestBody of Object and HttpServletRequest then use RestTemplate to forward it to the remote server.

The middleman

@RestController
@RequestMapping("/middleman")
public class MiddleManRestController {

    private RestTemplate restTemplate;

    @PostConstruct
    public void init() {
        this.restTemplate = new RestTemplate();
        this.restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(this.restTemplate.getRequestFactory()));
    }

    @RequestMapping(value = "/forward", method = RequestMethod.POST)
    public ResponseEntity<Object> forward(@RequestBody Object object, HttpServletRequest request) throws RestClientException {

        //setup the url and path
        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("Remote server URL").path("EnpointPath");

        //add query params from previous request
        addQueryParams(request, builder);

        //specify the method
        final RequestEntity.BodyBuilder requestBuilder = RequestEntity.method(HttpMethod.POST, builder.build().toUri());

        //add headers from previous request
        addHeaders(request, requestBuilder);

        RequestEntity<Object> requestEntity = requestBuilder.body(object);
        ParameterizedTypeReference<Object> returnType = new ParameterizedTypeReference<Object>() {};

        //forward to the remote server
        return this.restTemplate.exchange(requestEntity, returnType);
    }

    private void addHeaders(HttpServletRequest request, RequestEntity.BodyBuilder requestBuilder) {
        Enumeration<String> headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            requestBuilder.header(headerName, headerValue);
        }
    }

    private void addQueryParams(HttpServletRequest request, UriComponentsBuilder builder) {
        final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (parameterMap != null) {
            parameterMap.forEach((key, value) -> queryParams.addAll(key, Arrays.asList(value)));
        }
        builder.queryParams(queryParams);
    }
}
Rentius2407
  • 1,108
  • 2
  • 11
  • 29
0

Even complex and nested JSON objects can be taken into a Map with key as String and value as Object. I believe you should just use such a map as your request body and transfer the same to another api.

VaV
  • 1
  • 1