Search code examples
netflix-zuul

Is there a way to change http request method in netflix zuul routing filter?


I'm trying to trasform http GET method call from legacy api server built with MVC1 pattern to new restful api server without any change of front-end source code using netflix zuul and eureka.

I added zuul pre filter transforming legacy url to restful convention url working after PreDecorationFilter and it works fine.

But now I'm facing problem converting the GET method to proper method like POST, PUT, DELETE by distinguising url so that the requests are properly mapped in spring controller via @GetMapping/@PostMapping/@PutMapping/@DeleteMapping.

I looked into SimpleRoutingFilter that handles HttpClient but Because of environmental constraint, I have to use eureka service id to route to the new api server and that means I should use RibbonRoutingFilter which is quite complicated to find out a right place to this operation in.

So, is this possible to change http method or make new http request before RibbonRoutingFilter? If possible can you please suggest where is the right place to do that or some reference?

Many thanks!

======================================================================

Milenko Jevremovic,

Would you please tell me more detail about using Feign?

I defiend @FeignClient like below

@PostMapping(value = "{url"}, consumes = "application/json")
ResponseEntity<?> postMethod(@PathVariable("url") String url);

and to get query parameters to request body for POST In zuul pre filter,

after transform logic from GET request url to POST new restful url ...

byte[] bytes = objectMapper.writeValueAsBytes(ctx.get("requestQueryParams"));
ctx.setRequests(new HttpServletRequestWrapper(request) {
  @Override ..getMethod
  @Override ..getContentLength
  @Override ..getConentLengthLong
  @Override
  public ServletInputStream getInputStream() {
    return new ServletInputStreamWrapper(bytes);
  }
}
ResponseEntity<?> response feignClient.post(transformedNewApiUri);

and set RequestContext code that you suggested ....

and controller of new api server is like,

@PostMapping
ResponseEntity<model> post(@RequestBody req..)

It comes to controller fine but when I see the http request in post method of controller, There is no request body for parameters.

(HttpServleterRequest getInputStream shows empty)

The request data set in zuul pre filter by HttpServletRequestWrapper is not used in Feign maybe...? Would you please get me more idea setting request body when changing GET query to POST constructor for using Feign?


Solution

  • After doing some research did not find any built in solution.

    But what comes in my mind you can use Feign client in your Pre filter, get the response, set the response and return it immediately to client from your Pre filter.

    You can set Feign client url or your service id, like it is explained in the docs, it uses ribbon as well .

    Change response in your run method like:

    ...
    RequestContext ctx = RequestContext.getCurrentContext();
    ctx.setResponseStatusCode(your_code);
    ctx.setResponseBody(new_body);
    ctx.setSendZuulResponse(false);
    
    return null