Added support for ETag conditional GETs, streamlined support for
Last-Modified and If-Modified-Since
This commit is contained in:
parent
1690b6bf58
commit
5003588bb7
4 changed files with 131 additions and 59 deletions
|
@ -56,7 +56,7 @@ public class RequestBean implements Serializable {
|
||||||
return req.getUsername ();
|
return req.getUsername ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getLastModified () {
|
/* public Date getLastModified () {
|
||||||
long since = req.getIfModifiedSince ();
|
long since = req.getIfModifiedSince ();
|
||||||
if (since < 0)
|
if (since < 0)
|
||||||
return null;
|
return null;
|
||||||
|
@ -67,7 +67,7 @@ public class RequestBean implements Serializable {
|
||||||
public void setLastModified () {
|
public void setLastModified () {
|
||||||
throw new RuntimeException ("The lastModified property of the Request object is read-only. "+
|
throw new RuntimeException ("The lastModified property of the Request object is read-only. "+
|
||||||
"Set lastModified on the Response object if you want to mark the last modification date of a resource.");
|
"Set lastModified on the Response object if you want to mark the last modification date of a resource.");
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,9 @@ public class RequestTrans implements Externalizable {
|
||||||
|
|
||||||
// timestamp of client-cached version, if present in request
|
// timestamp of client-cached version, if present in request
|
||||||
private long ifModifiedSince = -1;
|
private long ifModifiedSince = -1;
|
||||||
|
// set of ETags the client sent with If-None-Match header
|
||||||
|
private Set etags;
|
||||||
|
|
||||||
|
|
||||||
// this is used to hold the EcmaScript form data object
|
|
||||||
public transient Object data;
|
|
||||||
// when was execution started on this request?
|
// when was execution started on this request?
|
||||||
public transient long startTime;
|
public transient long startTime;
|
||||||
|
|
||||||
|
@ -130,6 +129,7 @@ public class RequestTrans implements Externalizable {
|
||||||
values = (Map) s.readObject ();
|
values = (Map) s.readObject ();
|
||||||
httpMethod = s.readByte ();
|
httpMethod = s.readByte ();
|
||||||
ifModifiedSince = s.readLong ();
|
ifModifiedSince = s.readLong ();
|
||||||
|
etags = (Set) s.readObject ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,6 +141,7 @@ public class RequestTrans implements Externalizable {
|
||||||
s.writeObject (values);
|
s.writeObject (values);
|
||||||
s.writeByte (httpMethod);
|
s.writeByte (httpMethod);
|
||||||
s.writeLong (ifModifiedSince);
|
s.writeLong (ifModifiedSince);
|
||||||
|
s.writeObject (etags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIfModifiedSince (long since) {
|
public void setIfModifiedSince (long since) {
|
||||||
|
@ -151,6 +152,27 @@ public class RequestTrans implements Externalizable {
|
||||||
return ifModifiedSince;
|
return ifModifiedSince;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setETags (String etagHeader) {
|
||||||
|
etags = new HashSet();
|
||||||
|
if (etagHeader.indexOf (",") > -1) {
|
||||||
|
StringTokenizer st = new StringTokenizer (etagHeader, ", \r\n");
|
||||||
|
while (st.hasMoreTokens())
|
||||||
|
etags.add (st.nextToken ());
|
||||||
|
} else {
|
||||||
|
etags.add (etagHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set getETags () {
|
||||||
|
return etags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasETag (String etag) {
|
||||||
|
if (etags == null || etag == null)
|
||||||
|
return false;
|
||||||
|
return etags.contains (etag);
|
||||||
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
if ( httpUsername!=null )
|
if ( httpUsername!=null )
|
||||||
return httpUsername;
|
return httpUsername;
|
||||||
|
@ -181,10 +203,16 @@ public class RequestTrans implements Externalizable {
|
||||||
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" );
|
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" );
|
||||||
else
|
else
|
||||||
tok = new StringTokenizer ( new String( Base64.decode(auth.toCharArray()) ), ":" );
|
tok = new StringTokenizer ( new String( Base64.decode(auth.toCharArray()) ), ":" );
|
||||||
try { httpUsername = tok.nextToken(); }
|
try {
|
||||||
catch ( NoSuchElementException e ) { httpUsername = null; }
|
httpUsername = tok.nextToken();
|
||||||
try { httpPassword = tok.nextToken(); }
|
} catch ( NoSuchElementException e ) {
|
||||||
catch ( NoSuchElementException e ) { httpPassword = null; }
|
httpUsername = null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
httpPassword = tok.nextToken();
|
||||||
|
} catch ( NoSuchElementException e ) {
|
||||||
|
httpPassword = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,13 +97,6 @@ public class ResponseBean implements Serializable {
|
||||||
res.contentType = contentType;
|
res.contentType = contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastModified (Date date) {
|
|
||||||
if (date == null)
|
|
||||||
res.setLastModified (-1);
|
|
||||||
else
|
|
||||||
res.setLastModified (date.getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map getdata () {
|
public Map getdata () {
|
||||||
return res.getResponseData ();
|
return res.getResponseData ();
|
||||||
}
|
}
|
||||||
|
@ -152,9 +145,24 @@ public class ResponseBean implements Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notModified () throws RedirectException {
|
public void setLastModified (Date date) {
|
||||||
|
if (date == null)
|
||||||
|
res.setLastModified (-1);
|
||||||
|
else
|
||||||
|
res.setLastModified (date.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getETag () {
|
||||||
|
return res.getETag ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setETag (String etag) {
|
||||||
|
res.setETag (etag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public void notModified () throws RedirectException {
|
||||||
res.setNotModified (true);
|
res.setNotModified (true);
|
||||||
}
|
} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ public final class ResponseTrans implements Externalizable {
|
||||||
private long lastModified = -1;
|
private long lastModified = -1;
|
||||||
// flag to signal that resource has not been modified
|
// flag to signal that resource has not been modified
|
||||||
private boolean notModified = false;
|
private boolean notModified = false;
|
||||||
|
// Entity Tag for this response, used for conditional GETs
|
||||||
|
private String etag = null;
|
||||||
|
|
||||||
// cookies
|
// cookies
|
||||||
String cookieKeys[];
|
String cookieKeys[];
|
||||||
|
@ -85,20 +86,26 @@ public final class ResponseTrans implements Externalizable {
|
||||||
|
|
||||||
static final int INITIAL_BUFFER_SIZE = 2048;
|
static final int INITIAL_BUFFER_SIZE = 2048;
|
||||||
|
|
||||||
/**
|
|
||||||
* JavaScript object to make the values Map accessible to
|
|
||||||
* script code as res.data
|
|
||||||
*/
|
|
||||||
public transient Object data;
|
|
||||||
|
|
||||||
// the map of form and cookie data
|
// the map of form and cookie data
|
||||||
private transient Map values;
|
private transient Map values;
|
||||||
|
|
||||||
|
// the map of macro handlers
|
||||||
|
private transient Map handlers;
|
||||||
|
|
||||||
|
// the request trans for this response
|
||||||
|
private transient RequestTrans reqtrans;
|
||||||
|
|
||||||
|
|
||||||
public ResponseTrans () {
|
public ResponseTrans () {
|
||||||
super ();
|
super ();
|
||||||
title = head = body = message = error = null;
|
title = head = body = message = error = null;
|
||||||
values = new HashMap ();
|
values = new HashMap ();
|
||||||
|
handlers = new HashMap ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseTrans (RequestTrans req) {
|
||||||
|
this();
|
||||||
|
reqtrans = req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,6 +327,15 @@ public final class ResponseTrans implements Externalizable {
|
||||||
error = true;
|
error = true;
|
||||||
response = buffer.toString ().getBytes ();
|
response = buffer.toString ().getBytes ();
|
||||||
}
|
}
|
||||||
|
// if etag is not set, calc MD5 digest and check it
|
||||||
|
if (etag == null && !notModified && redir == null) try {
|
||||||
|
String digest = MD5Encoder.encode (response);
|
||||||
|
etag = "\""+digest+"\"";
|
||||||
|
if (reqtrans != null && reqtrans.hasETag (etag)) {
|
||||||
|
response = new byte[0];
|
||||||
|
notModified = true;
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {}
|
||||||
buffer = null; // make sure this is done only once, even with more requsts attached
|
buffer = null; // make sure this is done only once, even with more requsts attached
|
||||||
} else {
|
} else {
|
||||||
response = new byte[0];
|
response = new byte[0];
|
||||||
|
@ -359,6 +375,12 @@ public final class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastModified (long modified) {
|
public void setLastModified (long modified) {
|
||||||
|
if (modified > -1 && reqtrans != null &&
|
||||||
|
reqtrans.getIfModifiedSince() >= modified)
|
||||||
|
{
|
||||||
|
notModified = true;
|
||||||
|
throw new RedirectException (null);
|
||||||
|
}
|
||||||
lastModified = modified;
|
lastModified = modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,10 +388,22 @@ public final class ResponseTrans implements Externalizable {
|
||||||
return lastModified;
|
return lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNotModified (boolean notmod) throws RedirectException {
|
/* public void setNotModified (boolean notmod) throws RedirectException {
|
||||||
notModified = notmod;
|
notModified = notmod;
|
||||||
if (notmod)
|
if (notmod)
|
||||||
throw new RedirectException (null);
|
throw new RedirectException (null);
|
||||||
|
} */
|
||||||
|
|
||||||
|
public void setETag (String value) {
|
||||||
|
etag = value == null ? null : "\""+value+"\"";
|
||||||
|
if (etag != null && reqtrans != null && reqtrans.hasETag (etag)) {
|
||||||
|
notModified = true;
|
||||||
|
throw new RedirectException (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getETag () {
|
||||||
|
return etag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getNotModified () {
|
public boolean getNotModified () {
|
||||||
|
@ -460,6 +494,7 @@ public final class ResponseTrans implements Externalizable {
|
||||||
lastModified = s.readLong ();
|
lastModified = s.readLong ();
|
||||||
notModified = s.readBoolean ();
|
notModified = s.readBoolean ();
|
||||||
charset = (String) s.readObject ();
|
charset = (String) s.readObject ();
|
||||||
|
etag = (String) s.readObject ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeExternal (ObjectOutput s) throws IOException {
|
public void writeExternal (ObjectOutput s) throws IOException {
|
||||||
|
@ -476,6 +511,7 @@ public final class ResponseTrans implements Externalizable {
|
||||||
s.writeLong (lastModified);
|
s.writeLong (lastModified);
|
||||||
s.writeBoolean (notModified);
|
s.writeBoolean (notModified);
|
||||||
s.writeObject (charset);
|
s.writeObject (charset);
|
||||||
|
s.writeObject (etag);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue