From b6fef04761cd64daa1e963bbffb938c9395739a5 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Feb 2016 14:43:12 -0700 Subject: [PATCH] Preserve upstream character encoding. Only default to UTF-8 if not set. fixes gh-530 --- .../zuul/filters/post/SendResponseFilter.java | 6 +- .../filters/post/SendResponseFilterTests.java | 102 ++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilterTests.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java index e89c98e4..4b616820 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java @@ -92,13 +92,15 @@ public class SendResponseFilter extends ZuulFilter { return; } HttpServletResponse servletResponse = context.getResponse(); - servletResponse.setCharacterEncoding("UTF-8"); + if (servletResponse.getCharacterEncoding() == null) { // only set if not set + servletResponse.setCharacterEncoding("UTF-8"); + } OutputStream outStream = servletResponse.getOutputStream(); InputStream is = null; try { if (RequestContext.getCurrentContext().getResponseBody() != null) { String body = RequestContext.getCurrentContext().getResponseBody(); - writeResponse(new ByteArrayInputStream(body.getBytes()), outStream); + writeResponse(new ByteArrayInputStream(body.getBytes(servletResponse.getCharacterEncoding())), outStream); return; } boolean isGzipRequested = false; diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilterTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilterTests.java new file mode 100644 index 00000000..5f9f6185 --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilterTests.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.zuul.filters.post; + +import java.io.ByteArrayInputStream; +import javax.servlet.http.HttpServletRequest; + +import com.netflix.zuul.context.RequestContext; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.web.util.WebUtils; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * @author Spencer Gibb + */ +public class SendResponseFilterTests { + + @Before + public void setTestRequestcontext() { + RequestContext context = new RequestContext(); + RequestContext.testSetCurrentContext(context); + } + + @After + public void reset() { + RequestContext.getCurrentContext().clear(); + } + + @Test + public void runsNormally() throws Exception { + String characterEncoding = null; + String content = "hello"; + runFilter(characterEncoding, content, false); + } + + @Test + public void characterEncodingNotOverridden() throws Exception { + String characterEncoding = "UTF-16"; + String content = "\u00a5"; + runFilter(characterEncoding, content, true); + } + + private void runFilter(String characterEncoding, String content, boolean streamContent) throws Exception { + MockHttpServletResponse response = new MockHttpServletResponse(); + SendResponseFilter filter = createFilter(content, characterEncoding, response, streamContent); + assertTrue("shouldFilter returned false", filter.shouldFilter()); + filter.run(); + String encoding = RequestContext.getCurrentContext().getResponse().getCharacterEncoding(); + String expectedEncoding = characterEncoding != null ? characterEncoding : WebUtils.DEFAULT_CHARACTER_ENCODING; + assertThat("wrong character encoding", encoding, equalTo(expectedEncoding)); + assertThat("wrong content", response.getContentAsString(), equalTo(content)); + } + + private SendResponseFilter createFilter(String content, String characterEncoding, MockHttpServletResponse response, boolean streamContent) throws Exception { + HttpServletRequest request = new MockHttpServletRequest(); + RequestContext context = new RequestContext(); + context.setRequest(request); + context.setResponse(response); + + if (characterEncoding != null) { + response.setCharacterEncoding(characterEncoding); + } + + if (streamContent) { + context.setResponseDataStream(new ByteArrayInputStream(content.getBytes(characterEncoding))); + } else { + context.setResponseBody(content); + } + + context.addZuulResponseHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(content.length())); + + context.set("error.status_code", HttpStatus.NOT_FOUND.value()); + RequestContext.testSetCurrentContext(context); + SendResponseFilter filter = new SendResponseFilter(); + return filter; + } + +} \ No newline at end of file