Wicket
  1. Wicket
  2. WICKET-3921

No HTTP response cache headers are set in Wicket Ajax redirects

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 1.4.17
    • Fix Version/s: 1.4.18, 1.5-RC6
    • Component/s: wicket
    • Labels:
      None

      Description

      Usually HTTP response cache headers are being set in AjaxRequestTarget for Ajax responses. But for redirects, the handling is done in WebResponse where no cache headers are being set, which could lead to some trouble.

        Activity

        Hide
        Martin Grigorov added a comment -

        Fixed!
        Thanks Timo!

        Show
        Martin Grigorov added a comment - Fixed! Thanks Timo!
        Hide
        Timo Weber added a comment -

        Hi Martin,

        yes, thanks. This looks good to me and will solve the problem for sure. I've appended a very simple repo case below. It's a bit tricky to catch the redirect response in Firebug, if I can be of any further help, please let me know.

        public class AjaxResponseHeadersPage extends WebPage {

        public AjaxResponseHeadersPage() {
        setOutputMarkupId(true);

        add(new AjaxFallbackLink("link1") {
        @Override
        public void onClick(AjaxRequestTarget target)

        { // adding the page to the target will produce a wicket ajax redirect // without any cache headers target.addComponent(getPage()); }

        });

        add(new AjaxFallbackLink("link2") {
        @Override
        public void onClick(AjaxRequestTarget target)

        { // this produces an ajax response with cache headers set properly target.addComponent(this); }

        }.setOutputMarkupId(true));
        }
        }

        and

        <?xml version="1.0" encoding="UTF-8"?>
        <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
        <body>
        <a wicket:id="link1" href="#">Ajax response (Redirect) without any cache headers.</a>
        <a wicket:id="link2" href="#">Ajax response with proper cache headers.</a>
        </body>
        </html>

        Show
        Timo Weber added a comment - Hi Martin, yes, thanks. This looks good to me and will solve the problem for sure. I've appended a very simple repo case below. It's a bit tricky to catch the redirect response in Firebug, if I can be of any further help, please let me know. public class AjaxResponseHeadersPage extends WebPage { public AjaxResponseHeadersPage() { setOutputMarkupId(true); add(new AjaxFallbackLink("link1") { @Override public void onClick(AjaxRequestTarget target) { // adding the page to the target will produce a wicket ajax redirect // without any cache headers target.addComponent(getPage()); } }); add(new AjaxFallbackLink("link2") { @Override public void onClick(AjaxRequestTarget target) { // this produces an ajax response with cache headers set properly target.addComponent(this); } }.setOutputMarkupId(true)); } } and <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"> <body> <a wicket:id="link1" href="#">Ajax response (Redirect) without any cache headers.</a> <a wicket:id="link2" href="#">Ajax response with proper cache headers.</a> </body> </html>
        Hide
        Martin Grigorov added a comment -

        Index: wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java
        ===================================================================
        — wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java (revision 1146974)
        +++ wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java (working copy)
        @@ -312,6 +312,9 @@
        // Set content type based on markup type for page
        setCharacterEncoding(encoding);
        setContentType("text/xml; charset=" + encoding);
        + setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
        + setHeader("Cache-Control", "no-cache, must-revalidate");
        + setHeader("Pragma", "no-cache");
        }

        Here is the possible fix.
        WebResponse#redirect() is called not only when AjaxRequestTarget.addComponent(Page) is used but also when setResponsePage() is used in Ajax request.

        The fix is similar for 1.5.

        Show
        Martin Grigorov added a comment - Index: wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java =================================================================== — wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java (revision 1146974) +++ wicket/src/main/java/org/apache/wicket/protocol/http/WebResponse.java (working copy) @@ -312,6 +312,9 @@ // Set content type based on markup type for page setCharacterEncoding(encoding); setContentType("text/xml; charset=" + encoding); + setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); + setHeader("Cache-Control", "no-cache, must-revalidate"); + setHeader("Pragma", "no-cache"); } Here is the possible fix. WebResponse#redirect() is called not only when AjaxRequestTarget.addComponent(Page) is used but also when setResponsePage() is used in Ajax request. The fix is similar for 1.5.
        Hide
        Martin Grigorov added a comment -

        Hi Timo,

        Does that mean that if we move the setting of cache related headers before the redirect in AjaxRequestTarget#respond(RequestCycle) the problem will be solved ?
        That's why I need failing case to verify that the fix works.

        Show
        Martin Grigorov added a comment - Hi Timo, Does that mean that if we move the setting of cache related headers before the redirect in AjaxRequestTarget#respond(RequestCycle) the problem will be solved ? That's why I need failing case to verify that the fix works.
        Hide
        Timo Weber added a comment -

        It's probably easier for me to give you an entry point.

        Method respond(:RequestCycle) in AjaxRequestTarget does part of the response handling. If the page itself hasn't been added to the request target, everything's fine. The cache headers will be set to make sure that the response won't be cached by the browser (line 570-572 in AjaxRequestTarget).

        But if the page has been added, the handling is done by WebResponse.redirect(String url). This ajax redirect isn't performed as an HTTP redirect (some 30x code) but with the code 200 and the content "<ajax-response><redirect><![CDATA[" + url + "]]></redirect></ajax-response>" that is being interpreted by wicket-ajax in the browser. This response doesn't get any cache headers. Because of that it may be cached by the browser. As the payload contains a stateful url, this constellation could very likely be troublesome in some situations leading to obscure errors.

        I'd suggest that - if you also think, that it is a bug - you set these cache headers in a more central place for all ajax responses, WebRequestCycle.onEndRequest() would be a possible solution. That's where we put our workaround for now.

        Regards, Timo

        Show
        Timo Weber added a comment - It's probably easier for me to give you an entry point. Method respond(:RequestCycle) in AjaxRequestTarget does part of the response handling. If the page itself hasn't been added to the request target, everything's fine. The cache headers will be set to make sure that the response won't be cached by the browser (line 570-572 in AjaxRequestTarget). But if the page has been added, the handling is done by WebResponse.redirect(String url). This ajax redirect isn't performed as an HTTP redirect (some 30x code) but with the code 200 and the content "<ajax-response><redirect><![CDATA [" + url + "] ]></redirect></ajax-response>" that is being interpreted by wicket-ajax in the browser. This response doesn't get any cache headers. Because of that it may be cached by the browser. As the payload contains a stateful url, this constellation could very likely be troublesome in some situations leading to obscure errors. I'd suggest that - if you also think, that it is a bug - you set these cache headers in a more central place for all ajax responses, WebRequestCycle.onEndRequest() would be a possible solution. That's where we put our workaround for now. Regards, Timo
        Hide
        Martin Grigorov added a comment -

        Can you provide quickstart application that shows the problem ?

        Show
        Martin Grigorov added a comment - Can you provide quickstart application that shows the problem ?

          People

          • Assignee:
            Martin Grigorov
            Reporter:
            Timo Weber
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development