How to prevent net::ERR_INCOMPLETE_CHUNKED_ENCODING when using HTML5 Server events and Java Servlets?

a 夏天 提交于 2019-12-22 03:38:20

问题


i just started to play around with Server Events and i run into a chrome error message i would like to understand. i searched the web real quick but didn't find an explanation so i guess i may do something terribly wrong.

On the server side i have a simple servlet that accepts requests and creates a dummy event creator task:

private Executor executor = Executors.newSingleThreadExecutor();

public void doGet(final HttpServletRequest request, final HttpServletResponse response)
{
  final AsyncContext asynCtx = request.startAsync(request, response);

  response.setHeader("Cache-Control", "no-cache");
  response.setContentType("text/event-stream");
  response.setCharacterEncoding("utf-8");

  executor.execute(() -> {
    boolean run = true;
    try
    {
      while (run)
      {
        final ServletResponse resp = asynCtx.getResponse();
        run = resp != null;

        if (resp != null)
        {
          System.out.println("pushing a server event.");
          final PrintWriter writer = asynCtx.getResponse().getWriter();
          writer.println("data: {time: " + System.currentTimeMillis() + "}\n");
          writer.flush();
        }
        else
        {
          System.out.println("stopping beeper, no response object available anymore.");
          break; // do not run anymore, we got no response
        }

        Thread.sleep(2000);
      }
    }
    catch (final Exception e)
    {
      e.printStackTrace();
    }
  });

}

on the client i simply:

$(document).ready(function ()
{

   var source = new EventSource("/events");
   source.onmessage = function (event)
   {
     console.log("received event: " + JSON.stringify(event));
     document.getElementById("eventContainer").innerHTML += event.data + "<br/>";
   };

   console.log("start to receive events...")
});

when i load the HTML file it works fine, events are received and written to the console. But after 30 seconds i get an error message:

GET [HttpOfLocalhost]/events net::ERR_INCOMPLETE_CHUNKED_ENCODING

why?

the request than gets killed and a new one is started immediately so it doesn't kill the application but error messages on the console aren't nice.

screenshot of my developer console:

request/resposne details:

timing, this shows that it always occurs after 30 seconds:

Thanks!


回答1:


Ok, so i couldn't stand still and look closer whats happening.

The AsyncContext object has a setTimeout(...) method. Per default in my version of tomcat (Tomcat embedded 8) the value is set to 30,000 ms (30 seconds). That's exactly the duration after i got the net::ERR_INCOMPLETE_CHUNKED_ENCODING error in my chrome console.

i checked using:

System.out.println("Current Timeout is: " + asynCtx.getTimeout() + " ms");

which showed:

Current Timeout is: 30000 ms

so to avoid the net:ERR message someone could set the timeout to 0. But than the event thread keeps running forever (unfortunately). Another solution, which i used, is to add a AsyncListener to the AsyncContext and call the complete() method inside the onTimeout() method.

from the API doc of the complete() method:

Completes the asynchronous operation that was started on the request that was used to initialze this AsyncContext, closing the response that was used to initialize this AsyncContext. Any listeners of type AsyncListener that were registered with the ServletRequest for which this AsyncContext was created will be invoked at their onComplete method.

the source code of my listener:

asynCtx.addListener(new AsyncListener()
{
  @Override
  public void onComplete(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onComplete(...)");
  }

  @Override
  public void onTimeout(AsyncEvent asyncEvent) throws IOException
  {
    // this will close the request and the context gracefully
    // and the net:ERR is gone.
    asyncEvent.getAsyncContext().complete();
    System.out.println("onTimeout(...)");
  }

  @Override
  public void onError(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onError(...)");
  }

  @Override
  public void onStartAsync(AsyncEvent asyncEvent) throws IOException
  {
    System.out.println("onStart(...)");
  }
});

so yes, it was due lack of knowledge. i hope this is helpful for someone.




回答2:


You can send small "no operation" (noop) chunks to keep the connection alive every 10 seconds or so.



来源:https://stackoverflow.com/questions/26863972/how-to-prevent-neterr-incomplete-chunked-encoding-when-using-html5-server-even

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!