0
|
1 package cachingfilter;
|
|
2
|
|
3 import java.io.IOException;
|
|
4 import java.text.DateFormat;
|
|
5 import java.text.SimpleDateFormat;
|
|
6 import java.util.Enumeration;
|
|
7 import java.util.TimeZone;
|
|
8 import java.util.Date;
|
|
9 import java.util.Locale;
|
|
10 import java.util.Map;
|
|
11 import java.util.HashMap;
|
|
12 import javax.servlet.http.HttpServletRequest;
|
|
13 import javax.servlet.http.HttpServletRequestWrapper;
|
|
14 import org.slf4j.Logger;
|
|
15 import org.slf4j.LoggerFactory;
|
|
16 import org.eclipse.jetty.server.AbstractHttpConnection;
|
|
17
|
|
18
|
|
19 final class CachingRequestWrapper extends HttpServletRequestWrapper {
|
|
20 private static final Logger logger = LoggerFactory.getLogger(CachingRequestWrapper.class);
|
|
21
|
|
22 static final String IF_MODIFIED_SINCE = "If-Modified-Since".toLowerCase();
|
|
23 static final String IF_NONE_MATCH = "If-None-Match".toLowerCase();
|
|
24 static final String ACCEPT_ENCODING = "Accept-Encoding".toLowerCase();
|
|
25
|
|
26 final Map<String,Object> headerMap = new HashMap<String,Object>();
|
|
27
|
|
28 CachingRequestWrapper(HttpServletRequest request) throws IOException {
|
|
29 super(request);
|
|
30 checkRequest(request);
|
|
31 }
|
|
32
|
|
33 private static void checkRequest(HttpServletRequest request) throws IOException {
|
|
34 AbstractHttpConnection c = ((org.eclipse.jetty.server.Request) request).getConnection();
|
|
35 if (c.getRequestFields().containsKey("Host")) {
|
|
36 for (Enumeration<String> e2 = c.getRequestFields().getValues("Host"); e2.hasMoreElements();) {
|
|
37 if (e2.nextElement().trim().endsWith(":")) {
|
|
38 throw new IOException("Bad 'Host' request header (ends with colon)");
|
|
39 }
|
|
40 }
|
|
41 }
|
|
42 }
|
|
43
|
|
44 public String getHeader(String name) {
|
|
45 /*
|
|
46 String v = getHeader2(name);
|
|
47 logger.trace("getHeader "+name+" = "+v);
|
|
48 return v;
|
|
49 }
|
|
50 public String getHeader2(String name) {
|
|
51 */
|
|
52 String key = name.toLowerCase();
|
|
53 if( headerMap.containsKey(key) ) {
|
|
54 Object val = headerMap.get(key);
|
|
55 if( val instanceof Long ) {
|
|
56 long date = (Long)val;
|
|
57 if( date == -1 )
|
|
58 return null;
|
|
59 return formatDate(date);
|
|
60 }
|
|
61 return (String)val;
|
|
62 }
|
|
63 return super.getHeader(name);
|
|
64 }
|
|
65
|
|
66 public long getDateHeader(String name) {
|
|
67 /*
|
|
68 long v = getDateHeader2(name);
|
|
69 logger.trace("getDateHeader "+name+" = "+v);
|
|
70 return v;
|
|
71 }
|
|
72 public long getDateHeader2(String name) {
|
|
73 */
|
|
74 String key = name.toLowerCase();
|
|
75 if( headerMap.containsKey(key) )
|
|
76 return (Long)headerMap.get(key);
|
|
77 return super.getDateHeader(name);
|
|
78 }
|
|
79
|
|
80 boolean isCacheable() {
|
|
81 boolean isCacheable = false;
|
|
82 Long val = (Long)headerMap.get(IF_MODIFIED_SINCE);
|
|
83 if( val!=null ) {
|
|
84 try {
|
|
85 long cachedLastModified = val;
|
|
86 if( cachedLastModified != -1 ) {
|
|
87 long ifModifiedSince = super.getDateHeader(IF_MODIFIED_SINCE);
|
|
88 //logger.trace("cachedLastModified = "+cachedLastModified+" ifModifiedSince = "+ifModifiedSince);
|
|
89 if( cachedLastModified > ifModifiedSince )
|
|
90 return false;
|
|
91 isCacheable = true;
|
|
92 }
|
|
93 } catch(IllegalArgumentException e) {
|
|
94 logger.warn("bad date, user-agent="+getHeader("user-agent"),e);
|
|
95 }
|
|
96 }
|
|
97 String etag = (String)headerMap.get(IF_NONE_MATCH);
|
|
98 if( etag != null ) {
|
|
99 String ifNoneMatch = super.getHeader(IF_NONE_MATCH);
|
|
100 if( !etag.equals(ifNoneMatch) )
|
|
101 return false;
|
|
102 isCacheable = true;
|
|
103 }
|
|
104 return isCacheable;
|
|
105 }
|
|
106
|
|
107
|
|
108 private static ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
|
|
109 protected synchronized DateFormat initialValue() {
|
|
110 DateFormat httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
|
|
111 httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
|
112 return httpDateFormat;
|
|
113 }
|
|
114 };
|
|
115
|
|
116 private String formatDate(long date) {
|
|
117 return dateFormat.get().format(new Date(date));
|
|
118 }
|
|
119 }
|