logbook: The log contains Chinese, which is not displayed correctly.

Description

When print Chinese in Spring Boot projects, then looks like not right, for example:

{"code":45,"name":"广西壮族自治区"}

Expected Behavior

Print Chinese normal, like this:

{"code":45,"name":"广西壮族自治区"}

Actual Behavior

{"code":45,"name":"广西壮族自治区"}

Possible Fix

Must force set utf-8 encoding

server:
  servlet:
    encoding:
      enabled: true
      charset: UTF-8
      force: true

The root cause of this problem

image

The priority order for specifying the response body is:

  1. explicitly per request using setCharacterEncoding and setContentType
  2. implicitly per request using setLocale
  3. per web application via the deployment descriptor or ServletContext.setRequestCharacterEncoding(String)
  4. container default via vendor specific configuration
  5. ISO-8859-1

If any possible, get encoding form somewhere else. image

Your Environment

  • Version used: org.zalando:logbook-spring-boot-starter:2.3.0 & Spring Boot Ver: 2.3.4.RELEASE

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 36 (15 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @kasmarian just sharing a small app to help you reproduce the problem. In the README.md I’ve shared two links to the different API paths (one working and other not working) being the only difference the usage of Thymeleaf.

Project Link

The PR is merged and will be available in the next release. I’d like to resolve this issue. Feel free to reopen it, if it’s not fully addressed.

Thank you @kasmarian ! Any ETA for a release?

I think we can do it this week. Let me chat with the team about it

ok, another fix is merged. Hope this one doesn’t break anything else 😄

Hi @kasmarian

I’ve check your PR and I believe that will fix our use-cases.

Thank you very much for your effort solving this problem

@whiskeysierra Is it possible to reconsider the fix? As @kyle18th commented, Spring Boot does not provide the (legal) way to set the response charset when the content type is application/json.

This controller:

@RestController
public class Controller {
    @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public List<String> demo() {
	// "world" in Chinese characters: https://en.wiktionary.org/wiki/%E4%B8%96%E7%95%8C
	return List.of("世界");
    }
}

produces the UTF-8 JSON response below. It works without setting the response charset.

["世界"]

However, in the Logbook’s log message, the response body is garbled.

2021-07-21 19:38:59.398 TRACE 11671 --- [nio-8080-exec-1] org.zalando.logbook.Logbook              : {"origin":"local","type":"response","correlation":"ce55b6230e12728d","duration":437,"protocol":"HTTP/1.1","status":200,"headers":{"Connection":["keep-alive"],"Content-Type":["application/json"],"Date":["Wed, 21 Jul 2021 19:38:59 GMT"],"Keep-Alive":["timeout=60"],"Transfer-Encoding":["chunked"]},"body":["ããã«ã¡ã¯"]}

This seems to be because Logbook uses the fallback encoding (ISO-8859-1) even if the document is JSON.

Setting the response character encoding explictly:

@GetMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

fixes the log message.

2021-07-21 19:59:25.295 TRACE 12606 --- [nio-8080-exec-4] org.zalando.logbook.Logbook              : {"origin":"local","type":"response","correlation":"ac7dc50a7cf0fcd0","duration":5,"protocol":"HTTP/1.1","status":200,"headers":{"Connection":["keep-alive"],"Content-Type":["application/json;charset=UTF-8"],"Date":["Wed, 21 Jul 2021 19:59:25 GMT"],"Keep-Alive":["timeout=60"],"Transfer-Encoding":["chunked"]},"body":["世界"]}

But APPLICATION_JSON_UTF8_VALUE is deprecated and should not be used.