From 113ea0aecc23a102cac8b66e269c721deb39cfd7 Mon Sep 17 00:00:00 2001 From: hns Date: Fri, 2 Aug 2002 10:49:40 +0000 Subject: [PATCH] Added support for HTTP Last-Modified and If-Modified-Since headers and 304 Not Modified response. --- src/helma/framework/RequestBean.java | 13 +++++++++ src/helma/framework/RequestTrans.java | 18 ++++++++++-- src/helma/framework/ResponseBean.java | 20 ++++++++++++++ src/helma/framework/ResponseTrans.java | 29 ++++++++++++++++++++ src/helma/servlet/AbstractServletClient.java | 25 +++++++++-------- 5 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/helma/framework/RequestBean.java b/src/helma/framework/RequestBean.java index c57f62b6..41876fc0 100644 --- a/src/helma/framework/RequestBean.java +++ b/src/helma/framework/RequestBean.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Map; import helma.framework.core.Application; +import java.util.Date; public class RequestBean implements Serializable { @@ -55,6 +56,18 @@ public class RequestBean implements Serializable { return req.getUsername (); } + public Date getLastModified () { + long since = req.getIfModifiedSince (); + if (since < 0) + return null; + else + return new Date (since); + } + + 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."); + } } diff --git a/src/helma/framework/RequestTrans.java b/src/helma/framework/RequestTrans.java index 16c8a212..6b27214f 100644 --- a/src/helma/framework/RequestTrans.java +++ b/src/helma/framework/RequestTrans.java @@ -24,6 +24,10 @@ public class RequestTrans implements Externalizable { // the request method - 0 for GET, 1 for POST private byte httpMethod = 0; + // timestamp of client-cached version, if present in request + private long ifModifiedSince = -1; + + // this is used to hold the EcmaScript form data object public transient Object data; // when was execution started on this request? @@ -32,8 +36,8 @@ public class RequestTrans implements Externalizable { // the name of the action being invoked public transient String action; - private transient String httpUsername; - private transient String httpPassword; + private transient String httpUsername; + private transient String httpPassword; static final long serialVersionUID = 5398880083482000580L; @@ -125,6 +129,7 @@ public class RequestTrans implements Externalizable { session = s.readUTF (); values = (Map) s.readObject (); httpMethod = s.readByte (); + ifModifiedSince = s.readLong (); } /** @@ -135,6 +140,15 @@ public class RequestTrans implements Externalizable { s.writeUTF (session); s.writeObject (values); s.writeByte (httpMethod); + s.writeLong (ifModifiedSince); + } + + public void setIfModifiedSince (long since) { + ifModifiedSince = since; + } + + public long getIfModifiedSince () { + return ifModifiedSince; } public String getUsername() { diff --git a/src/helma/framework/ResponseBean.java b/src/helma/framework/ResponseBean.java index 69c937b1..7b1a1996 100644 --- a/src/helma/framework/ResponseBean.java +++ b/src/helma/framework/ResponseBean.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Map; import helma.framework.core.Application; +import java.util.Date; public class ResponseBean implements Serializable { @@ -92,6 +93,13 @@ 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 (); } @@ -131,6 +139,18 @@ 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 + return null; + } + + public void notModified () throws RedirectException { + res.setNotModified (true); + } } diff --git a/src/helma/framework/ResponseTrans.java b/src/helma/framework/ResponseTrans.java index 1aa4fc60..e683b665 100644 --- a/src/helma/framework/ResponseTrans.java +++ b/src/helma/framework/ResponseTrans.java @@ -49,6 +49,12 @@ public final class ResponseTrans implements Externalizable { // contains the redirect URL private String redir = null; + + // the last-modified date, if it should be set in the response + private long lastModified = -1; + // flag to signal that resource has not been modified + private boolean notModified = false; + // cookies String cookieKeys[]; @@ -120,6 +126,7 @@ public final class ResponseTrans implements Externalizable { skin = null; title = head = body = message = error = null; values.clear (); + lastModified = -1; } @@ -327,6 +334,24 @@ public final class ResponseTrans implements Externalizable { return contentType; } + public void setLastModified (long modified) { + lastModified = modified; + } + + public long getLastModified () { + return lastModified; + } + + public void setNotModified (boolean notmod) throws RedirectException { + notModified = notmod; + if (notmod) + throw new RedirectException (null); + } + + public boolean getNotModified () { + return notModified; + } + public void setSkinpath (Object[] arr) { this.skinpath = arr; skincache = null; @@ -408,6 +433,8 @@ public final class ResponseTrans implements Externalizable { cache = s.readBoolean (); status = s.readInt (); realm = (String) s.readObject (); + lastModified = s.readLong (); + notModified = s.readBoolean (); } public void writeExternal (ObjectOutput s) throws IOException { @@ -421,6 +448,8 @@ public final class ResponseTrans implements Externalizable { s.writeBoolean (cache); s.writeInt (status); s.writeObject (realm); + s.writeLong (lastModified); + s.writeBoolean (notModified); } } diff --git a/src/helma/servlet/AbstractServletClient.java b/src/helma/servlet/AbstractServletClient.java index 3a45fbb3..7e4a6ac4 100644 --- a/src/helma/servlet/AbstractServletClient.java +++ b/src/helma/servlet/AbstractServletClient.java @@ -169,6 +169,12 @@ public abstract class AbstractServletClient extends HttpServlet { if (referer != null) reqtrans.set ("http_referer", referer); + try { + long ifModifiedSince = request.getDateHeader ("If-Modified-Since"); + if (ifModifiedSince > -1) + reqtrans.setIfModifiedSince (ifModifiedSince); + } catch (IllegalArgumentException ignore) {} + String remotehost = request.getRemoteAddr (); if (remotehost != null) reqtrans.set ("http_remotehost", remotehost); @@ -226,7 +232,8 @@ public abstract class AbstractServletClient extends HttpServlet { try { res.sendRedirect(trans.getRedirect ()); } catch(Exception io_e) {} - + } else if (trans.getNotModified ()) { + res.setStatus (HttpServletResponse.SC_NOT_MODIFIED); } else { if (!trans.cache || ! caching) { @@ -240,6 +247,10 @@ public abstract class AbstractServletClient extends HttpServlet { res.setHeader( "WWW-Authenticate", "Basic realm=\"" + trans.realm + "\"" ); if (trans.status > 0) res.setStatus (trans.status); + // set last-modified header to now + long modified = trans.getLastModified (); + if (modified > -1) + res.setDateHeader ("Last-Modified", System.currentTimeMillis ()); // if we don't know which charset to use for parsing HTTP params, // take the one from the response. This usually works because // browsers send parrameters in the same encoding as the page @@ -254,19 +265,11 @@ public abstract class AbstractServletClient extends HttpServlet { out.write (trans.getContent ()); out.close (); } catch(Exception io_e) { - System.err.println ("Exception in writeResponse: "+io_e); + log ("Exception in writeResponse: "+io_e); } } } - - private void redirectResponse (HttpServletRequest request, HttpServletResponse res, ResponseTrans trans, String url) { - try { - res.sendRedirect(url); - } catch (Exception e) { - System.err.println ("Exception at redirect: " + e + e.getMessage()); - } - } - + public FileUpload getUpload (HttpServletRequest request) throws Exception { int contentLength = request.getContentLength ();