5

I have a Java Servlet that responds to the Twilio API. It appears that Twilio does not support the chunked transfer that my responses are using. How can I avoid using Transfer-Encoding: chunked?

Here is my code:

// response is HttpServletResponse
// xml is a String with XML in it
response.getWriter().write(xml);
response.getWriter().flush();

I am using Jetty as the Servlet container.

Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
Adam
  • 43,763
  • 16
  • 104
  • 144

3 Answers3

7

I believe that Jetty will use chunked responses when it doesn't know the response content length and/or it is using persistent connections. To avoid chunking you either need to set the response content length or to avoid persistent connections by setting "Connection":"close" header on the response.

cmbaxter
  • 35,283
  • 4
  • 86
  • 95
  • 2
    Beat me to it. @Adam, if my code works, please accept cmbaxter answer. – Anthony Accioly May 13 '13 at 23:58
  • 3
    @AnthonyAccioly, now _that_ is classy SO etiquette – Jason Sperske May 14 '13 at 00:00
  • 2
    @AnthonyAccioly I will up-vote cmbaxter's answer. But, I was really looking for a code sample that showed what content length to set, so your answer is better despite the fact that both are correct, therefore I will accept yours. – Adam May 28 '13 at 20:26
  • In my case `Connection: close` suppresses chunking, but then Jersey isn't supplying `Content-Length`, even though my `MessageBodyWriter` returns a non-negative `getSize`. I can set it myself, but then if the response is gzip-encoded, my `Content-Length` will be wrong and Jersey removes it. – Daniel Lubarov Mar 14 '16 at 20:29
6

Try setting the Content-length before writing to the stream. Don't forget to calculate the amount of bytes according to the correct encoding, e.g.:

final byte[] content = xml.getBytes("UTF-8");
response.setContentLength(content.length);
response.setContentType("text/xml"); // or "text/xml; charset=UTF-8"
response.setCharacterEncoding("UTF-8");

final OutputStream out = response.getOutputStream();
out.write(content);
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
  • 1
    `setCharacterEncoding` is probably not necessary since you are writing raw bytes. content type should include encoding: "text/xml; charset=UTF-8". – ZhongYu May 14 '13 at 00:34
  • Thanks @zhong.j.yu, updated the answer with your suggestion... User can either set the charset directly with the MIME type or use [setCharacterEncoding](http://docs.oracle.com/javaee/6/api/javax/servlet/ServletResponse.html#setCharacterEncoding(java.lang.String)) which will override the Content-type header. – Anthony Accioly May 14 '13 at 02:08
1

The container will decide itself to use Content-Length or Transfer-Encoding basing on the size of data to be written by using Writer or outputStream. If the size of the data is larger than the HttpServletResponse.getBufferSize(), then the response will be trunked. If not, Content-Length will be used.

In your case, just remove the 2nd flushing code will solve your problem.

Robert
  • 5,278
  • 43
  • 65
  • 115
Popeye
  • 2,002
  • 20
  • 14