Steps:

  • Created a simple Springboot 2.4.4 application with with War packaging with Spring Web dependency.
  • Added a simple index.html page in the src/main/resource/static/index.html.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
</head>
<body>
    <h1>Encoding should be UTF-8</h1>
</body>
</html>
  • Built the .war file with bootWar - say example.war
  • Deployed the war to external Tomcat 9.x by dropping the .war file to webapps folder of Tomcat (running at localhost:8090)
  • In the browser access the application using the following URL:

http:// localhost:8090/example

NOTE This internally gets forwarded to index.html by Springboot.

The returned Content-Type response header is set to:

Content-Type: text/html;charset=ISO-8859-1

NOTE Debugging shows that the Tomcat code injects this charset based on a Locale-based map because the response from the application did not have the charset specified.

  • Now access the application using the following URL:

http:// localhost:8090/example/index.html

The returned Content-Type response header is set to:

Content-Type: text/html

NOTE: The charset=ISO-8859-1 is now missing.

  • Now run the same app as a Springboot standalone app with embedded Tomcat.

  • In the browser access the application using the following URL:

http:// localhost:8080/

The returned Content-Type response header is set to:

Content-Type: text/html;charset=UTF-8

  • Now access the application using the following URL:

http:// localhost:8080/index.html

The returned Content-Type response header is set to:

Content-Type: text/html

NOTE: The charset=UTF-8 is now missing.

Expected behavior:

The Content-Type header value should be consistent in all 4 cases - preferably with charset=UTF-8

Comment From: sandipchitale

I think the above maybe the cause of issues with d3 library not working in some cases when used with Spring: https://github.com/d3/d3/issues/1195 . Sorry it is just my suspicion.

Comment From: sandipchitale

What is the resolution of this issue?

Comment From: philwebb

@rajanjha786 was there a specific reason you thought this issue should be closed?

Comment From: sandipchitale

If it helps the external Tomcat's behavior of injection of charset may be related to

getCharacterEncoding()

specs in section SRV.15.2.22.1 Methods of Servlet 2.5 spec

Comment From: wilkinsona

The behaviour, in the embedded case at least, is due to some differences in Spring MVC's behaviour.

When a request is made to /, it's dispatched to WelcomePageHandlerMapping which uses a forward view (forward:index.html) to forward the request to the static index.html file. As part of rendering this view, DispatcherServlet sets the locale of the response which, in turn, causes its character encoding to be set.

When a request is made to /index.html, it's dispatched to ResourceHttpRequestHandler and no view rendering is performed. This lack of view rendering means that the response's locale is never set and, therefore, that its character encoding is never set either.

This looks like it may be a Framework issue to me.

Comment From: imanhn

Just to double check,

are you sure you have saved your static html file with UTF8 encoding? Cause if your locale is iso8859-1 and you have saved the file with that encoding, the meta tag does not change it to UTF8.

Comment From: sandipchitale

@imanhn I will have to check that, but most likely the file was saved in UTF-8. In any case this issue is about the chartset value in Content-Type response header.

Comment From: sandipchitale

Any updates?

Comment From: sandipchitale

Any updates?

Comment From: SentretC

Seems that it results from the default locale-encoding-mapping setting of Tomcat. The embedded Tomcat that Spring Boot creates has this setting overridden to use UTF-8 instead.

You can add the following to your web.xml file (inside the web-app element) to achieve the same effect. I don't know whether this can be done programmatically.

<locale-encoding-mapping-list>
    <locale-encoding-mapping>
        <locale>en</locale>
        <encoding>UTF-8</encoding>
    </locale-encoding-mapping>
    <locale-encoding-mapping>
        <locale>fr</locale>
        <encoding>UTF-8</encoding>
    </locale-encoding-mapping>
    <locale-encoding-mapping>
        <locale>ja</locale>
        <encoding>UTF-8</encoding>
    </locale-encoding-mapping>
</locale-encoding-mapping-list>

The application property server.servlet.encoding.force-response can be used to force response encoding, however setting it to true (while leaving server.servlet.encoding.charset to default) results in ";charset=UTF-8" being added even for images, while server.servlet.encoding.mapping.* works for embedded containers only

Comment From: SentretC

Even though it's not a bug of Spring, I don't think a lot of people want to rely on their container to map between locale and encoding. Maybe it's better to provide an option to simply set encoding explicitly along with locale, and have Spring Boot enable it by default? (than the current behavior which is to reset specific mappings when configuring an embedded container)

Comment From: jhoeller

Since there is nothing we can do about this at the core Spring Framework level, I'm closing this issue. For any concrete improvements in Spring Boot, please create a dedicated enhancement request there.