title: How to avoid a ServletFilter being called twice?
body: <p>I got a simple Filter which sets an Expiration date and content type for .mp4 and .png files. This together with Frontend is deployed on a Payara Server from which I call the desired media files. What then happens is that the request for a video is sent twice. The second request then throws an Exception because the connection for that ressource is already closed at that point.</p>
  
  <p>The StackTrace looks like this:</p>
  
  <pre><code>  Going into filter! URL: http://localhost:8080/application/video/app.mp4|#]
    Filter img or video!|#]
    Going into filter! URL: http://localhost:8080/application/video/projectcage.mp4|#]
    Filter img or video!|#]
    StandardWrapperValve[default]: Servlet.service() for servlet default threw exception
  java.io.IOException: Connection is closed
      at org.glassfish.grizzly.nio.NIOConnection.assertOpen(NIOConnection.java:441)
      at org.glassfish.grizzly.http.io.OutputBuffer.write(OutputBuffer.java:663)
      at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:338)
      at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:325)
      at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:158)
      at org.apache.catalina.servlets.DefaultServlet.copyRange(DefaultServlet.java:2396)
      [...]
  Caused by: java.io.IOException: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
      at sun.nio.ch.SocketDispatcher.write0(Native Method)
      at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
      at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
      at sun.nio.ch.IOUtil.write(IOUtil.java:51)
      at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
      at org.glassfish.grizzly.nio.transport.TCPNIOUtils.flushByteBuffer(TCPNIOUtils.java:125)
      at org.glassfish.grizzly.nio.transport.TCPNIOUtils.writeCompositeBuffer(TCPNIOUtils.java:64)
      [...]
  </code></pre>
  
  <p>My Code for the Servlet looks like this:</p>
  
  <pre><code>public class ExpiresFilter implements Filter
  {
      private Integer days = -1;
  
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  
          HttpServletRequest req = (HttpServletRequest) request;
          HttpServletResponse rep = (HttpServletResponse) response;
  
          String url = req.getRequestURL().toString();
          System.out.println("Going into filter! URL: "+url);
  
          if ( days &gt; -1  &amp;&amp; URLIsImageOrVideo(url)) {
              System.out.println("Filter img or video!");
  
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(new Date());
              calendar.add(Calendar.DATE, days);
  
              //HTTP header date format: Thu, 01 Dec 1994 16:00:00 GMT
              String expireDate = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz").format(calendar.getTime());
              rep.setHeader("Expires", expireDate );
              String ct = "";
              if(URLIsImage(url))
              {
                  ct = "image/png";
  
              } else if(URLIsVideo(url)) {
                  ct = "video/mp4";
              }
              rep.setHeader("Content-Type", ct);
              rep.setHeader("ContentType", ct);
  
              rep.setStatus(401);
          }
  
          chain.doFilter(request, response);
          return;
      }
  
      @Override
      public void init(FilterConfig filterConfig) {        
          String expiresAfter = filterConfig.getInitParameter("days");
          if (expiresAfter != null) {
              try {
                  days = Integer.parseInt(expiresAfter);
              }
              catch (NumberFormatException nfe) {
                  days = -1;
              }                       
          }
      }
  
      private boolean URLIsImageOrVideo(String url) {
          return URLIsImage(url) || URLIsVideo(url);
      }
  
      private boolean URLIsImage(String url) {
          return url.endsWith(".png");
      }
  
      private boolean URLIsVideo(String url){
          return url.endsWith(".mp4");
      }
  }
  </code></pre>
  
  <pre><code>&lt;web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
       version="3.1"&gt;
      &lt;session-config&gt;
          &lt;session-timeout&gt;
              30
          &lt;/session-timeout&gt;
      &lt;/session-config&gt;
      &lt;filter&gt;
          &lt;description&gt;Set cache expiry for static content&lt;/description&gt;
          &lt;filter-name&gt;ExpiresFilter&lt;/filter-name&gt;
          &lt;filter-class&gt;com.codingforce.pc.ExpiresFilter&lt;/filter-class&gt;
          &lt;init-param&gt;
              &lt;description&gt;Add an Expires Header&lt;/description&gt;
              &lt;param-name&gt;days&lt;/param-name&gt;
              &lt;param-value&gt;30&lt;/param-value&gt;
          &lt;/init-param&gt;
      &lt;/filter&gt;
      &lt;filter-mapping&gt;
          &lt;filter-name&gt;ExpiresFilter&lt;/filter-name&gt;
          &lt;url-pattern&gt;/images/*&lt;/url-pattern&gt;
          &lt;url-pattern&gt;/video/*&lt;/url-pattern&gt;
          &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
      &lt;/filter-mapping&gt;
  &lt;/web-app&gt;
  </code></pre>
  
  <p>HTML (shortened) that loads some of the data which is supposed to go through the filter.</p>
  
  <pre><code>&lt;html lang="de"&gt;
    &lt;head&gt;
      &lt;title&gt;Application&lt;/title&gt;
      &lt;meta charset="utf-8" /&gt;
    &lt;body&gt;    
      &lt;header id="ph"&gt;
          &lt;picture class="himg"&gt;
              &lt;source media="(min-width: 1920px)" srcset="/Projectcage/images/1920.png"&gt;
              &lt;source media="(min-width: 1280px)" srcset="/Projectcage/images/1280.png"&gt;
              &lt;source media="(min-width: 640px)" srcset="/Projectcage/images/640.png"&gt;
              &lt;img src="/Projectcage/images/320.png" alt="Default"&gt;
          &lt;/picture&gt;
  
      &lt;/header&gt;
          &lt;section&gt;
              &lt;div id="midcontainer"&gt;
  
                  &lt;video width="700" height="400" controls&gt;
                      &lt;source src="/Projectcage/video/application.mp4" type="video/mp4"&gt;
                      Video vom Browser nicht unterst&amp;uuml;zt
                  &lt;/video&gt;
              &lt;/div&gt;
          &lt;/section&gt;
      &lt;/div&gt;
  
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Any help is appreciated!</p>