Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Webflux - Set UTF-8 Encoding

I've been working with Spring Boot 2.0.0.RC1 and use spring-boot-starter-webflux in order to build a REST Controller that returns a flux of text data.

@GetMapping(value = "/")
public Flux<String> getData(){
    return Flux.interval(Duration.ofSeconds(2))
        .map(l -> "Some text with umlauts (e.g. ä, ö, ü)...");
}

Since the text data contains some umlauts (e.g. ä, ö, ü), I would like to change the Content-Type header of the response from text/event-stream to text/event-stream;charset=UTF-8. Therefore, I tried wrapping to flux into a ResponseEntity. Like this:

@GetMapping(value = "/")
public ResponseEntity<Flux<String>> getData(){
    return ResponseEntity
            .ok()
            .contentType(MediaType.parseMediaType("text/event-stream;charset=UTF-8"))
            .body(Flux.interval(Duration.ofSeconds(2))
                    .map(l -> "Some text with umlauts (e.g. ä, ö, ü)..."));
}

Now, making a curl request to the endpoint shows that the Content-Type remains the same:

< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: text/event-stream
<
data:Some text with umlauts (e.g. ├ñ, ├Â, ├╝)...

I suspected the MediaType.parseMediaType() method to be the issue, but the media type is parsed correctly (as this screenshot shows):

this

However, the parameter charset seems to be ignored. How can I change the encoding to UTF-8 so that the browser interprets the umlaut characters correctly?

EDIT: Setting within the GetMapping annotation the produces field does not work either.

@GetMapping(value = "/", produces = "text/event-stream;charset=UTF-8")
public ResponseEntity<Flux<String>> getData(){
    return ResponseEntity
            .accepted()
            .contentType(MediaType.parseMediaType("text/event-stream;charset=UTF-8"))
            .body(Flux.interval(Duration.ofSeconds(2))
                    .map(l -> "Some text with umlauts (e.g. ä, ö, ü)..."));
}
like image 352
Michael Stadler Avatar asked May 08 '26 07:05

Michael Stadler


1 Answers

The problem here is that Spring uses the StringHttpMessageConverter to convert the Flux<String> into the http response body. This converter defaults to the ISO-8859-1 charset, even though UTF-8 is required by specification when you use produces = "text/event-stream"

in org/springframework/http/converter/StringHttpMessageConverter.java:51

     ...
     public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
     ...

You can work around this in two ways.

  1. Change the default encoding of StringHttpMessageConverter to UTF-8:

     @Configuration
     @EnableWebMvc
     public class WebConfig implements WebMvcConfigurer {
    
       @Override
       public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
           converters.stream()
                   .filter(converter -> converter instanceof StringHttpMessageConverter)
                   .forEach(converter -> 
                        ((StringHttpMessageConverter) converter)
                             .setDefaultCharset(StandardCharsets.UTF_8));
       }
     }
    
  2. or return a JSON a.k.a a custom object instead of String from your method. That way, Spring uses the MappingJackson2HttpMessageConverter which writes in UTF-8.

    Change the return type of java.lang.String

     @GetMapping(value = "/", produces = "text/event-stream")
     public Flux<String> getData(){
         return Flux.interval(Duration.ofSeconds(2))
             .map(l -> "Some text with umlauts (e.g. ä, ö, ü)...");
     }
    

    to an object of your choice

    @GetMapping(value = "/", produces = "text/event-stream")
    public Flux<MyStringData> getData(){
         return Flux.interval(Duration.ofSeconds(2))
             .map(l -> new MyStringData("Some text with umlauts (e.g. ä, ö, ü)..."));
    }
    
    public record MyStringData(String data) {}
    

    and your response will be in UTF-8 (but also in JSON)

See also this question here: How to overwrite StringHttpMessageConverter DEFAULT_CHARSET to use UTF8 in spring 4

like image 133
Manuel Avatar answered May 10 '26 19:05

Manuel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!