2

I have a handler in a jetty server deployment, which has a reference to the HttpServletResponse object.

I am writing byte content to the Response.getOutputStream() like below:

ServletOutputStream serlvetOutputStream = handlerContext.getResponse().getOutputStream();
...
while(condition) { 
//read chunk from some source into byteBuffer
servletOutputStream.write(byteBuffer, 0, lengthRead);
}

But before I can write write(), I must set the content-length the http client expects in the response:

handlerContext.getResponse().setContentLength((int) length); //or as below
handlerContext.getResponse().addHeader("Content-Length", String.valueOf(length));

Failure to set the length before writing to the outputstream, results in an "Error File size unknown" popup box on the Windows client application. But in some cases, I would not know what would be the length to be written until afterward. I cannot accumulate the entire data to be read beforehand (because it can time-out the client for larger data) so it must be "chunked" i.e read x kilobytes and then write x kilobytes, until condition is false.

My question is - is there any way to dynamically update the content length just before writing? In the loop above, I want to set the content-length as however many bytes were available to write, write() those, and then update it again when it loops around.

If I update the content-length within the loop, I get jetty.server.EoFexception.

PKM
  • 329
  • 4
  • 17
  • 1
    If you are reading the data chunked, and you can't buffer the entire data in Java, then you can't know the actual amount read. Is there any chance you could estimate the content length or could the API from which you are reading provide some estimate? – Tim Biegeleisen Jan 03 '17 at 06:54
  • 1
    As the name suggests, Content-Length is a Header and may be set once only at the beginning of your response. Depending on the origin of your data (file, blob, etc.), see if there's metadata available to you from which you can query the expected length before streaming the content. Otherwise, you may actually have to buffer the entire stream (in memory or on disk), determine its length and then set the header and start the response. Finally, if the content-length is truly impossible to determine up-front, look into updating the client and look into HTTP chunked or streaming protocols. – Arash Motamedi Jan 03 '17 at 06:55
  • 1
    Headers may only be sent before actual content, that's how HTTP works. – Jiri Tousek Jan 03 '17 at 06:56
  • 1
    `Transfer-encoding: chunked` might help you, see http://stackoverflow.com/questions/2395192/http-headers-for-unknown-content-length for .NET example. – Jiri Tousek Jan 03 '17 at 06:59
  • Response to all commenters - [Thanks] it seems I cannot write buffered date since there is no way for me to get size beforehand. This may qualify as separate - but why can't the header be updated in a loop before writing each chunk of data? The http server should (I presume) not begin to pass down the response object until the outputstream has been fully written to (i.e all the chunks have been written in), before sending it down the layers, so the header has still not yet been sent down. Could the Java Reflection let me write the header field dynamically? – PKM Jan 03 '17 at 07:47
  • 2
    @Jiri: This is already automatically done by Servlet API when content length is not set. PKM, if client fails on this, then this is clearly a bug in the client used and not your concern. – BalusC Jan 03 '17 at 07:58

1 Answers1

2

You don't need to set the content length. It will happen automatically. What you have here is an XY problem. You have an undisclosed exception and you think that setting the content length will solve it. However, as you can't set the content length either, you have zero actual evidence for your belief.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • The client is a Windows application and it throws an error if content-length is missing. – PKM Jan 03 '17 at 08:57
  • It throws *what* exception? And where is your evidence that supplying a content-length will fix it? – user207421 Jan 03 '17 at 08:58
  • If I manually set the content-length for a known content size it does not complain. I saw (using Wireshark) that the client has a packet with content-length. Would amend "Exception" on client with an "error" - a pop up box saying "Error Size Unknown". – PKM Jan 03 '17 at 08:59
  • A popup box is not an exception, and it is not thrown. It is a popup box, and it is popped up. Possibly your client is buggy. – user207421 Jan 03 '17 at 09:01
  • If I Response.setHeader("Transfer-Encoding", "chunked"); and the client application still pops up with "Error File size unknown", is that expected behavior? Basically, I do not know for sure if the client subscribes fully to the http API. – PKM Jan 03 '17 at 10:59
  • 1
    It's an error if the client is supposed to support chunked transfer encoding. – user207421 Jan 03 '17 at 14:01