From 57b84458ae8a3035019a3381e2be06c51d713473 Mon Sep 17 00:00:00 2001 From: Xavier Coulon Date: Mon, 12 Aug 2013 15:50:38 +0200 Subject: [PATCH] JBIDE-15317 - LiveReload script injection corrupted html encoding Using Charset configured in Eclipse when reading local files. Fallback to UTF-8 if charset is unknown Fixed the "content-length" response header value Also, the returned content is encoded with the charset provided in the request's "accept" header. --- .../JBossLiveReloadCoreActivator.java | 3 + .../server/jetty/LiveReloadProxyServer.java | 8 +- .../jetty/LiveReloadScriptFileServlet.java | 29 ++++-- .../LiveReloadScriptInjectionFilter.java | 25 +++-- .../server/jetty/LiveReloadServer.java | 10 +- .../server/jetty/WorkspaceFileServlet.java | 15 ++- .../wst/LiveReloadLaunchConfiguration.java | 1 + .../server/wst/LiveReloadServerBehaviour.java | 1 - .../core/internal/util/HttpUtils.java | 36 ++++++- ...LiveReloadServerConfigurationMessages.java | 2 +- .../org.eclipse.core.resources.prefs | 3 + .../WebContent/chinese.html | 9 ++ .../src/chinese.html | 9 ++ .../jetty/LiveReloadServerTestCase.java | 98 +++++++++++++++++-- .../internal/util/HttpUtilsTestCase.java | 31 ++++++ .../util/ScriptInjectionUtilsTestCase.java | 19 +++- .../test/previewserver/PreviewServer.java | 13 ++- 17 files changed, 268 insertions(+), 44 deletions(-) create mode 100644 tests/org.jboss.tools.livereload.test/.settings/org.eclipse.core.resources.prefs create mode 100644 tests/org.jboss.tools.livereload.test/projects/sample-static-site/WebContent/chinese.html create mode 100644 tests/org.jboss.tools.livereload.test/src/chinese.html diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/JBossLiveReloadCoreActivator.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/JBossLiveReloadCoreActivator.java index 494273c..a997154 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/JBossLiveReloadCoreActivator.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/JBossLiveReloadCoreActivator.java @@ -68,6 +68,9 @@ public static JBossLiveReloadCoreActivator getDefault() { public InputStream getResourceContent(String path) throws IOException { final URL resource = getBundle().getResource(path); + if(resource == null) { + return null; + } return resource.openStream(); } } diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadProxyServer.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadProxyServer.java index a8a4e1a..34a3f03 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadProxyServer.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadProxyServer.java @@ -36,8 +36,12 @@ public class LiveReloadProxyServer extends Server { /** * Constructor * - * @param config - * the LiveReload configuration to use. + * @param proxyPort + * @param targetHost + * @param targetPort + * @param liveReloadPort + * @param allowRemoteConnections + * @param enableScriptInjection * @throws UnknownHostException */ public LiveReloadProxyServer(final int proxyPort, final String targetHost, final int targetPort, final int liveReloadPort, final boolean allowRemoteConnections, diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptFileServlet.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptFileServlet.java index 31b8577..2193f25 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptFileServlet.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptFileServlet.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.io.InputStream; +import java.nio.charset.Charset; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -21,6 +22,7 @@ import org.apache.commons.io.IOUtils; import org.jboss.tools.livereload.core.internal.JBossLiveReloadCoreActivator; +import org.jboss.tools.livereload.core.internal.util.HttpUtils; import org.jboss.tools.livereload.core.internal.util.Logger; /** @@ -33,13 +35,26 @@ public class LiveReloadScriptFileServlet extends HttpServlet { private static final long serialVersionUID = 163695311668462503L; @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - Logger.info("Serving embedded /livereload.js"); - HttpServletResponse httpServletResponse = (HttpServletResponse) response; - final InputStream scriptContent = JBossLiveReloadCoreActivator.getDefault().getResourceContent("/script/livereload.js"); - httpServletResponse.getOutputStream().write(IOUtils.toByteArray(scriptContent)); - httpServletResponse.setStatus(200); - httpServletResponse.setContentType("text/javascript"); + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + InputStream scriptContent = null; + try { + Logger.info("Serving embedded /livereload.js"); + final HttpServletResponse httpServletResponse = (HttpServletResponse) response; + scriptContent = JBossLiveReloadCoreActivator.getDefault().getResourceContent("/script/livereload.js"); + if(scriptContent == null) { + httpServletResponse.setStatus(404); + } else { + final Charset charset = HttpUtils.getContentCharSet(request.getHeader("accept"), "UTF-8"); + httpServletResponse.setContentType("text/javascript; charset=" + charset.name()); + // output content will use the charset defined in the content type above. + httpServletResponse.getOutputStream().write(IOUtils.toByteArray(scriptContent)); + httpServletResponse.setStatus(200); + } + } finally { + if(scriptContent != null) { + scriptContent.close(); + } + } } } diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptInjectionFilter.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptInjectionFilter.java index bd2d07c..071d2a2 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptInjectionFilter.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadScriptInjectionFilter.java @@ -14,6 +14,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -122,7 +125,8 @@ private void terminate(final HttpServletRequest httpRequest, returnedContentType); final InputStream responseStream = responseWrapper.getResponseAsStream(); final char[] modifiedResponseContent = ScriptInjectionUtils.injectContent(responseStream, scriptContent); - responseWrapper.terminate(modifiedResponseContent); + final Charset charset = HttpUtils.getContentCharSet(returnedContentType, "UTF-8"); + responseWrapper.terminate(modifiedResponseContent, charset); } // finalize the responseWrapper by copying the wrapper's // outputstream into the response outputstream that will be returned @@ -184,7 +188,8 @@ public ServletOutputStream getOutputStream() throws IOException { public InputStream getResponseAsStream() throws IOException { final byte[] byteArray = responseOutputStream.toByteArray(); responseOutputStream.close(); - return IOUtils.toInputStream(new String(byteArray), getCharacterEncoding()); + final String characterEncoding = getCharacterEncoding(); + return IOUtils.toInputStream(new String(byteArray, characterEncoding), characterEncoding); } /** @@ -192,16 +197,20 @@ public InputStream getResponseAsStream() throws IOException { * and adjust the 'content-length' response header as well (in case * content modification occurred in the response entity). * + * @param responseContent the content of the response. + * @param encoding the ecnoding to use when writing the char[] content into the response's outputstream. + * * @throws IOException */ - public void terminate(final char[] responseContent) throws IOException { - ((HttpServletResponse) getResponse()).setHeader("Content-length", Integer.toString(responseContent.length)); - IOUtils.write(responseContent, getResponse().getOutputStream()); - // getResponse().getOutputStream().flush(); - // getResponse().getOutputStream().close(); + public void terminate(final char[] responseContent, final Charset charset) throws IOException { + // see http://mark.koli.ch/2009/09/remember-kids-an-http-content-length-is-the-number-of-bytes-not-the-number-of-characters.html + final CharBuffer charBuffer = CharBuffer.wrap(responseContent); + final ByteBuffer byteBuffer = charset.encode(charBuffer); + ((HttpServletResponse) getResponse()).setHeader("Content-length", Integer.toString(byteBuffer.array().length)); + IOUtils.write(responseContent, getResponse().getOutputStream(), charset.name()); responseOutputStream.close(); } - + /** * Writes the content of the internal and temporary * {@link ByteArrayOutputStream} into the wrapped diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadServer.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadServer.java index 3b32b7f..e10457c 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadServer.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/LiveReloadServer.java @@ -11,7 +11,6 @@ package org.jboss.tools.livereload.core.internal.server.jetty; -import java.net.UnknownHostException; import java.util.EventObject; import org.eclipse.jetty.server.Server; @@ -49,10 +48,11 @@ public class LiveReloadServer extends Server implements Subscriber { /** * Constructor - * - * @param config - * the LiveReload configuration to use. - * @throws UnknownHostException + * @param name the server name (appears in the Servers Views) + * @param websocketPort the websocket port + * @param enableProxyServer flag to enable the proxy server + * @param allowRemoteConnections flag to allow remote connections + * @param enableScriptInjection flag to enable script injection */ public LiveReloadServer(final String name, final int websocketPort, final boolean enableProxyServer, final boolean allowRemoteConnections, final boolean enableScriptInjection) { diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/WorkspaceFileServlet.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/WorkspaceFileServlet.java index 4d62493..ea1552d 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/WorkspaceFileServlet.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/jetty/WorkspaceFileServlet.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.net.URLConnection; +import java.nio.charset.Charset; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -23,6 +24,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; +import org.jboss.tools.livereload.core.internal.util.HttpUtils; import org.jboss.tools.livereload.core.internal.util.Logger; import org.jboss.tools.livereload.core.internal.util.ResourceUtils; @@ -36,7 +38,7 @@ public class WorkspaceFileServlet extends HttpServlet { private static final long serialVersionUID = 163695311668462503L; @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { final HttpServletResponse httpServletResponse = (HttpServletResponse) response; final String requestURI = request.getRequestURI(); Logger.info("Serving " + requestURI); @@ -46,10 +48,17 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t final IResource resource = ResourceUtils.retrieveResource(requestURI); if (resource != null && resource.getType() == IResource.FILE) { try { - final byte[] scriptContent = IOUtils.toByteArray(((IFile) resource).getContents()); + final IFile workspaceFile = (IFile) resource; + final byte[] scriptContent = IOUtils.toByteArray(workspaceFile.getContents()); httpServletResponse.getOutputStream().write(scriptContent); httpServletResponse.setStatus(200); - httpServletResponse.setContentType(URLConnection.guessContentTypeFromName(resource.getName())); + + final Charset charset = HttpUtils.getContentCharSet(request.getHeader("accept"), workspaceFile.getCharset()); + String guessedContentType = URLConnection.guessContentTypeFromName(resource.getName()); + if(guessedContentType != null && !guessedContentType.contains("charset")) { + guessedContentType = guessedContentType.concat("; charset=").concat(charset.name()); + } + httpServletResponse.setContentType(guessedContentType); // httpServletResponse.setContentType("text/javascript"); } catch (CoreException e) { Logger.error("Error occurred while returning content at location: " + requestURI, e); diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadLaunchConfiguration.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadLaunchConfiguration.java index 25784fc..f8f6dd6 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadLaunchConfiguration.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadLaunchConfiguration.java @@ -40,6 +40,7 @@ public class LiveReloadLaunchConfiguration implements ILaunchConfigurationDelega public static final int DEFAULT_WEBSOCKET_PORT = 35729; + @Override public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadServerBehaviour.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadServerBehaviour.java index 64685fb..cd4651a 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadServerBehaviour.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/server/wst/LiveReloadServerBehaviour.java @@ -125,7 +125,6 @@ public void startServer() throws CoreException { final IServer server = getServer(); // retrieve the websocket port, use the default value if it was missing websocketPort = server.getAttribute(LiveReloadLaunchConfiguration.WEBSOCKET_PORT, LiveReloadLaunchConfiguration.DEFAULT_WEBSOCKET_PORT); - // fix the new default behaviour: proxy is now always enabled if(!isProxyEnabled()) { setProxyEnabled(true); diff --git a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/util/HttpUtils.java b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/util/HttpUtils.java index e1ad3ab..fd61350 100644 --- a/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/util/HttpUtils.java +++ b/plugins/org.jboss.tools.livereload.core/src/org/jboss/tools/livereload/core/internal/util/HttpUtils.java @@ -11,6 +11,8 @@ package org.jboss.tools.livereload.core.internal.util; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; import java.util.StringTokenizer; /** @@ -45,7 +47,7 @@ public static boolean isHtmlContentType(final String acceptedContentTypes) { if (acceptedContentTypes == null) { return false; } - // first, let's remove everything after the coma character + // first, let's remove everything behind the comma character int location = acceptedContentTypes.indexOf(";"); final String contentTypes = (location != -1) ? acceptedContentTypes.substring(0, location):acceptedContentTypes; // now, let's analyze each type @@ -59,5 +61,37 @@ public static boolean isHtmlContentType(final String acceptedContentTypes) { } return false; } + + /** + * Returns the {@link Charset} from the given content-type. + * + * @param contentType + * the given content type that may contain some ";charset=...". + * @param defaultCharsetName + * the name of the default charset to return in case when the given + * contentType would be null or would not contain any specific + * charset. If this name cannot be resolved into a valid charset, then "UTF-8" is used. + * @return the value of the "charset" token in the given contentType, or + * the given defaultCharsetName, or "UTF-8" as a last resort. + */ + public static Charset getContentCharSet(final String contentType, final String defaultCharsetName) { + if(contentType != null) { + final StringTokenizer stk = new StringTokenizer(contentType, ";"); + while(stk.hasMoreTokens()) { + final String token = stk.nextToken().toLowerCase().replace(" ", ""); + if(token.startsWith("charset=")) { + final StringTokenizer tokenSplitter = new StringTokenizer(token, "="); + tokenSplitter.nextToken(); // skip the 'charset' part as we already know it + final String value = tokenSplitter.hasMoreTokens()? tokenSplitter.nextToken() : null; + return Charset.forName(value.toUpperCase()); + } + } + } + try { + return Charset.forName(defaultCharsetName); + } catch(UnsupportedCharsetException e) { + return Charset.forName("UTF-8"); + } + } } diff --git a/plugins/org.jboss.tools.livereload.ui/src/org/jboss/tools/livereload/ui/internal/configuration/LiveReloadServerConfigurationMessages.java b/plugins/org.jboss.tools.livereload.ui/src/org/jboss/tools/livereload/ui/internal/configuration/LiveReloadServerConfigurationMessages.java index aada64c..f0997fe 100644 --- a/plugins/org.jboss.tools.livereload.ui/src/org/jboss/tools/livereload/ui/internal/configuration/LiveReloadServerConfigurationMessages.java +++ b/plugins/org.jboss.tools.livereload.ui/src/org/jboss/tools/livereload/ui/internal/configuration/LiveReloadServerConfigurationMessages.java @@ -19,7 +19,7 @@ private LiveReloadServerConfigurationMessages() { public static String WEBSOCKET_SERVER_PORT_LABEL; public static String WEBSOCKET_SERVER_PORT_COMMAND; - + public static String PROXY_SERVER_CONFIGURATION_TITLE; public static String PROXY_CONFIGURATION_DESCRIPTION; diff --git a/tests/org.jboss.tools.livereload.test/.settings/org.eclipse.core.resources.prefs b/tests/org.jboss.tools.livereload.test/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..014076d --- /dev/null +++ b/tests/org.jboss.tools.livereload.test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//projects/sample-static-site/WebContent/chinese.html=UTF-8 +encoding//src/org/jboss/tools/livereload/internal/server/jetty/LiveReloadServerTestCase.java=UTF-8 diff --git a/tests/org.jboss.tools.livereload.test/projects/sample-static-site/WebContent/chinese.html b/tests/org.jboss.tools.livereload.test/projects/sample-static-site/WebContent/chinese.html new file mode 100644 index 0000000..f05d4d3 --- /dev/null +++ b/tests/org.jboss.tools.livereload.test/projects/sample-static-site/WebContent/chinese.html @@ -0,0 +1,9 @@ + + + + + + + 中文 + + \ No newline at end of file diff --git a/tests/org.jboss.tools.livereload.test/src/chinese.html b/tests/org.jboss.tools.livereload.test/src/chinese.html new file mode 100644 index 0000000..f05d4d3 --- /dev/null +++ b/tests/org.jboss.tools.livereload.test/src/chinese.html @@ -0,0 +1,9 @@ + + + + + + + 中文 + + \ No newline at end of file diff --git a/tests/org.jboss.tools.livereload.test/src/org/jboss/tools/livereload/internal/server/jetty/LiveReloadServerTestCase.java b/tests/org.jboss.tools.livereload.test/src/org/jboss/tools/livereload/internal/server/jetty/LiveReloadServerTestCase.java index 54fd081..f9e60f6 100644 --- a/tests/org.jboss.tools.livereload.test/src/org/jboss/tools/livereload/internal/server/jetty/LiveReloadServerTestCase.java +++ b/tests/org.jboss.tools.livereload.test/src/org/jboss/tools/livereload/internal/server/jetty/LiveReloadServerTestCase.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeoutException; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; @@ -300,7 +301,7 @@ public void shouldNotInjectLiveReloadScriptInHtmlPage() throws Exception { // verification assertThat(status).isEqualTo(HttpStatus.SC_OK); // Read the response body. - String responseBody = new String(method.getResponseBody()); + String responseBody = method.getResponseBodyAsString(); assertThat(responseBody).doesNotContain(scriptContent); } @@ -320,10 +321,61 @@ public void shouldInjectLiveReloadScriptInHtmlPageWithSimpleAcceptedTypes() thro // verification assertThat(status).isEqualTo(HttpStatus.SC_OK); // Read the response body. - String responseBody = new String(method.getResponseBody()); + String responseBody = method.getResponseBodyAsString(); assertThat(responseBody).contains(scriptContent); } + + @Test + // @see https://issues.jboss.org/browse/JBIDE-15317 + public void shouldNotCorruptHtmlContentWhenInjectingScript() throws CoreException, InterruptedException, ExecutionException, TimeoutException, HttpException, IOException { + // pre-condition + createAndLaunchLiveReloadServer(true); + final String scriptContent = new StringBuilder( + "").toString(); + final IResource chineseHtmlFile = project.findMember("WebContent" + File.separator + "chinese.html"); + final String chineseDocumentlocation = "http://localhost:" + liveReloadServerPort + "/" + project.getName() + "/" + + chineseHtmlFile.getLocation().makeRelativeTo(project.getLocation()).toOSString(); + assertThat(chineseHtmlFile).isNotNull(); + // operation + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(chineseDocumentlocation); + method.addRequestHeader("Accept", "text/html"); + int status = client.executeMethod(method); + // verification + assertThat(status).isEqualTo(HttpStatus.SC_OK); + // Read the response body. + String responseBody = method.getResponseBodyAsString(); + assertThat(responseBody).contains(scriptContent); + LOGGER.debug(responseBody); + assertThat(responseBody).doesNotContain("??"); + assertThat(responseBody).contains("中文"); + } + @Test + // @see https://issues.jboss.org/browse/JBIDE-15317 + public void shouldNotCorruptHtmlContentWhenNotInjectingScript() throws CoreException, InterruptedException, ExecutionException, TimeoutException, HttpException, IOException { + // pre-condition + createAndLaunchLiveReloadServer(false); + final IResource chineseHtmlFile = project.findMember("WebContent" + File.separator + "chinese.html"); + final String chineseDocumentlocation = "http://localhost:" + liveReloadServerPort + "/" + project.getName() + "/" + + chineseHtmlFile.getLocation().makeRelativeTo(project.getLocation()).toOSString(); + assertThat(chineseHtmlFile).isNotNull(); + // operation + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(chineseDocumentlocation); + method.addRequestHeader("Accept", "text/html"); + int status = client.executeMethod(method); + // verification + assertThat(status).isEqualTo(HttpStatus.SC_OK); + // Read the response body. + String responseBody = method.getResponseBodyAsString(); + assertThat(responseBody).doesNotContain(""); + assertThat(new String(modifiedContent)).contains(addition + ""); } @Test @@ -43,7 +43,20 @@ public void shouldNotInjectScriptOnHtmlPageFragment() throws IOException { // operation final char[] modifiedContent = ScriptInjectionUtils.injectContent(sourceStream, addition); // verifications - Assertions.assertThat(new String(modifiedContent)).doesNotContain(addition + ""); + assertThat(new String(modifiedContent)).doesNotContain(addition + ""); } + + @Test + public void shouldInjectScriptAtEndOfChineseBody() throws IOException { + // pre-conditions + final InputStream sourceStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("chinese.html"); + final String addition = "