Repository: olingo-odata2 Updated Branches: refs/heads/master b2b42b1e4 -> 297c39492
[OLINGO-531] Fix: ODataServlet response contains content-length header Signed-off-by: Christian Amend <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/297c3949 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/297c3949 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/297c3949 Branch: refs/heads/master Commit: 297c3949222e50de4a6c266e4a221564ad2d9b08 Parents: b2b42b1 Author: Christian Holzer <[email protected]> Authored: Tue Jan 13 09:31:52 2015 +0100 Committer: Christian Amend <[email protected]> Committed: Tue Jan 13 12:50:58 2015 +0100 ---------------------------------------------------------------------- .../odata2/core/servlet/ODataServlet.java | 17 +++- .../odata2/core/servlet/ODataServletTest.java | 82 ++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/297c3949/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java index 0973f33..e1faeae 100644 --- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java +++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/servlet/ODataServlet.java @@ -245,16 +245,31 @@ public class ODataServlet extends HttpServlet { if (entity != null) { ServletOutputStream out = resp.getOutputStream(); int curByte; + int contentLength = 0; + if (entity instanceof InputStream) { while ((curByte = ((InputStream) entity).read()) != -1) { + contentLength++; out.write((char) curByte); } ((InputStream) entity).close(); } else if (entity instanceof String) { String body = (String) entity; - out.write(body.getBytes("utf-8")); + final byte[] entityBytes = body.getBytes("utf-8"); + out.write(entityBytes); + contentLength = entityBytes.length; + } + + if (response.getHeader(HttpHeaders.CONTENT_LENGTH) != null) { + // Override content length + try { + contentLength = Integer.parseInt(response.getHeader(HttpHeaders.CONTENT_LENGTH)); + } catch (NumberFormatException e) { + // Ignore + } } + resp.setContentLength(contentLength); out.flush(); out.close(); } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/297c3949/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java ---------------------------------------------------------------------- diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java index 2f877d2..883ab96 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/servlet/ODataServletTest.java @@ -18,16 +18,22 @@ ******************************************************************************/ package org.apache.olingo.odata2.core.servlet; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.lang.reflect.Field; +import java.lang.reflect.Method; import javax.servlet.GenericServlet; import javax.servlet.ServletConfig; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.olingo.odata2.api.ODataServiceFactory; import org.apache.olingo.odata2.api.commons.HttpHeaders; import org.apache.olingo.odata2.api.commons.HttpStatusCodes; +import org.apache.olingo.odata2.api.processor.ODataResponse; +import org.apache.olingo.odata2.core.ODataResponseImpl; import org.apache.olingo.odata2.core.rest.ODataServiceFactoryImpl; import org.junit.Test; import org.mockito.Mockito; @@ -91,6 +97,82 @@ public class ODataServletTest { Mockito.verify(respMock).setHeader(HttpHeaders.LOCATION, "/"); } + @Test + public void contentLengthCalculatedString() throws Exception { + final Method createResponse = + ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class); + createResponse.setAccessible(true); + + final ODataServlet servlet = new ODataServlet(); + final String content = "Test\r\n"; + final ODataResponse response = ODataResponseImpl.status(HttpStatusCodes.OK).entity(content).build(); + prepareResponseMockToWrite(respMock); + prepareServlet(servlet); + + createResponse.invoke(servlet, respMock, response); + Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length); + } + + @Test + public void contentLengthCalculatedStream() throws Exception { + final Method createResponse = + ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class); + createResponse.setAccessible(true); + + final ODataServlet servlet = new ODataServlet(); + final String content = "Test\r\n"; + + final ODataResponse response = + ODataResponseImpl.status(HttpStatusCodes.OK).entity(new ByteArrayInputStream(content.getBytes("utf-8"))) + .build(); + prepareResponseMockToWrite(respMock); + prepareServlet(servlet); + + createResponse.invoke(servlet, respMock, response); + Mockito.verify(respMock).setContentLength(content.getBytes("utf-8").length); + } + + @Test + public void contentLengthHeader() throws Exception { + final Method createResponse = + ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class); + createResponse.setAccessible(true); + final ODataServlet servlet = new ODataServlet(); + final ODataResponse response = + ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "15").entity("").build(); + prepareResponseMockToWrite(respMock); + prepareServlet(servlet); + + createResponse.invoke(servlet, respMock, response); + + Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "15"); + Mockito.verify(respMock).setContentLength(15); + } + + @Test + public void contentLengthHeaderInvalid() throws Exception { + final Method createResponse = + ODataServlet.class.getDeclaredMethod("createResponse", HttpServletResponse.class, ODataResponse.class); + createResponse.setAccessible(true); + final ODataServlet servlet = new ODataServlet(); + final ODataResponse response = + ODataResponseImpl.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_LENGTH, "ab").entity("Test").build(); + prepareResponseMockToWrite(respMock); + prepareServlet(servlet); + + createResponse.invoke(servlet, respMock, response); + + Mockito.verify(respMock).setHeader(HttpHeaders.CONTENT_LENGTH, "ab"); + Mockito.verify(respMock).setContentLength(4); // ||"Test"|| = 4 + } + + private void prepareResponseMockToWrite(final HttpServletResponse response) throws IOException { + Mockito.when(response.getOutputStream()).thenReturn(new ServletOutputStream() { + @Override + public void write(int b) throws IOException {} + }); + } + private void prepareRequest(final HttpServletRequest req, final String contextPath, final String servletPath) { Mockito.when(req.getMethod()).thenReturn("GET"); Mockito.when(req.getContextPath()).thenReturn(contextPath);
