mcardle     2005/11/08 11:58:49 CET

  Modified files:
    src/net/sf/j2ep/responsehandlers ResponseHandlerBase.java 
  Log:
  * better policy for cookie caching

  * supports Last-Modified header
  
  Revision  Changes    Path
  1.10      +87 -126   
esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java.diff?r1=1.9&r2=1.10&f=h
  
  
  
  Index: ResponseHandlerBase.java
  ===================================================================
  RCS file: 
/home/cvs/repository/esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ResponseHandlerBase.java  4 Nov 2005 16:56:30 -0000       1.9
  +++ ResponseHandlerBase.java  8 Nov 2005 10:58:49 -0000       1.10
  @@ -25,8 +25,6 @@
   import java.util.Vector;
   import java.util.Enumeration;
   import java.util.Date;
  -import java.text.DateFormat;
  -import java.text.ParseException;
   
   import javax.servlet.ServletResponse;
   import javax.servlet.http.HttpServletResponse;
  @@ -40,6 +38,8 @@
   import net.sf.j2ep.ProxyFilter;
   
   import org.apache.commons.httpclient.*;
  +import org.apache.commons.httpclient.util.DateUtil;
  +import org.apache.commons.httpclient.util.DateParseException;
   import org.apache.commons.httpclient.methods.GetMethod;
   import org.apache.commons.logging.LogFactory;
   import org.apache.commons.logging.Log;
  @@ -56,7 +56,7 @@
    *
    * @author Anders Nyman
    */
  -public abstract class ResponseHandlerBase implements ResponseHandler{
  +public abstract class ResponseHandlerBase implements ResponseHandler {
   
       private static Log log = LogFactory.getLog(ResponseHandlerBase.class);
   
  @@ -163,12 +163,7 @@
   
           ByteArrayOutputStream cacheStream = new ByteArrayOutputStream(1000);
   
  -        /*private Locale locale = null;
  -        private String contentEncoding = null;
  -        private String contentType = null;
  -         private long lastModified = -1;*/
  -
  -        if (streamFromServer != null) {
  +       if (streamFromServer != null) {
               byte[] buffer = new byte[1024];
               int read = streamFromServer.read(buffer);
               while (read > 0) {
  @@ -199,38 +194,8 @@
   
       public void sendStreamToClientFromCache(ServletResponse clientResponse, 
String cacheKey, byte[] cachedByteContent) throws IOException {
   
  -
  -        //****************************************** MEGA HACK 
*************************************
  -        String ifnonematch = "";
  -        try {
  -            if (methodToServer.getRequestHeader("if-none-match").getValue() 
!=null) {
  -                log.debug("removed if-none-match 
["+methodToServer.getRequestHeader("if-none-match")+"] ");
  -                methodToServer.removeRequestHeader("if-none-match");
  -            }
  -
  -        } catch (Exception ex) {
  -            log.debug(" no if-none-match 
["+methodToServer.getResponseHeader("if-none-match")+"]  ex: "+ex);
  -        }
  -        String ifmodifiedsince = "";
  -        try {
  -            if 
(methodToServer.getRequestHeader("if-modified-since").getValue() !=null) {
  -                log.debug("removed if-modified-since 
["+methodToServer.getRequestHeader("if-modified-since")+"] ");
  -                methodToServer.removeRequestHeader("if-modified-since");
  -            }
  -
  -        } catch (Exception ex) {
  -            log.debug(" no if-modified-since 
["+methodToServer.getResponseHeader("if-modified-since")+"]  ex: "+ex);
  -        }
  -        //****************************************** MEGA HACK 
*************************************
  -
  -
           OutputStream clientResponseStream = clientResponse.getOutputStream();
   
  -        /*private Locale locale = null;
  -        private String contentEncoding = null;
  -        private String contentType = null;
  -         private long lastModified = -1;*/
  -
           if (cachedByteContent==null) {
               log.error("sendStreamToClientFromCache : cachedByteContent is 
NULL. so not sending anything");
           }
  @@ -263,9 +228,17 @@
               String name = header.getName();
               boolean contentLength = name.equalsIgnoreCase("content-length");
               boolean connection = name.equalsIgnoreCase("connection");
  -            boolean cookie = name.equalsIgnoreCase("set-cookie");
  +            boolean setcookie = name.equalsIgnoreCase("set-cookie");
   
               if (!contentLength && !connection ) {
  +                //optionally ignore Set-Cookie header
  +                if (setcookie && ignoreCookies) {
  +                    log.debug("Ignored Set-Cookie header because this is a 
response returned from Cache. Header:"+header);
  +                    continue;
  +                }
  +                else if (setcookie)  {
  +                    log.debug("Keeping Set-Cookie header because this is a 
response returned directly from Server. Header:"+header);
  +                }
                   clientResponse.addHeader(name, header.getValue());
               }
           }
  @@ -351,11 +324,13 @@
           else {
   
               CacheObject cacheObject = null;
  +            boolean freshCopy = false;
   
               //Case 2: Not in cache so fetch any necessary bits
               if (!fragmentCache.contains(cacheKey)) {
                   log.debug(" * Case 2: Not in cache so fetch any necessary 
bits *");
                   fetch ( clientResponse, clientRequest, cacheKey , 
clientRequestUrl);
  +                freshCopy = true;
               }
               else {
                   log.debug (" * Case 3: in cache => return from cache *");
  @@ -367,16 +342,25 @@
               //reset the method to the cached one so we can take the settings 
from that one
               this.methodToServer = 
cacheObject.getUrlCacheObject().getMethod();
   
  -            copyHeadersFromServerResponseToClientResponse(clientResponse, 
true); //doesn't copy over saved cookie
  -            //copy the Cookie in the client request to the one sent back to 
the client
  -            //and not the old one stored in the cache as they might be for 
different sessions
  -            clientResponse.addHeader("Set-Cookie", 
clientRequest.getHeader("Cookie"));
  +            //copy all server response headers to the client
  +            // but not necessarily for the Set-Cookie header:
  +            //the Set-Cookie header is only forwarded back to the client if
  +            //this is a fresh copy of the object we are returning.
  +            //So we can guarantee that the returned Set-Cookie is the one 
targetted for the current client
  +            copyHeadersFromServerResponseToClientResponse(clientResponse, 
!freshCopy); //doesn't copy over saved cookie for responses returned from the 
cache
  +            //TODO: might be inconsistancies
  +            //TODO: 1/ when simply a fragment of a skeleton is fetched
  +            //TODO: and we return the Set-Cookie of the cached skeleton and 
not of the newly
  +            //TODO: fetched fragment. Not sure what behaviour to adopt here.
  +            //TODO: 2/ when a Set-Cookie should be sent back to the client
  +            //TODO: but isn't because the object is already cached. Might 
not be important since
  +            //TODO: original GET URL contains an ESI identifier which has a 
similar role to cookies. Need to check
   
               boolean return304NotModified = 
checkIfConditionalHtppHeaders(clientRequest, cacheObject);
   
               if (return304NotModified) {
                   log.debug("Returning a HTPP 304 for 
"+cacheObject.getUrlCacheObject().getUrl());
  -                clientResponse.setStatus(304); //HTTP 304: the document was 
not modified
  +                
clientResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED); //HTTP 304: the 
document was not modified
                   //no data sent since request object hasn't changed
               }
               else {
  @@ -386,6 +370,7 @@
               }
           }
   
  +
       }
   
   
  @@ -479,125 +464,101 @@
       private boolean checkIfConditionalHtppHeaders(HttpServletRequest 
clientRequest, CacheObject cacheObject) {
           boolean return304NotModified = false;
   
  +        printRequestHeaders(clientRequest);
  +
           //check Entity Tag Revalidation
  -        String eTagHeader = clientRequest.getHeader("If-None-Match");
  -        if (eTagHeader !=null) {
  +        String IfNoneMatchHeader = clientRequest.getHeader("If-None-Match");
  +        if (IfNoneMatchHeader !=null) {
               Header eTagRespHeader = 
this.methodToServer.getResponseHeader("ETag");
               if (eTagRespHeader!=null)  {
                   String[] eTag = eTagRespHeader.getValue().split(",");
                   for (int i = 0; i<eTag.length; i++) { //since there can be 
more than one ETag e.g. If-None-March: "foobar","A34FAC0095","Profiles in 
Courage"
  -                    if (eTagHeader.equals(eTag[i])) {
  -                        log.debug("Detected a HTPP 304 for "+eTagHeader);
  +                    if (IfNoneMatchHeader.equals(eTag[i])) {
  +                        log.debug("Detected a HTPP 304 for 
["+IfNoneMatchHeader+"] because of ETag header ["+eTagRespHeader+"] from 
server");
                           return304NotModified = true;
                       }
                   }
               }
  +            else
  +                log.debug("client submitted a 
IfNoneMatch:"+IfNoneMatchHeader +" but cached server response did not contain 
an ETag");
           }
   
  -        String modSinceHeader = clientRequest.getHeader("If-Modified-Since");
  -        if ((eTagHeader!=null ^ return304NotModified==false)  //If an 
HTTP/1.1 cache or server receives a request with both If-Modified-Since and 
entity tag conditional headers, it must not return a 304 Not Modified response 
unless doing so is consistent with all of the conditional header fields in the 
request.
  -                && modSinceHeader !=null) {
  -
  -            try {
  -                //First check if the object has been changed in the cache 
since If-Modified-Since date
  -                Date modSinceHeaderDate = 
DateFormat.getDateInstance().parse(modSinceHeader);
  -                if 
(cacheObject.getUrlCacheObject().getLastUpdateDate().after(modSinceHeaderDate) 
) {
  -                    log.debug("Detected a HTPP 304 for "+modSinceHeader);
  -                    return304NotModified = true;
  +        long modSinceHeader = 
clientRequest.getDateHeader("If-Modified-Since");
  +        //if ((IfNoneMatchHeader!=null ^ return304NotModified==false)  //If 
an HTTP/1.1 cache or server receives a request with both If-Modified-Since and 
entity tag conditional headers, it must not return a 304 Not Modified response 
unless doing so is consistent with all of the conditional header fields in the 
request.
  +        //        && modSinceHeader !=null) {
  +        if (return304NotModified==false && modSinceHeader !=-1) {
  +            //First check if the object has been changed in the cache since 
If-Modified-Since date
  +            Date modSinceHeaderDate = new Date(modSinceHeader);
  +            if 
(cacheObject.getUrlCacheObject().getLastUpdateDate().after(modSinceHeaderDate) 
) {
  +                log.debug("Detected a HTTP 304 for ["+new 
Date(modSinceHeader)+"] because object has been changed/added in the cache at 
"+cacheObject.getUrlCacheObject().getLastUpdateDate());
  +                return304NotModified = true;
  +            }
  +            //if it hasn't, then still check if the stored Expires header 
date is after the If-Modified-Since date
  +            else {
  +                Header expiresRespHeader = 
this.methodToServer.getResponseHeader("Expires");
  +                if (expiresRespHeader!=null) {
  +                    try {
  +                        //TODO: move this date parsing to UrlCacheKey object 
initialization
  +                        Date expiresHeaderDate  = DateUtil.parseDate( 
expiresRespHeader.getValue() ) ;
  +                        if (modSinceHeaderDate.after(expiresHeaderDate)) {
  +                            log.debug("Detected a HTTP 304 for 
["+modSinceHeader+"] because of Expires Header ["+expiresRespHeader+"] from 
Server");
  +                            return304NotModified = true;
  +                        }
  +                    } catch (DateParseException e) {
  +                        log.error("Error trying to parse Expires Header date 
["+expiresRespHeader.getValue()+"] : "+e);
  +                    }
                   }
  -                //if it hasn't, then still check if the stored Expires 
header date is after the If-Modified-Since date
  -                else {
  -                    //TODO: rename vars to something more meaningful
  -                    Header expiresRespHeader = 
this.methodToServer.getResponseHeader("Expires");
  -                    if (expiresRespHeader!=null)   {
  -                        String expiresHeader = expiresRespHeader.getValue();
  -                        try {
  -                            Date expiresHeaderDate = 
DateFormat.getDateInstance().parse(expiresHeader);
  -                            if (modSinceHeaderDate.after(expiresHeaderDate)) 
{
  -                                log.debug("Detected a HTPP 304 for 
"+expiresRespHeader);
  -                                return304NotModified = true;
  -                            }
  -                        } catch (ParseException e) {
  -                            log.debug("Error trying to parse Expires Header 
date ["+expiresHeader+"] : "+e);
  +                Header lastModRespHeader = 
this.methodToServer.getResponseHeader("Last-Modified");
  +                if (return304NotModified==false && lastModRespHeader !=null) 
{
  +                    try {
  +                        //TODO: move this date parsing to UrlCacheKey object 
initialization
  +                        Date lastModHeaderDate  = DateUtil.parseDate( 
lastModRespHeader.getValue() ) ;
  +                        if (modSinceHeaderDate.after(lastModHeaderDate)) {
  +                            log.debug("Detected a HTTP 304 for 
["+modSinceHeader+"] because of Last-Modified Header ["+lastModRespHeader+"] 
from Server");
  +                            return304NotModified = true;
                           }
  +                    } catch (DateParseException e) {
  +                        log.error("Error trying to parse Last-Modified 
Header date ["+lastModRespHeader+"] : "+e);
                       }
                   }
  -            } catch (ParseException e) {
  -                log.debug("Badly formatted If-Modified-Since Header date 
["+modSinceHeader+"] in client Request : "+e);
  -            }
  -        }
  -        return return304NotModified;
  -    }
   
  -    public static void getRidOfDodgyRequestHeaders(HttpMethod method) {
  -        //****************************************** MEGA HACK 
*************************************
  -        String ifnonematch = "";
  -        try {
  -            if (method.getRequestHeader("if-none-match").getValue() !=null) {
  -                log.debug("removed if-none-match 
["+method.getRequestHeader("if-none-match")+"] ");
  -                method.removeRequestHeader("if-none-match");
  -            }
   
  -        } catch (Exception ex) {
  -            //log.debug(" no if-none-match 
["+method.getResponseHeader("if-none-match")+"]  ex: "+ex);
  -        }
  -        String ifmodifiedsince = "";
  -        try {
  -            if (method.getRequestHeader("if-modified-since").getValue() 
!=null) {
  -                log.debug("removed if-modified-since 
["+method.getRequestHeader("if-modified-since")+"] ");
  -                method.removeRequestHeader("if-modified-since");
               }
  -
  -        } catch (Exception ex) {
  -            //log.debug(" no if-modified-since 
["+method.getResponseHeader("if-modified-since")+"]  ex: "+ex);
           }
  -
  -        //****************************************** MEGA HACK 
*************************************
  +        return return304NotModified;
       }
   
  -    public static void getRidOfDodgyResponseHeaders(HttpMethod method) {
  -        //****************************************** MEGA HACK 
*************************************
  -        String ETag = "";
  -        try {
  -            if (method.getRequestHeader("ETag").getValue() !=null) {
  -                log.debug("removed ETag 
["+method.getRequestHeader("ETag")+"] ");
  -                method.removeRequestHeader("ETag");
  -            }
  -
  -        } catch (Exception ex) {
  -            //log.debug(" no ETag ["+method.getResponseHeader("ETag")+"]  
ex: "+ex);
  -        }
  -
  -        String LastModified = "";
  -        try {
  -            if (method.getRequestHeader("Last-Modified").getValue() !=null) {
  -                log.debug("removed Last-Modified 
["+method.getRequestHeader("Last-Modified")+"] ");
  -                method.removeRequestHeader("Last-Modified");
  +    public static void printRequestHeaders(HttpServletRequest clientRequest) 
{
  +        StringBuffer buffer = new StringBuffer();
  +        Enumeration headerNamesEnum = clientRequest.getHeaderNames();
  +        while (headerNamesEnum.hasMoreElements()) {
  +            String hName = (String) headerNamesEnum.nextElement();
  +            Enumeration hValEnum = clientRequest.getHeaders(hName);
  +            while (hValEnum.hasMoreElements()) {
  +                String hVal =  (String) hValEnum.nextElement();
  +                buffer.append(hName +":"+ hVal+"\n");
               }
  -
  -        } catch (Exception ex) {
  -            //log.debug(" no ETag 
["+method.getResponseHeader("Last-Modified")+"]  ex: "+ex);
           }
  -
  -        //****************************************** MEGA HACK 
*************************************
  +        log.debug("HTTP client REQUEST Headers : \n" + buffer.toString());
       }
   
  -
       public static void printRequestHeaders(HttpMethod method) {
           Header[] headers = method.getRequestHeaders();
           StringBuffer buffer = new StringBuffer();
           for (int i=0; i<headers.length; i++){
               buffer.append(headers[i]);
           }
  -        log.debug("HTTP REQUEST Headers : \n" + buffer.toString());
  +        log.debug("HTTP Server REQUEST Headers : \n" + buffer.toString());
       }
  +
  +
       public static void printResponseHeaders(HttpMethod method) {
           Header[] headers = method.getResponseHeaders();
           StringBuffer buffer = new StringBuffer();
           for (int i=0; i<headers.length; i++){
               buffer.append(headers[i]);
           }
  -        log.debug("HTTP RESPONSE Headers : \n" + buffer.toString());
  +        log.debug("HTTP Server RESPONSE Headers : \n" + buffer.toString());
       }
   
   
  

Reply via email to