Skip to content

Commit 5ae6a21

Browse files
authored
Use UTF-8 for captured responses if charset is not set explicitly (#39)
In the newest versions of Spring Framework, after a change[1] to align it with the RFC8259[2], the character encoding is no longer set to UTF-8 for responses with `application/json` content-type. This fix makes a `JsonResponseWrapper` use UTF-8 by default, instead of getting charset from the wrapped `Response` instance which could have been not set and so it returns default ISO-8895-1. [1]: spring-projects/spring-framework#22788 [2]: https://tools.ietf.org/html/rfc8259#section-11
1 parent 8dc8d3a commit 5ae6a21

File tree

4 files changed

+26
-12
lines changed

4 files changed

+26
-12
lines changed

filters/src/main/java/ua/net/tokar/json/rainbowrest/HtmlResponseWrapper.java renamed to filters/src/main/java/ua/net/tokar/json/rainbowrest/JsonResponseWrapper.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@
99
import java.io.IOException;
1010
import java.io.OutputStreamWriter;
1111
import java.io.PrintWriter;
12+
import java.nio.charset.StandardCharsets;
1213

13-
class HtmlResponseWrapper extends HttpServletResponseWrapper {
14+
class JsonResponseWrapper extends HttpServletResponseWrapper {
15+
// RFC 8259 (section 11) specifies that 'charset' parameter for media
16+
// type 'application/json' has no effect and JSON text MUST be encoded
17+
// using UTF-8 (section 8.1)
18+
private static final String DEFAULT_CHARSET = StandardCharsets.UTF_8.name();
19+
20+
private String charset = DEFAULT_CHARSET;
1421
private final ByteArrayOutputStream capture;
1522
private ServletOutputStream output;
1623
private PrintWriter writer;
1724

18-
HtmlResponseWrapper(ServletResponse response) {
25+
JsonResponseWrapper(ServletResponse response) {
1926
super((HttpServletResponse)response);
2027
capture = new ByteArrayOutputStream(response.getBufferSize());
2128
}
@@ -84,6 +91,13 @@ public void flushBuffer() throws IOException {
8491
}
8592
}
8693

94+
@Override
95+
public void setCharacterEncoding(String charset) {
96+
// for backward compatibility use non-default charset if set explicitly
97+
super.setCharacterEncoding(charset);
98+
this.charset = charset != null ? charset : DEFAULT_CHARSET;
99+
}
100+
87101
private byte[] getCaptureAsBytes() throws IOException {
88102
if (writer != null) {
89103
writer.close();
@@ -95,6 +109,6 @@ private byte[] getCaptureAsBytes() throws IOException {
95109
}
96110

97111
String getCaptureAsString() throws IOException {
98-
return new String(getCaptureAsBytes(), getCharacterEncoding());
112+
return new String(getCaptureAsBytes(), charset);
99113
}
100114
}

filters/src/main/java/ua/net/tokar/json/rainbowrest/RainbowRestBatchFilter.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,10 @@ protected void doFilterInternal(
123123
return;
124124
}
125125
response.setContentType( "application/json" );
126-
response.getWriter().write(
127-
getBatchResults(
128-
map,
129-
(HttpServletRequest) request
130-
).toString() );
126+
mapper.writeValue(
127+
response.getOutputStream(),
128+
getBatchResults( map, (HttpServletRequest) request )
129+
);
131130
}
132131
}
133132

filters/src/main/java/ua/net/tokar/json/rainbowrest/RainbowRestOncePerRequestFilter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.net.URI;
1515
import java.net.URISyntaxException;
1616
import java.nio.charset.Charset;
17+
import java.nio.charset.StandardCharsets;
1718
import java.util.ArrayList;
1819
import java.util.Collection;
1920
import java.util.Enumeration;
@@ -109,7 +110,7 @@ protected String getResponseViaInternalDispatching(
109110
ServletRequest request,
110111
ServletResponse response
111112
) throws ServletException, IOException {
112-
HtmlResponseWrapper responseWrapper = new HtmlResponseWrapper( response );
113+
JsonResponseWrapper responseWrapper = new JsonResponseWrapper( response );
113114
request.getRequestDispatcher( relativeUrl )
114115
.forward(
115116
new GetHttpServletRequest( (HttpServletRequest) request ),
@@ -138,7 +139,7 @@ protected URI buildUri(
138139
List<NameValuePair> params = new ArrayList<>();
139140
params.addAll( URLEncodedUtils.parse(
140141
new URI( relativeUrl ),
141-
Charset.forName( "UTF-8" )
142+
StandardCharsets.UTF_8
142143
) );
143144
params.addAll( additionalRequestParams );
144145

filters/src/main/java/ua/net/tokar/json/rainbowrest/RainbowRestWebFilter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ protected void doFilterInternal(
124124
return;
125125
}
126126

127-
HtmlResponseWrapper capturingResponseWrapper = new HtmlResponseWrapper( response );
127+
JsonResponseWrapper capturingResponseWrapper = new JsonResponseWrapper( response );
128128
filterChain.doFilter( request, capturingResponseWrapper );
129129

130130
Set<String> includeFields = new HashSet<>();
@@ -159,7 +159,7 @@ protected void doFilterInternal(
159159
filterTree( tree, includeFields, excludeFields );
160160
}
161161

162-
response.getWriter().write( tree.toString() );
162+
mapper.writeValue(response.getOutputStream(), tree);
163163
}
164164

165165
private void processIncludes(

0 commit comments

Comments
 (0)