Added support for ETag conditional GETs, streamlined support for

Last-Modified and If-Modified-Since
This commit is contained in:
hns 2002-10-28 16:48:28 +00:00
parent 1690b6bf58
commit 5003588bb7
4 changed files with 131 additions and 59 deletions

View file

@ -56,7 +56,7 @@ public class RequestBean implements Serializable {
return req.getUsername ();
}
public Date getLastModified () {
/* public Date getLastModified () {
long since = req.getIfModifiedSince ();
if (since < 0)
return null;
@ -67,7 +67,7 @@ public class RequestBean implements Serializable {
public void setLastModified () {
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.");
}
} */
}

View file

@ -26,10 +26,9 @@ public class RequestTrans implements Externalizable {
// timestamp of client-cached version, if present in request
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?
public transient long startTime;
@ -130,6 +129,7 @@ public class RequestTrans implements Externalizable {
values = (Map) s.readObject ();
httpMethod = s.readByte ();
ifModifiedSince = s.readLong ();
etags = (Set) s.readObject ();
}
/**
@ -141,50 +141,78 @@ public class RequestTrans implements Externalizable {
s.writeObject (values);
s.writeByte (httpMethod);
s.writeLong (ifModifiedSince);
s.writeObject (etags);
}
public void setIfModifiedSince (long since) {
ifModifiedSince = since;
}
public long getIfModifiedSince () {
return ifModifiedSince;
}
public String getUsername() {
if ( httpUsername!=null )
return httpUsername;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpUsername;
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 String getPassword() {
if ( httpPassword!=null )
return httpPassword;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpPassword;
}
public Set getETags () {
return etags;
}
private void decodeHttpAuth(String auth) {
if ( auth==null )
return;
StringTokenizer tok;
if( auth.startsWith("Basic ") )
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" );
else
tok = new StringTokenizer ( new String( Base64.decode(auth.toCharArray()) ), ":" );
try { httpUsername = tok.nextToken(); }
catch ( NoSuchElementException e ) { httpUsername = null; }
try { httpPassword = tok.nextToken(); }
catch ( NoSuchElementException e ) { httpPassword = null; }
public boolean hasETag (String etag) {
if (etags == null || etag == null)
return false;
return etags.contains (etag);
}
public String getUsername() {
if ( httpUsername!=null )
return httpUsername;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpUsername;
}
public String getPassword() {
if ( httpPassword!=null )
return httpPassword;
String auth = (String)get("authorization");
if ( auth==null || "".equals(auth) ) {
return null;
}
decodeHttpAuth(auth);
return httpPassword;
}
private void decodeHttpAuth(String auth) {
if ( auth==null )
return;
StringTokenizer tok;
if( auth.startsWith("Basic ") )
tok = new StringTokenizer ( new String( Base64.decode((auth.substring(6)).toCharArray()) ), ":" );
else
tok = new StringTokenizer ( new String( Base64.decode(auth.toCharArray()) ), ":" );
try {
httpUsername = tok.nextToken();
} catch ( NoSuchElementException e ) {
httpUsername = null;
}
try {
httpPassword = tok.nextToken();
} catch ( NoSuchElementException e ) {
httpPassword = null;
}
}
}

View file

@ -97,13 +97,6 @@ public class ResponseBean implements Serializable {
res.contentType = contentType;
}
public void setLastModified (Date date) {
if (date == null)
res.setLastModified (-1);
else
res.setLastModified (date.getTime());
}
public Map getdata () {
return res.getResponseData ();
}
@ -143,19 +136,34 @@ public class ResponseBean implements Serializable {
public void setstatus (int status) {
res.status = status;
}
public Date getLastModified () {
long modified = res.getLastModified ();
if (modified > -1)
return new Date (modified);
else
else
return null;
}
public void notModified () throws RedirectException {
res.setNotModified (true);
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);
} */
}

View file

@ -54,7 +54,8 @@ public final class ResponseTrans implements Externalizable {
private long lastModified = -1;
// flag to signal that resource has not been modified
private boolean notModified = false;
// Entity Tag for this response, used for conditional GETs
private String etag = null;
// cookies
String cookieKeys[];
@ -85,20 +86,26 @@ public final class ResponseTrans implements Externalizable {
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
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 () {
super ();
title = head = body = message = error = null;
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;
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
} else {
response = new byte[0];
@ -359,17 +375,35 @@ public final class ResponseTrans implements Externalizable {
}
public void setLastModified (long modified) {
if (modified > -1 && reqtrans != null &&
reqtrans.getIfModifiedSince() >= modified)
{
notModified = true;
throw new RedirectException (null);
}
lastModified = modified;
}
public long getLastModified () {
return lastModified;
}
public void setNotModified (boolean notmod) throws RedirectException {
/* public void setNotModified (boolean notmod) throws RedirectException {
notModified = notmod;
if (notmod)
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 () {
@ -460,6 +494,7 @@ public final class ResponseTrans implements Externalizable {
lastModified = s.readLong ();
notModified = s.readBoolean ();
charset = (String) s.readObject ();
etag = (String) s.readObject ();
}
public void writeExternal (ObjectOutput s) throws IOException {
@ -476,6 +511,7 @@ public final class ResponseTrans implements Externalizable {
s.writeLong (lastModified);
s.writeBoolean (notModified);
s.writeObject (charset);
s.writeObject (etag);
}
}