-
Enhancement
-
Resolution: Cannot Reproduce
-
Minor
-
None
-
2.0.11.Final
-
None
Undertow pollutes logs with ERROR messages when client (browser, etc) closes connection while receiving data from an application behind ProxyHandler (load balancer in our case). Expected error message should be at most DEBUG in this scenario.
Example program:
import io.undertow.Handlers; import io.undertow.Undertow; import io.undertow.server.handlers.proxy.LoadBalancingProxyClient; import io.undertow.servlet.Servlets; import io.undertow.servlet.api.DeploymentInfo; import io.undertow.servlet.api.DeploymentManager; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; public class App { public static void main(String[] args) throws ServletException { // Application DeploymentInfo servletBuilder = Servlets.deployment() .setClassLoader(App.class.getClassLoader()) .setContextPath("/") .setDeploymentName("test.war") .addServlets(Servlets.servlet("test", RequestPrinter.class).addMapping("/*")); DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder); manager.deploy(); Undertow applicationServer = Undertow.builder() .addHttpListener(8080, "localhost") .setHandler(manager.start()) .build(); applicationServer.start(); // Proxy LoadBalancingProxyClient proxyClient = new LoadBalancingProxyClient(); proxyClient.addHost(URI.create("http://localhost:8080")); Undertow loadBalancer = Undertow.builder() .addHttpListener(8180, "localhost") .setHandler(Handlers.proxyHandler(proxyClient)) .build(); loadBalancer.start(); try { URL url = new URL("http://localhost:8180/"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream inputStream = urlConnection.getInputStream(); // read a small part of the response and exit byte[] buffer = new byte[10]; inputStream.read(buffer, 0, 10); System.out.println("Done reading"); } catch (Exception e) { e.printStackTrace(); } } public static class RequestPrinter extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { // Write lots of data ServletOutputStream outputStream = resp.getOutputStream(); for (int i = 0; i < 100000; i++) { outputStream.println("ResponseLine#" + i); } } } }
Output:
Aug 13, 2018 11:17:57 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.3.8.Final
Aug 13, 2018 11:17:57 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.8.Final
Done reading
Aug 13, 2018 11:17:58 AM io.undertow.server.handlers.proxy.ProxyHandler handleFailure
ERROR: UT005028: Proxy request to / failed
java.nio.channels.ClosedChannelException
at io.undertow.client.http.HttpClientConnection$5.handleEvent(HttpClientConnection.java:192)
at io.undertow.client.http.HttpClientConnection$5.handleEvent(HttpClientConnection.java:171)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.StreamConnection.invokeCloseListener(StreamConnection.java:80)
at org.xnio.Connection.close(Connection.java:142)
at org.xnio.IoUtils.safeClose(IoUtils.java:134)
at io.undertow.util.ConnectionUtils.doDrain(ConnectionUtils.java:130)
at io.undertow.util.ConnectionUtils.cleanClose(ConnectionUtils.java:74)
at io.undertow.client.http.HttpClientConnection.close(HttpClientConnection.java:472)
at org.xnio.IoUtils.safeClose(IoUtils.java:134)
at io.undertow.server.handlers.proxy.ProxyHandler$IoExceptionHandler.handleException(ProxyHandler.java:790)
at org.xnio.ChannelListeners.invokeChannelExceptionHandler(ChannelListeners.java:126)
at io.undertow.util.Transfer$TransferListener.handleEvent(Transfer.java:193)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at io.undertow.channels.DetachableStreamSinkChannel$SetterDelegatingListener.handleEvent(DetachableStreamSinkChannel.java:285)
at io.undertow.channels.DetachableStreamSinkChannel$SetterDelegatingListener.handleEvent(DetachableStreamSinkChannel.java:272)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.WriteReadyHandler$ChannelListenerHandler.writeReady(WriteReadyHandler.java:65)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:93)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)