Package rabbit.proxy

Source Code of rabbit.proxy.ConditionalChecker

package rabbit.proxy;

import java.util.Date;
import java.util.List;
import rabbit.cache.CacheEntry;
import rabbit.http.HttpDateParser;
import rabbit.http.HttpHeader;
import rabbit.util.Logger;

/** A class used to check for conditional requests.
*
* @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a>
*/
class ConditionalChecker {
   
    private Logger logger;

    public ConditionalChecker (Logger logger) {
  this.logger = logger;
    }

    boolean checkConditional (Connection con, HttpHeader header,
            Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry; 
  return (checkVary (con, header, rh) ||
    checkMaxAge (con, header, rh) ||
    checkNoCache (con, header, rh) ||
    checkQuery (con, header, rh) ||
    checkMinFresh (con, header, rh) ||
    checkRevalidation (con, header, rh));
    }

    private boolean checkVary (Connection con, HttpHeader req,
             Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
  HttpHeader resp = rh.dataHook;
  List<String> varies = resp.getHeaders ("Vary");
  for (String vary : varies) {
      if (vary.equals ("*")) {
    con.setMayUseCache (false);
    return false;
      } else {
    HttpHeader origreq = entry.getKey ();
    List<String> vals = origreq.getHeaders (vary);
    List<String> nvals = req.getHeaders (vary);
    if (vals.size () != nvals.size ()) {
        return setupRevalidation (con, req, rh);
    } else {
        for (String val : vals) {
      int k = nvals.indexOf (val);
      if (k == -1) {
          return setupRevalidation (con, req, rh);
      }
        }
    }
      }
  }
  return false;
    }

    private boolean checkMaxAge (Connection con, HttpHeader req,
         Connection.RequestHandler rh, String cached) {
  if (cached != null) {
      cached = cached.trim();
      if (cached.startsWith ("max-age=0")) {
    return setupRevalidation (con, req, rh);
      } else {
    Date now = new Date ();
    CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
    if (checkMaxAge (cached, "max-age=",
         entry.getCacheTime (), now)
        || checkMaxAge (cached, "s-maxage=",
            entry.getCacheTime (), now)) {
        con.setMayUseCache (false);
        return false;
    }
      }
  }
  return false;
    }
   
    private boolean checkMaxAge (String cached, String type,
         long cachetime, Date now) {
  if (cached.startsWith (type)) {
      String secs = cached.substring (type.length ());
      try {
    long l = Long.parseLong (secs) * 1000;
    long ad = now.getTime () - cachetime;
    if (ad > l)
        return true;
      } catch (NumberFormatException e) {
    logger.logWarn ("Bad number for max-age: '" +
        cached.substring (8) + "'");       
      }
  }
  return false;
    }

    protected boolean checkMaxAge (Connection con, HttpHeader req,
           Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
   List<String> ccs = req.getHeaders ("Cache-Control");
  for (String cc : ccs) {
      if (checkMaxAge (con, req, rh, cc))
     return true;
  }
  return false;
    }

    private boolean checkNoCacheHeader (List<String> v) {
  for (String nc : v)
      if (nc.equals ("no-cache"))
    return true;
  return false;
    }

    private boolean checkNoCache (Connection con, HttpHeader header,
          Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
  boolean noCache = false;
  // Only check the response header,
  // request headers with no-cache == refetch.
  HttpHeader resp = rh.dataHook;
  noCache = checkNoCacheHeader (resp.getHeaders ("Cache-Control"));
  if (noCache) {
      return setupRevalidation (con, header, rh);
  }
  return false;
    }

    private boolean checkQuery (Connection con, HttpHeader header,
        Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
  String uri = header.getRequestURI ();
  int i = uri.indexOf ('?');
  if (i >= 0) {
      return setupRevalidation (con, header, rh);
  }
  return false;
    }

    protected long getCacheControlValue (HttpHeader header, String cc) {
  for (String ncc : header.getHeaders ("Cache-Control")) {
      String[] sts = ncc.split (",");
      for (String nc : sts) {
    nc = nc.trim ();
    if (nc.startsWith (cc))
        return Long.parseLong (nc.substring (cc.length ()));
      }
  }
  return -1;
    }
   
    private boolean checkMinFresh (Connection con, HttpHeader header,
           Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
  long minFresh = getCacheControlValue (header, "min-fresh=");
  if (minFresh == -1)
      return false;
  long maxAge = getCacheControlValue (rh.dataHook, "max-age=");
  if (maxAge == -1)
      return false;
  long currentAge = (System.currentTimeMillis () -
         entry.getCacheTime ()) / 1000;
  if ((maxAge - currentAge) < minFresh)
      return setupRevalidation (con, header, rh);
  return false;
    }

    private boolean checkRevalidation (Connection con, HttpHeader header,
               Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  if (entry == null)
      return false;
 
  HttpHeader resp = rh.dataHook;
  for (String ncc : resp.getHeaders ("Cache-Control")) {
      String[] sts = ncc.split (",");
      for (String nc : sts) {
    nc = nc.trim ();
    if (nc.equals ("must-revalidate") ||
        nc.equals ("proxy-revalidate")) {
        con.setMustRevalidate (true);
        long maxAge =
      getCacheControlValue (rh.dataHook, "max-age=");
        if (maxAge >= 0) {
      long currentAge = (System.currentTimeMillis () -
             entry.getCacheTime ()) / 1000;
      if (maxAge == 0 || currentAge > maxAge) {
          return setupRevalidation (con, header, rh);
      }
        }
    } else if (nc.startsWith ("s-maxage=")) {
        con.setMustRevalidate (true);
        long sm =
      Long.parseLong (nc.substring ("s-maxage=".length ()));
        if (sm >= 0) {
      long currentAge = (System.currentTimeMillis () -
             entry.getCacheTime ()) / 1000;
      if (sm == 0 || currentAge > sm) {     
          return setupRevalidation (con, header, rh);
      }
        }
    }
      }
  }
  return false;
    }

    private boolean setupRevalidation (Connection con, HttpHeader req,
               Connection.RequestHandler rh) {
  CacheEntry<HttpHeader, HttpHeader> entry = rh.entry;
  con.setMayUseCache (false);
  String method = req.getMethod ();
  // if we can not filter (noproxy-request) we can not revalidate...
  if (method.equals ("GET") && entry != null && con.getMayFilter ()) {
      HttpHeader resp = rh.dataHook;
      String etag = resp.getHeader ("ETag");
      String lmod = resp.getHeader ("Last-Modified");
      if (etag != null) {
    String inm = req.getHeader ("If-None-Match");
    if (inm == null) {
        req.setHeader ("If-None-Match", etag);
        con.setAddedINM (true);
    }
    return true;
      } else if (lmod != null) {
    String ims = req.getHeader ("If-Modified-Since");
    if (ims == null) {
        req.setHeader ("If-Modified-Since", lmod);
        con.setAddedIMS (true);
    }
    return true;
      } else {
    con.setMayUseCache (false);
    return false;
      }
  }
  return false;
    }

    boolean checkMaxStale (HttpHeader req, Connection.RequestHandler rh) {
  for (String cc : req.getHeaders ("Cache-Control")) {
      cc = cc.trim ();
      if (cc.equals ("max-stale")) {
    if (rh.entry != null) {
        HttpHeader resp = rh.dataHook;
        long maxAge =
      rh.cond.getCacheControlValue (resp, "max-age=");
        if (maxAge >= 0) {
      long now = System.currentTimeMillis ();
      long secs = (now - rh.entry.getCacheTime ()) / 1000;
      long currentAge = secs;
      String age = resp.getHeader ("Age");
      if (age != null)
          currentAge += Long.parseLong (age);
      if (currentAge > maxAge) {
          resp.addHeader ("Warning",
              "110 RabbIT \"Response is stale\"");
      }
        }
    }
    return true;
      }
  }
  return false;
    }

    private void checkStaleHeader (HttpHeader header, HttpHeader webHeader,
           HttpHeader cachedWebHeader, String str,
           Connection con) {
  String cln = webHeader.getHeader (str);
  String clo = cachedWebHeader.getHeader (str);
  if (clo != null) {
      if (!clo.equals (cln)) {
    con.getProxy ().getCache ().remove (header);
    return;
      }
  } else {
      if (cln != null) {
    con.getProxy ().getCache ().remove (header);
    return;
      }
  }
    }

    void checkStaleCache (HttpHeader header, Connection con,
        Connection.RequestHandler rh) {
  if (rh.entry == null)
      return;
  if (rh.webHeader.getStatusCode ().trim ().equals ("304"))
      return;
  HttpHeader cachedWebHeader = rh.dataHook;

  String sd = rh.webHeader.getHeader ("Date");
  String cd = cachedWebHeader.getHeader ("Date");
  if (sd != null && cd != null) {
      Date d1 = HttpDateParser.getDate (sd);
      Date d2 = HttpDateParser.getDate (cd);
      // if we get a response with a date older than we have,
      // we keep our cache.
      if (d1 != null && d1.before (d2)) {
    con.setMayCache (false);
    return;
      }
  }
 
  if (rh.webHeader.getStatusCode ().equals ("200"))
      checkStaleHeader (header, rh.webHeader,
            cachedWebHeader, "Content-Length", con);
  checkStaleHeader (header, rh.webHeader,
        cachedWebHeader, "Content-MD5", con);
  checkStaleHeader (header, rh.webHeader,
        cachedWebHeader, "ETag", con);
  checkStaleHeader (header, rh.webHeader,
        cachedWebHeader, "Last-Modified", con);
    }
}
TOP

Related Classes of rabbit.proxy.ConditionalChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.