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):

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. ä, ö, ü)..."));
}
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.
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));
}
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With