Search code examples
servletsnetflix-zuulspring-cloud-netflix

Processing GET Body with Zuul


I am using Zuul to proxy a strange client that sends a body as part of a GET request. There is unfortunately no way I can change the client.

With curl such a request can be sent as:

curl -XGET 'localhost:8765/kibana/index.html' -d' {"key": "value"}'

And the data is really sent in the body. On zuul side, however, when I try to read the body it is empty. Here is my prototype zuul code:

@Configuration
@ComponentScan
@EnableAutoConfiguration
@Controller
@EnableZuulProxy
public class ZuulServerApplication {

    @Bean
    public ZuulFilter myFilter() {
    return new ZuulFilter(){

        @Override
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request=(HttpServletRequest)ctx.getRequest();
            try {
                InputStream is=request.getInputStream();
                String content=IOUtils.toString(is);
                System.out.println("Request content:"+content);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public boolean shouldFilter() {
            return true;
        }

        @Override
        public int filterOrder() {
            return 10;
        }
        @Override
        public String filterType() {
            return "pre";
        }};
    }
         public static void main(String[] args) {
            new SpringApplicationBuilder(ZuulServerApplication.class).web(true).run(args);
        }

    }

If I send a POST request, the this code prints the request body without problem. However, if I send the above GET request, the body is not printed. Anything I can do to actually get the body sent as part of a GET request?


Solution

  • It seems that some underlying machinery[0], e.g. some built-in Zuul filter with lesser filter order, replaces default "raw" HttpServletRequest with HttpServletRequestWrapper which, under standard circumstances (i.e. not GET method with body), is able to handle multiple acquisition of input stream. But in the case of GET method with body HttpServletRequestWrapper seems to not proxy input stream at all.

    Thus solution could be to change filterOrder e.g. to -10.

    Then it works for the filter since HttpServletRequest is used - the mentioned machinery did not get to its turn and thus didn't replace HttpServletRequest with HttpServletRequestWrapper yet. But potential issue with this solution is that the filter might exhaust input stream for something else, e.g. filter with higher filter order. But since GET with body is not a good practice anyway, it might be good enough solution after all :)

    [0] I've debug into this longer time ago, but did not get to exact point - thus vague definition of "the machinery".