I made changes against the 1.4 release that enable the cross-domain invocation of a RemoteService (following GWT coding guidelines, unit tested). A service can be invoked cross-domain by annotating the service class with "@gwt.RPCTransport ScriptTag". This makes it possible to put the host page on a different domain than the GWT application. Non-annotated RemoteServices fall back on the XHR transport (you can also explicitly annotate them with "@gwt.RPCTransport XHR").
> I made changes against the 1.4 release that enable the cross-domain
> invocation of a RemoteService (following GWT coding guidelines, unit
> tested). A service can be invoked cross-domain by annotating the service
> class with "@gwt.RPCTransport ScriptTag". This makes it possible to put the
> host page on a different domain than the GWT application. Non-annotated
> RemoteServices fall back on the XHR transport (you can also explicitly
> annotate them with "@gwt.RPCTransport XHR").
> How are you serializing the method arguments? Are you coding with
> base64? Complex objects are allowed?
It's basically GWT-RPC over script tags instead of XmlHttpRequest. The
GWT-RPC request is urlencoded and transmitted via an url parameter.
Since complex objects are supported by GWT-RPC, these are also
supported when the communication is done using script tags, the only
thing that changes is that the GWT-RPC payload is transported in a
different way.
I like this approach. I've another question: what about the URL 2KB
limitation? An exception is throwed if the payload is over 2KB?
A kind of protocol is needed to send big payloads to cross domain, to
divide the payload in 2KB segments, and manage cross domain sessions.
A quick solution would be compress the payload to gain some bytes.
I've developed a GWT based LZW compressor with ASCII input and base64
output. Please, take a look in this demo: http://www.juglar.org/tests/blackpill/CompressionTest.html
-- Andrés
On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote:
> > How are you serializing the method arguments? Are you coding with
> > base64? Complex objects are allowed?
> It's basically GWT-RPC over script tags instead of XmlHttpRequest. The
> GWT-RPC request is urlencoded and transmitted via an url parameter.
> Since complex objects are supported by GWT-RPC, these are also
> supported when the communication is done using script tags, the only
> thing that changes is that the GWT-RPC payload is transported in a
> different way.
BTW, the GWT serialization stream, allows to optimize the compresion
dividing the output stream in two compression streams: an stream for
numbers (with an initial dictionary for only 16 chars), and a stream
for string (with an initial a dictionary for 256 chars).
-- Andrés
On 16 ene, 11:13, "Andrés Testi" <andres.a.te...@gmail.com> wrote:
> I like this approach. I've another question: what about the URL 2KB
> limitation? An exception is throwed if the payload is over 2KB?
> A kind of protocol is needed to send big payloads to cross domain, to
> divide the payload in 2KB segments, and manage cross domain sessions.
> A quick solution would be compress the payload to gain some bytes.
> I've developed a GWT based LZW compressor with ASCII input and base64
> output. Please, take a look in this demo:http://www.juglar.org/tests/blackpill/CompressionTest.html
> -- Andrés
> On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote:
> > Hi Andrés,
> > > How are you serializing the method arguments? Are you coding with
> > > base64? Complex objects are allowed?
> > It's basically GWT-RPC over script tags instead of XmlHttpRequest. The
> > GWT-RPC request is urlencoded and transmitted via an url parameter.
> > Since complex objects are supported by GWT-RPC, these are also
> > supported when the communication is done using script tags, the only
> > thing that changes is that the GWT-RPC payload is transported in a
> > different way.
"RFC 2068 states: Servers should be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations may not properly support these lengths."
...and...
"The spec for URL length does not dictate a minimum or maximum URL length, but implementation varies by browser. On Windows: Opera supports ~4050 characters, IE 4.0+ supports exactly 2083 characters, Netscape 3 -> 4.78 support up to 8192 characters before causing errors on shut-down, and Netscape 6 supports ~2000 before causing errors on start-up.
So even if you set the limit to 2000 characters you still run the risk of failures due to lesser maximums on browsers that are not explicitly supported and proxy servers.
I like the idea a lot, I am just concerned about potential failures that I can't even test for. I don't even think there is a programmatic solution, and that we would need to rely on good documentation and possible compile-time warnings.
I would be interested on hearing about some testing results on this. Specifically, what happens when you exceed the threshold? Also, the info I provided is a bit old, it would be great to hear if newer browsers have different limitations.
> I like this approach. I've another question: what about the URL 2KB > limitation? An exception is throwed if the payload is over 2KB? > A kind of protocol is needed to send big payloads to cross domain, to > divide the payload in 2KB segments, and manage cross domain sessions. > A quick solution would be compress the payload to gain some bytes. > I've developed a GWT based LZW compressor with ASCII input and base64 > output. Please, take a look in this demo: http://www.juglar.org/tests/blackpill/CompressionTest.html
> -- Andrés
> On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote: > > Hi Andrés,
> > > How are you serializing the method arguments? Are you coding with > > > base64? Complex objects are allowed?
> > It's basically GWT-RPC over script tags instead of XmlHttpRequest. The > > GWT-RPC request is urlencoded and transmitted via an url parameter. > > Since complex objects are supported by GWT-RPC, these are also > > supported when the communication is done using script tags, the only > > thing that changes is that the GWT-RPC payload is transported in a > > different way.
On 16 ene, 11:25, "Robert Hanson" <iamroberthan...@gmail.com> wrote:
> I was about to bring up the same point. The limitation isn't 2K
> though, each browser has it's own maximum.
You're right. I was assuming the lesser maximum was the IE size,
because IE is the lesser capable browser :-P
> So even if you set the limit to 2000 characters you still run the risk
> of failures due to lesser maximums on browsers that are not explicitly
> supported and proxy servers.
Yes, and for this issue I'm talking about a "kind of protocol". Why
"protocol"? Well, because the maximum size is a combination between
browser maximum/proxy maximum/HTTP server maximum. The hypothetical
protocol I'm proposing, begins with a URL size test, to stablish the
maximum size allowed in the channel. Secondly, the segment size is
determined, and the payload is divided in a sequence of numbered
segments. But warning! A session is needed here, to associate the
severals segments with a unique client. And more warning! JSONP
requires non-cookie based session, then the session needs to be
managed explicitally by GWT. And what about if a segment is lost?
There is need of a timeslice?
If it walks like a protocol and quacks like a protocol, I would call
it a protocol. ;-)
On 16 jan, 15:24, "Andrés Testi" <andres.a.te...@gmail.com> wrote:
> BTW, the GWT serialization stream, allows to optimize the compresion
> dividing the output stream in two compression streams: an stream for
> numbers (with an initial dictionary for only 16 chars), and a stream
> for string (with an initial a dictionary for 256 chars).
I did not change the way the RPC request and response are built, I
assumed it already called the appropriate methods on the serialization
stream. So this is OK I guess?
About the URL length:
This is indeed a problem. And in the submitted patch there is no error
handling for it.
> I like the idea a lot, I am just concerned about potential failures
> that I can't even test for. I don't even think there is a
> programmatic solution, and that we would need to rely on good
> documentation and possible compile-time warnings.
Cross-domain communication is a problem I really needed a solution
for. The only known way (to me, I'm rather new to this) to solve this
is by dynamically adding script tags. Keeping this in mind you can do
the communication in 2 different ways:
1) by hand crafting the request by manually, adding the different
parameters and values (and writing the servlet code to parse these
parameters and returning a good response)
2) letting GWT build the request automatically (for example the way
this patch does it)
Both options suffer from the URL length limit. However with (1) you
are building the URL manually and because of that you are very well
aware of the possible URL length, but doing this for each service is a
lot of work. Option (2) lets you avoid the work, and if you want to
you can still fall back on option (1). I also assumed that the RPC
encoding had more potential for compressing the payload than the case
where URLs would be hand crafted.
The programmatic solution proposed by Andrés (the segmentation) looks
interesting, I'll have to think about this a bit more. It also looks
like a daunting task.
Good documentation would indeed be essential. Generating good and
useful compile time warnings looks also difficult because you probably
would have to generate a warning for each remote service that uses the
ScriptTag transport if its methods take non-primitive arguments.
One, somewhat ugly hack, is to perform the request using two requests. The first, use a cross-domain <form> submit to send the RPC arguments with a rendezvous id, the second, use a script tag with the ID to pick up the results. It incurs 2x HTTP requests, and extra server state tho.
I use script-tag RPC on Chronoscope too, because in widget deployment mode, I let people people embed the widget locally, but target an RPC font-metrics server we host. Luckuly, I know the RPC arguments are just primitives.
On Jan 16, 2008 6:25 AM, Robert Hanson <iamroberthan...@gmail.com> wrote:
> "RFC 2068 states: Servers should be cautious about depending on URI > lengths above 255 bytes, because some older client or proxy > implementations may not properly support these lengths."
> ...and...
> "The spec for URL length does not dictate a minimum or maximum URL > length, but implementation varies by browser. On Windows: Opera > supports ~4050 characters, IE 4.0+ supports exactly 2083 characters, > Netscape 3 -> 4.78 support up to 8192 characters before causing errors > on shut-down, and Netscape 6 supports ~2000 before causing errors on > start-up.
> So even if you set the limit to 2000 characters you still run the risk > of failures due to lesser maximums on browsers that are not explicitly > supported and proxy servers.
> I like the idea a lot, I am just concerned about potential failures > that I can't even test for. I don't even think there is a > programmatic solution, and that we would need to rely on good > documentation and possible compile-time warnings.
> I would be interested on hearing about some testing results on this. > Specifically, what happens when you exceed the threshold? Also, the > info I provided is a bit old, it would be great to hear if newer > browsers have different limitations.
> On Jan 16, 2008 9:13 AM, Andrés Testi <andres.a.te...@gmail.com> wrote:
> > I like this approach. I've another question: what about the URL 2KB > > limitation? An exception is throwed if the payload is over 2KB? > > A kind of protocol is needed to send big payloads to cross domain, to > > divide the payload in 2KB segments, and manage cross domain sessions. > > A quick solution would be compress the payload to gain some bytes. > > I've developed a GWT based LZW compressor with ASCII input and base64 > > output. Please, take a look in this demo: http://www.juglar.org/tests/blackpill/CompressionTest.html
> > -- Andrés
> > On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote: > > > Hi Andrés,
> > > > How are you serializing the method arguments? Are you coding with > > > > base64? Complex objects are allowed?
> > > It's basically GWT-RPC over script tags instead of XmlHttpRequest. The > > > GWT-RPC request is urlencoded and transmitted via an url parameter. > > > Since complex objects are supported by GWT-RPC, these are also > > > supported when the communication is done using script tags, the only > > > thing that changes is that the GWT-RPC payload is transported in a > > > different way.
> One, somewhat ugly hack, is to perform the request using two requests. > The first, use a cross-domain <form> submit to send the RPC arguments > with a rendezvous id, the second, use a script tag with the ID to pick > up the results. It incurs 2x HTTP requests, and extra server state > tho.
> I use script-tag RPC on Chronoscope too, because in widget deployment > mode, I let people people embed the widget locally, but target an RPC > font-metrics server we host. Luckuly, I know the RPC arguments are > just primitives.
> On Jan 16, 2008 6:25 AM, Robert Hanson <iamroberthan...@gmail.com> wrote:
> > I was about to bring up the same point. The limitation isn't 2K > > though, each browser has it's own maximum.
> > "RFC 2068 states: Servers should be cautious about depending on URI > > lengths above 255 bytes, because some older client or proxy > > implementations may not properly support these lengths."
> > ...and...
> > "The spec for URL length does not dictate a minimum or maximum URL > > length, but implementation varies by browser. On Windows: Opera > > supports ~4050 characters, IE 4.0+ supports exactly 2083 characters, > > Netscape 3 -> 4.78 support up to 8192 characters before causing errors > > on shut-down, and Netscape 6 supports ~2000 before causing errors on > > start-up.
> > So even if you set the limit to 2000 characters you still run the risk > > of failures due to lesser maximums on browsers that are not explicitly > > supported and proxy servers.
> > I like the idea a lot, I am just concerned about potential failures > > that I can't even test for. I don't even think there is a > > programmatic solution, and that we would need to rely on good > > documentation and possible compile-time warnings.
> > I would be interested on hearing about some testing results on this. > > Specifically, what happens when you exceed the threshold? Also, the > > info I provided is a bit old, it would be great to hear if newer > > browsers have different limitations.
> > On Jan 16, 2008 9:13 AM, Andrés Testi <andres.a.te...@gmail.com> wrote:
> > > I like this approach. I've another question: what about the URL 2KB > > > limitation? An exception is throwed if the payload is over 2KB? > > > A kind of protocol is needed to send big payloads to cross domain, to > > > divide the payload in 2KB segments, and manage cross domain sessions. > > > A quick solution would be compress the payload to gain some bytes. > > > I've developed a GWT based LZW compressor with ASCII input and base64 > > > output. Please, take a look in this demo: http://www.juglar.org/tests/blackpill/CompressionTest.html
> > > -- Andrés
> > > On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote: > > > > Hi Andrés,
> > > > > How are you serializing the method arguments? Are you coding with > > > > > base64? Complex objects are allowed?
> > > > It's basically GWT-RPC over script tags instead of XmlHttpRequest. The > > > > GWT-RPC request is urlencoded and transmitted via an url parameter. > > > > Since complex objects are supported by GWT-RPC, these are also > > > > supported when the communication is done using script tags, the only > > > > thing that changes is that the GWT-RPC payload is transported in a > > > > different way.
On 16 ene, 13:31, "Ray Cromwell" <cromwell...@gmail.com> wrote:
> One, somewhat ugly hack, is to perform the request using two requests.
> The first, use a cross-domain <form> submit to send the RPC arguments
> with a rendezvous id, the second, use a script tag with the ID to pick
> up the results. It incurs 2x HTTP requests, and extra server state
> tho.
Don't worry about hacks, AJAX programming is 60% based in hacks ;-)
I've seen a slightly modified version of that where you do two posts
within an <iframe>:
One post submits the RPC call to the remote server with a "return post
URL". The remote server then posts the data back to the return post
URL which is on the same domain. Because of this, it can access the
parent window's script.
The advantage to this method is that there are no size limits (beyond
POST limits) and no server state. The disadvantage is that you
require a dedicated server script in the same scripting domain as the
caller to convert the return POST into a JS callback.
On Jan 16, 9:31 am, "Ray Cromwell" <cromwell...@gmail.com> wrote:
> One, somewhat ugly hack, is to perform the request using two requests.
> The first, use a cross-domain <form> submit to send the RPC arguments
> with a rendezvous id, the second, use a script tag with the ID to pick
> up the results. It incurs 2x HTTP requests, and extra server state
> tho.
> I use script-tag RPC on Chronoscope too, because in widget deployment
> mode, I let people people embed the widget locally, but target an RPC
> font-metrics server we host. Luckuly, I know the RPC arguments are
> just primitives.
> On Jan 16, 2008 6:25 AM, Robert Hanson <iamroberthan...@gmail.com> wrote:
> > I was about to bring up the same point. The limitation isn't 2K
> > though, each browser has it's own maximum.
> > "RFC 2068 states: Servers should be cautious about depending on URI
> > lengths above 255 bytes, because some older client or proxy
> > implementations may not properly support these lengths."
> > ...and...
> > "The spec for URL length does not dictate a minimum or maximum URL
> > length, but implementation varies by browser. On Windows: Opera
> > supports ~4050 characters, IE 4.0+ supports exactly 2083 characters,
> > Netscape 3 -> 4.78 support up to 8192 characters before causing errors
> > on shut-down, and Netscape 6 supports ~2000 before causing errors on
> > start-up.
> > So even if you set the limit to 2000 characters you still run the risk
> > of failures due to lesser maximums on browsers that are not explicitly
> > supported and proxy servers.
> > I like the idea a lot, I am just concerned about potential failures
> > that I can't even test for. I don't even think there is a
> > programmatic solution, and that we would need to rely on good
> > documentation and possible compile-time warnings.
> > I would be interested on hearing about some testing results on this.
> > Specifically, what happens when you exceed the threshold? Also, the
> > info I provided is a bit old, it would be great to hear if newer
> > browsers have different limitations.
> > On Jan 16, 2008 9:13 AM, Andrés Testi <andres.a.te...@gmail.com> wrote:
> > > I like this approach. I've another question: what about the URL 2KB
> > > limitation? An exception is throwed if the payload is over 2KB?
> > > A kind of protocol is needed to send big payloads to cross domain, to
> > > divide the payload in 2KB segments, and manage cross domain sessions.
> > > A quick solution would be compress the payload to gain some bytes.
> > > I've developed a GWT based LZW compressor with ASCII input and base64
> > > output. Please, take a look in this demo:http://www.juglar.org/tests/blackpill/CompressionTest.html
> > > -- Andrés
> > > On 16 ene, 06:32, janick reynders <janick.reynd...@gmail.com> wrote:
> > > > Hi Andrés,
> > > > > How are you serializing the method arguments? Are you coding with
> > > > > base64? Complex objects are allowed?
> > > > It's basically GWT-RPC over script tags instead of XmlHttpRequest. The
> > > > GWT-RPC request is urlencoded and transmitted via an url parameter.
> > > > Since complex objects are supported by GWT-RPC, these are also
> > > > supported when the communication is done using script tags, the only
> > > > thing that changes is that the GWT-RPC payload is transported in a
> > > > different way.
On 16 jan, 17:31, "Ray Cromwell" <cromwell...@gmail.com> wrote:
> One, somewhat ugly hack, is to perform the request using two requests.
> The first, use across-domain<form> submit to send the RPC arguments
> with a rendezvous id, the second, use a script tag with the ID to pick
> up the results. It incurs 2x HTTP requests, and extra server state
> tho.
I didn't know cross-domain form submit was possible. Do we really need
the 2 requests? For example: what if the form submit uses an iframe as
target, and the response is something like:
<script>super.window.mycallback({"rpcResult": .... });</script>
I dunno if it will work because the domain of the IFRAME will be different than the domain of the main GWT app. I use a similar technique to do Google AuthSub in GWT. I send a popup window with IFRAME to Google's login screen, it redirects back to a servlet which renders a script tag which invokes a callback in the main GWT app which closes the popup and updates the UI with success/failure. However, the servlet which renders the <SCRIPT> is in the same domain as the GWT app.
-Ray
On Jan 21, 2008 12:31 AM, janick reynders <janick.reynd...@gmail.com> wrote:
> On 16 jan, 17:31, "Ray Cromwell" <cromwell...@gmail.com> wrote: > > One, somewhat ugly hack, is to perform the request using two requests. > > The first, use across-domain<form> submit to send the RPC arguments > > with a rendezvous id, the second, use a script tag with the ID to pick > > up the results. It incurs 2x HTTP requests, and extra server state > > tho.
> I didn't know cross-domain form submit was possible. Do we really need > the 2 requests? For example: what if the form submit uses an iframe as > target, and the response is something like: > <script>super.window.mycallback({"rpcResult": .... });</script>
will not work, if the domain of the IFRAME differs from that of the parent window. I had tried doing this before, and the Same-Origin Policy stopped me in my tracks.
Rajeev
On Jan 21, 2008 3:35 AM, Ray Cromwell <cromwell...@gmail.com> wrote:
> I dunno if it will work because the domain of the IFRAME will be > different than the domain of the main GWT app. I use a similar > technique to do Google AuthSub in GWT. I send a popup window with > IFRAME to Google's login screen, it redirects back to a servlet which > renders a script tag which invokes a callback in the main GWT app > which closes the popup and updates the UI with success/failure. > However, the servlet which renders the <SCRIPT> is in the same domain > as the GWT app.
> -Ray
> On Jan 21, 2008 12:31 AM, janick reynders <janick.reynd...@gmail.com> > wrote:
> > Hi Ray,
> > On 16 jan, 17:31, "Ray Cromwell" <cromwell...@gmail.com> wrote: > > > One, somewhat ugly hack, is to perform the request using two requests. > > > The first, use across-domain<form> submit to send the RPC arguments > > > with a rendezvous id, the second, use a script tag with the ID to pick > > > up the results. It incurs 2x HTTP requests, and extra server state > > > tho.
> > I didn't know cross-domain form submit was possible. Do we really need > > the 2 requests? For example: what if the form submit uses an iframe as > > target, and the response is something like: > > <script>super.window.mycallback({"rpcResult": .... });</script>
I've tried the patch and found a problem while decoding request.
Here is a part of the stack trace of exception i had:
2008-02-01 18:46:47,526 ERROR [org.apache.catalina.core.ContainerBase.
[jboss.web].[localhost].[/CustomerInfoPanel]] Exception while
dispatching incoming RPC call
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.extract (ServerSerializationStreamReader.java:
282)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.readInt (ServerSerializationStreamReader.java:
142)
at
com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.prepa reToRead(AbstractSerializationStreamReader.java:
38)
at
com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.prepare ToRead(ServerSerializationStreamReader.java:
97)
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:234)
at
com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServi ceServlet.java:
279)
at
com.google.gwt.user.server.rpc.RemoteServiceServlet.handleRPCRequest(Remote ServiceServlet.java:
495)
at
com.google.gwt.user.server.rpc.RemoteServiceServlet.doGet(RemoteServiceServ let.java:
209)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
As my investigation showed, the request had not been decoded properly
from UTF-8 and because of this could not be parsed by
ServerSerializationStreamReader.
Here is my change of
com.google.gwt.user.server.rpc.RemoteServiceServlet which corrects
this:
===================================================================
--- RemoteServiceServlet.java.bak Thu Jan 31 18:21:32 2008
+++ RemoteServiceServlet.java Fri Feb 01 23:15:56 2008
@@ -68,8 +68,17 @@
}
Unfortunately, I had to stop using this patch because of Opera's cache
problems: PRC responses are cached by Opera.
There is a work-around for this - we can add timestamp parameter to
request, may be I'll do it later.
On Mon, Feb 25, 2008 at 10:30 AM, pash7ka <pash...@gmail.com> wrote: > Unfortunately, I had to stop using this patch because of Opera's cache > problems: PRC responses are cached by Opera. > There is a work-around for this - we can add timestamp parameter to > request, may be I'll do it later.
Are you sure the web server was setting the cache headers properly on the script-tag RPC response? If Opera caches the response anyway, things are going to be horribly broken on Opera, not just for this.
No, I had not examined that headers. And I hadn't done any special configuration for this responses, just as I hadn't do it for XHR transport. But I've found Script-Tag transport working in IE & Firefox, and totally broken in Opera. I just have no time now to check for correct headers, sorry.
On Mon, Feb 25, 2008 at 11:10 AM, PashKa <pash...@gmail.com> wrote: > No, I had not examined that headers. And I hadn't done any special > configuration for this responses, just as I hadn't do it for XHR transport. > But I've found Script-Tag transport working in IE & Firefox, and totally > broken in Opera. > I just have no time now to check for correct headers, sorry.
Most browsers refuse to cache POST responses, but they do cache script GET reponses. So, if you want this to work properly, you need to have the server set the proper cache headers (in fact you need to in general to get the best performance). Otherwise, if you make the same RPC call with the same arguments it will get cached (and I found it to be the case on all browsers, not just Opera, although they may have different triggers for URLs that heuristically don't get cached).
Thanks! I've added function below and calls to it and it seems like the problem had been solved. ------- private static DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); protected void addNoCacheHeaders(){ HttpServletResponse responce = getThreadLocalResponse(); responce.addHeader("Cache-Control", "no-store"); responce.addHeader("Expires", df.format(new Date())); } -------
On Tue, Feb 26, 2008 at 8:16 AM, PashKa <pash...@gmail.com> wrote: > Thanks! I've added function below and calls to it and it seems like the > problem had been solved. > ------- > private static DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy > HH:mm:ss Z"); > protected void addNoCacheHeaders(){ > HttpServletResponse responce = getThreadLocalResponse(); > responce.addHeader("Cache-Control", "no-store"); > responce.addHeader("Expires", df.format(new Date())); > } > -------
We need to do a better job documenting the recommended best practice, but there are a couple of other things you should include:
- Cache-Control: private, no-cache (no-store just means any cache [such as an intervening proxy] can't store the response to disk, but it can still cache it) - Pragma: no-cache (old browsers/proxies) - You need proper Date and Last-Modified times as well or some browsers ignore the Expires (I don't know if those are set outside this code snippet, as they aren't really cache headers) - Any pre-expired Expires header is sufficient, so you don't need to set it to the current time (and in fact could be dangerous if the client's clock is wrong) - personally I use Fri, 2 Jan 1970 00:00:00 GMT.
I have also seen including a bogus Set-Cookie header for broken caches that ignore both Cache-Control and Pragma, but surely those have long since been replaced.