Spring-Cloud Zuul breaks UTF-8 symbols in forwarde

2019-05-10 12:47发布

问题:

this is first time for me on SO, so please be patient for my first question.

I think i have some kind of configuration problem, but after a day of experiments i'm stuck. Our application is based on Spring-Cloud [Brixton release]. We have configuration like this: Portal (web application serving angular-based web-ui), which has zuul proxy with single route configured to our gateway service, like so:

zuul:
   ignoredServices: '*'
   prefix: /api
   routes:
       api-proxy:
          path: /**
          serviceId: api-gateway

which has another Zuul configured and relays requests to inner bussiness logic services:

zuul:
  ignoredServices: '*'
  routes:
     service1:
       path: /service1/**
       serviceId: service1
     service2:
       path: /service2/**
       serviceId: service2

All this configuration is working with no problem. The problem now that i am facing is with file upload multipart requests. To be more precise - those multipart requests, when file to be uploaded has non latin symbols (e.g. ąčęėįš) from UTF-8. When request reaches service which has to deal with @RequestPart MultipartFile file, then file.getOriginalFilename() returns questionmarks in the places of aforementioned symbols. Now, i have tried to directly upload such file to such controller, and filename comes without questionmarks, that is, not broken, which suggests, that some bad interpretation/parsing of multipart request occurs somewhere in Zuul filters, when proxy relays incomming request.

Maybe someone had similar experience with Zuul and can direct me some way to resolve this problem?

回答1:

I just ran into the same issue myself, and created the following issue:

https://jira.spring.io/browse/SPR-15396

Hopefully this is getting configurable in Spring 4.3.8.

In the meantime, you have to create a bean of type FormBodyWrapperFilter (that overrides the one in ZuulConfiguration). In the constructor, you pass a copy of FormHttpMessageConverter, which extends from FormHttpMessageConverter, and you change the encoding used in FormHttpMessageConverter.MultipartHttpOutputMessage#getAsciiBytes(String) to UTF-8 (you might also want to delete any references to javax-mail, unless you have that on classpath). You need a pretty recent version of Spring Cloud Netflix to do this.

Example:

@Bean
FormBodyWrapperFilter formBodyWrapperFilter() {
    return new FormBodyWrapperFilter(new MyFormHttpMessageConverter());
}

Then you create a copy of FormHttpMessageConverter, and change the following method:

    private byte[] getAsciiBytes(String name) {
        try {
            // THIS IS THE ONLY MODIFICATION:
            return name.getBytes("UTF-8");
        } catch (UnsupportedEncodingException ex) {
            // Should not happen - US-ASCII is always supported.
            throw new IllegalStateException(ex);
        }
    }