public static CacheControl getCacheControl(IHttpHeaders headers, long requestTime) { CacheControl cc=new CacheControl(); bool proxyRevalidate=false; int sMaxAge=0; bool publicCache=false; bool privateCache=false; bool noCache=false; long expires=0; bool hasExpires=false; cc.uri=headers.getUrl(); string cacheControl=headers.getHeaderField("cache-control"); if(cacheControl!=null){ int index=0; int[] intval=new int[1]; while(index<cacheControl.Length){ int current=index; if((index=HeaderParser.parseToken(cacheControl,current,"private",true))!=current){ privateCache=true; } else if((index=HeaderParser.parseToken(cacheControl,current,"no-cache",true))!=current){ noCache=true; //Console.WriteLine("returning early because it saw no-cache"); return null; // return immediately, this is not cacheable } else if((index=HeaderParser.parseToken( cacheControl,current,"no-store",false))!=current){ cc.noStore=true; //Console.WriteLine("returning early because it saw no-store"); return null; // return immediately, this is not cacheable or storable } else if((index=HeaderParser.parseToken( cacheControl,current,"public",false))!=current){ publicCache=true; } else if((index=HeaderParser.parseToken( cacheControl,current,"no-transform",false))!=current){ cc.noTransform=true; } else if((index=HeaderParser.parseToken( cacheControl,current,"must-revalidate",false))!=current){ cc.mustRevalidate=true; } else if((index=HeaderParser.parseToken( cacheControl,current,"proxy-revalidate",false))!=current){ proxyRevalidate=true; } else if((index=HeaderParser.parseTokenWithDelta( cacheControl,current,"max-age",intval))!=current){ cc.maxAge=intval[0]; } else if((index=HeaderParser.parseTokenWithDelta( cacheControl,current,"s-maxage",intval))!=current){ sMaxAge=intval[0]; } else { index=HeaderParser.skipDirective(cacheControl,current); } } if(!publicCache && !privateCache && !noCache){ noCache=true; } } else { int code=headers.getResponseCode(); if((code==200 || code==203 || code==300 || code==301 || code==410) && headers.getHeaderField("authorization")==null){ publicCache=true; privateCache=false; } else { noCache=true; } } if(headers.getResponseCode()==206) { noCache=true; } string pragma=headers.getHeaderField("pragma"); if(pragma!=null && "no-cache".Equals(StringUtility.toLowerCaseAscii(pragma))){ noCache=true; //Console.WriteLine("returning early because it saw pragma no-cache"); return null; } long now=DateTimeUtility.getCurrentDate(); cc.code=headers.getResponseCode(); cc.date=now; cc.responseTime=now; cc.requestTime=requestTime; if(proxyRevalidate){ // Enable must-revalidate for simplicity; // proxyRevalidate usually only applies to shared caches cc.mustRevalidate=true; } if(headers.getHeaderField("date")!=null){ cc.date=headers.getHeaderFieldDate("date",Int64.MinValue); if(cc.date==Int64.MinValue) { noCache=true; } } else { noCache=true; } string expiresHeader=headers.getHeaderField("expires"); if(expiresHeader!=null){ expires=headers.getHeaderFieldDate("expires",Int64.MinValue); hasExpires=(cc.date!=Int64.MinValue); } if(headers.getHeaderField("age")!=null){ try { cc.age=Int32.Parse(headers.getHeaderField("age"),NumberStyles.AllowLeadingSign,CultureInfo.InvariantCulture); if(cc.age<0) { cc.age=0; } } catch(FormatException){ cc.age=-1; } } if(cc.maxAge>0 || sMaxAge>0){ long maxAge=cc.maxAge; // max age in seconds if(maxAge==0) { maxAge=sMaxAge; } if(cc.maxAge>0 && sMaxAge>0){ maxAge=Math.Max(cc.maxAge,sMaxAge); } cc.maxAge=maxAge*1000L; // max-age and s-maxage are in seconds hasExpires=false; } else if(hasExpires && !noCache){ long maxAge=expires-cc.date; cc.maxAge=(maxAge>Int32.MaxValue) ? Int32.MaxValue : (int)maxAge; } else if(noCache || cc.noStore){ cc.maxAge=0; } else { cc.maxAge=24L*3600L*1000L; } string reqmethod=headers.getRequestMethod(); if(reqmethod==null || ( !StringUtility.toLowerCaseAscii(reqmethod).Equals("get"))) // caching responses other than GET responses not supported return null; cc.requestMethod=StringUtility.toLowerCaseAscii(reqmethod); cc.cacheability=2; if(noCache) { cc.cacheability=0; } else if(privateCache) { cc.cacheability=1; } int i=0; cc.headers.Add(headers.getHeaderField(null)); while(true){ string newValue=headers.getHeaderField(i); if(newValue==null) { break; } string key=headers.getHeaderFieldKey(i); i++; if(key==null){ //Console.WriteLine("null key"); continue; } key=StringUtility.toLowerCaseAscii(key); // to simplify matters, don't include Age header fields; // so-called hop-by-hop headers are also not included if(!"age".Equals(key) && !"connection".Equals(key) && !"keep-alive".Equals(key) && !"proxy-authenticate".Equals(key) && !"proxy-authorization".Equals(key) && !"te".Equals(key) && !"trailer".Equals(key) && // NOTE: NOT Trailers !"transfer-encoding".Equals(key) && !"upgrade".Equals(key)){ cc.headers.Add(key); cc.headers.Add(newValue); } } //Console.WriteLine(" cc: %s",cc); return cc; }