* Implement ETag based conditional GET for forwarded resources.
(ETag is based on last modified date and file size)
This commit is contained in:
parent
cab28b406a
commit
1c51121bdc
1 changed files with 29 additions and 9 deletions
|
@ -493,22 +493,27 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
throw new IOException("Resource "+forward+" not found");
|
throw new IOException("Resource "+forward+" not found");
|
||||||
|
|
||||||
File file = new File(path);
|
File file = new File(path);
|
||||||
// check last modified date.
|
// calculate checksom on last modified date and content length.
|
||||||
// date headers don't do milliseconds, round to seconds
|
byte[] checksum = getChecksum(file);
|
||||||
long lastModified = (file.lastModified() / 1000) * 1000;
|
String etag = "\"" + new String(Base64.encode(checksum)) + "\"";
|
||||||
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
|
res.setHeader("ETag", etag);
|
||||||
if (lastModified == ifModifiedSince) {
|
String etagHeader = req.getHeader("If-None-Match");
|
||||||
res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
if (etagHeader != null) {
|
||||||
return;
|
StringTokenizer st = new StringTokenizer(etagHeader, ", \r\n");
|
||||||
|
while (st.hasMoreTokens()) {
|
||||||
|
if (etag.equals(st.nextToken())) {
|
||||||
|
res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int length = (int) file.length();
|
int length = (int) file.length();
|
||||||
res.setContentLength(length);
|
res.setContentLength(length);
|
||||||
res.setDateHeader("Last-Modified", lastModified);
|
|
||||||
res.setContentType(hopres.getContentType());
|
res.setContentType(hopres.getContentType());
|
||||||
|
|
||||||
InputStream in = cx.getResourceAsStream(forward);
|
InputStream in = cx.getResourceAsStream(forward);
|
||||||
if (in == null)
|
if (in == null)
|
||||||
throw new IOException("Can't read "+path);
|
throw new IOException("Can't read " + path);
|
||||||
try {
|
try {
|
||||||
OutputStream out = res.getOutputStream();
|
OutputStream out = res.getOutputStream();
|
||||||
|
|
||||||
|
@ -533,6 +538,21 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] getChecksum(File file) {
|
||||||
|
byte[] checksum = new byte[16];
|
||||||
|
long n = file.lastModified();
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
checksum[i] = (byte) (n);
|
||||||
|
n >>>= 8;
|
||||||
|
}
|
||||||
|
n = file.length();
|
||||||
|
for (int i=8; i<16; i++) {
|
||||||
|
checksum[i] = (byte) (n);
|
||||||
|
n >>>= 8;
|
||||||
|
}
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to build the form value array when a multipart (file upload) form has
|
* Used to build the form value array when a multipart (file upload) form has
|
||||||
* multiple values for one form element name.
|
* multiple values for one form element name.
|
||||||
|
|
Loading…
Add table
Reference in a new issue