Query parameters showing in URL on initial page access

Splash Forums PrettyFaces Users Query parameters showing in URL on initial page access

Tagged: 

This topic contains 22 replies, has 3 voices, and was last updated by  clemmonsm 5 years, 5 months ago.

Viewing 15 posts - 1 through 15 (of 23 total)
  • Author
    Posts
  • #18213

    clemmonsm
    Participant

    Gentlemen,

    I hope all is well. I recently noticed behavior with my Pretty URLs for which I would like to seek your input. When I am navigating within my app, all of my Pretty URLs work beautifully. However, if I begin my session by typing in or pasting a Pretty URL, the query parameters for that URL show.

    For example, when I navigate to the city page using a pretty link, the following URL is accessed:

    /new-homes/ohio/cincinnati/

    <url-mapping id="city">
    <pattern value="/new-homes/#{state:bean.state}/#{city:bean.city}/">
    <validate index="0" validator="#{bean.validateStateCityCombo}" onError="pretty:error" />
    </pattern>
    <view-id value="/faces/pages/city.jspx" />
    </url-mapping>

    However, when I type in the above URL or access it from a bookmark, the following occurs:

    /new-homes/ohio/cincinnati/?state=ohio&city=cincinnati

    When I click a pretty link on the city page, the subsequent URL is back to normal, no params in the URL.

    I am on a snapshot of v3.3.3.

    Thanks for reading!

    #22237

    Hi,

    you write that if you manually enter an URL like /new-homes/ohio/cincinnati/ into the browser bar you end up with additional query parameters in the URL. It would be interesting to know where these parameters are coming from. Do you get an redirect when the page is first accessed using /new-homes/ohio/cincinnati/? You could check this with Firebug or some similar tool.

    Christian

    #22238

    clemmonsm
    Participant

    I believe I am getting a redirect. In Firebug > Net > HTML, the Referer for “/new-homes/ohio/cincinnati/?state=ohio&city=cincinnati” is “/new-homes/ohio/cincinnati/”.

    #22239

    Check the “Network” tab. You will see what the server response for each requests there. Perhaps you could upload a screenshot of this tab somewhere? Or attach it to this post?

    #22240

    clemmonsm
    Participant

    Here are the screenshots. The first is when params are not in the URL. The second set is for when one enters the web app on the given page and params appear. You’ll notice the second example has a 302 and a 200 b/c of a redirect.

    #1 (No Params)

    URL: /new-homes/ohio/cincinnati/find/communities/crosspointe/commons_of_crosspointe_condos/tour/?_adf.ctrl-state=dlai9yv7l_105&_afrLoop=27438524375185562

    200 – http://bit.ly/A7S5Ys

    #2 (Params)

    URL – /new-homes/ohio/cincinnati/find/communities/crosspointe/commons_of_crosspointe_condos/tour/?_afrLoop=27437758768487145&state=ohio&neighborhood=commons_of_crosspointe_condos&community=crosspointe&city=cincinnati&_afrWindowMode=0&_adf.ctrl-state=dlai9yv7l_105

    302 – http://bit.ly/zDuvAd

    200 – http://bit.ly/A8M8Y2

    #22241

    Hmmm. This is really a very wired issue. I don’t see a reason for this redirect to happen. Do you have any rewrite rules in your pretty-config.xml? Perhaps this redirect is automatically created by ADF to add the query parameters?

    Perhaps you could add a breakpoint for calls to HttpServletResponse.sendRedirect(). This could help to identify the origin of the redirect.

    #22242

    clemmonsm
    Participant

    Did a bit of debugging in my PF processor. I think you are right – ADF must be appending the params. Below is my config and PF processing. Below that are the debugging results from breaking on the return statements in the processor methods.

    pretty-config.xml rewrite rules:

    <!-- inbound rewrite rules: process inbound urls w/o "?" or "."; append trailing slash, set url to lowercase -->
    <rewrite outbound="false" match="^[^?.]*$" toCase="lowercase" trailingSlash="append" redirect="301" />

    <!-- outbound rewrite rules: process outbound urls that have a specific pattern via PrettyFacesAdfProcessor -->
    <rewrite inbound="false" match=".*(^/$|/about/|/finance/|/build-on-your-lot/|/new-homes/|/request-info/|/career/)+.*" processor="siteUtils.PrettyFacesAdfProcessor" redirect="301" />

    PrettyFacesAdfProcessor logic:

    public class PrettyFacesAdfProcessor implements Processor {

    public String processInbound(final HttpServletRequest request, final HttpServletResponse response, final RewriteRule rewrite, final String url) {

    return url;
    }

    public String processOutbound(final HttpServletRequest request, final HttpServletResponse response, final RewriteRule rewrite, final String url) {

    if (request.getParameterValues("_adf.ctrl-state") != null && !url.contains("_adf.ctrl-state")) {
    // param exists and is not assigned to url, so append _adf.ctrl-state key/value to query string
    String newUrl = url + "?_adf.ctrl-state=" + request.getParameterValues("_adf.ctrl-state")[0];
    return newUrl;
    }

    return url;
    }
    }

    Results:

    1) processInbound – no params on URL

    2) processInbound – ADF params on URL

    3) processOutbound – ADF & Query params on URL

    4) processOutbound – ADF & Query params on URL

    5) processInbound – ADF & Query params on URL

    6) processOutbound – ADF & Query params on URL

    7) processOutbound – ADF & Query params on URL

    …other outbound URL writing begins…

    You mentioned breaking on calls to HttpServletResponse.sendRedirect(), however I don’t explicitly call that method in my code.

    So, based on this, do you think I should modify my processor to remove these params?

    #22243

    What about your first rewrite rule? For me it looks like this one could cause the redirect. Possible?

    My idea was to break on HttpServletResponse.sendRedirect() because I’m not sure PrettyFaces is causing this redirect. In this way you could find out who is sending it and why.

    #22244

    Note, just a side about your first rewrite rule, you say URL’s that don’t contain '?' or '.', but your regex: ^[^?.]*$ actually prevents '?', '', and '.', because you are in the character class '[...]' the '.' doesn’t need escaping.

    #22245

    clemmonsm
    Participant

    @Christian – The first rewrite rule does not appear to be causing the redirect. When the rewrite rule is removed, behavior remains the same. I was wrong when I earlier wrote I did not explicitly call sendRedirect(). I do call it once in my prettyFacesRedirect method:

    public void prettyFacesRedirect(String mappingId, Object[] params) {
    try {

    // PrettyFaces redirect
    HttpServletRequest request =
    (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
    HttpServletResponse response =
    (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
    PrettyContext context = PrettyContext.getCurrentInstance(request);
    PrettyURLBuilder builder = new PrettyURLBuilder();

    // set PrettyFaces url-mapping id
    UrlMapping mapping = context.getConfig().getMappingById(mappingId);

    // IMPORTANT!!! Persist the _adf.ctrl-state parameter across requests so ADF session is not broken.
    String targetURL =
    context.getContextPath() + builder.build(mapping, true, params) +
    "?_adf.ctrl-state=" + request.getParameterValues("_adf.ctrl-state")[0];

    targetURL = response.encodeRedirectURL(targetURL);
    response.sendRedirect(targetURL);
    FacesContext.getCurrentInstance().responseComplete();

    } catch (IOException e) {
    e.printStackTrace(); // Can't redirect
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    …but this method only fires when a non-pretty command link is required, so it does not help pinpoint the origin of the redirect. I do believe that ADF is again the culprit. When I add the following inbound rule:

    <rewrite outbound="false" match=".*(^/$|/about-drees/|/finance/|/build-on-your-lot/|/new-homes/|/request-info/|/career/)+.*(?)" processor="siteUtils.PrettyFacesAdfProcessor" redirect="301" />

    I can capture the inbound and then I can do the following to wipe the params and add back only the ADF params:

    public String processInbound(final HttpServletRequest request, final HttpServletResponse response, final RewriteRule rewrite, final String url) {

    // we have a URL with query params

    if (request.getParameterValues("_adf.ctrl-state") != null && url.contains("_adf.ctrl-state")) {
    // we have access to _adf.ctrl-state & query string includes _adf.ctrl-state, so we can begin rewriting the inbound
    String newUrl = url.replaceAll("\?(.*)",""); // remove query string

    newUrl = newUrl + "?_adf.ctrl-state=" + request.getParameterValues("_adf.ctrl-state")[0]; // add _adf.ctrl-state back

    // add other required ADF params back

    if (request.getParameterValues("_afrLoop") != null) {
    newUrl = newUrl + "&_afrLoop=" + request.getParameterValues("_afrLoop")[0];
    }

    if (request.getParameterValues("_afrWindowMode") != null) {
    newUrl = newUrl + "&_afrWindowMode=" + request.getParameterValues("_afrWindowMode")[0];
    }

    if (request.getParameterValues("_afrWindowId") != null) {
    newUrl = newUrl + "&_afrWindowId=" + request.getParameterValues("_afrWindowId")[0];
    }

    return newUrl;
    }

    return url;
    }

    …this eliminates the params from the string on the initial request into the app. The problem with this is that my rewrite rule captures all inbound nav requests, including those fired from commandLinks. In these inbound requests, the “url” passed into processInbound is the POST URL (i.e. the page the user is on) and not the GET URL, so the current page ends up reloading. I think I’m on the right track, but I need to find a way to allow commandLink processing to avoid going through the processor I believe. What do you think? Am I on the right track here?

    [EDIT – ADDED] Interestingly, all of my commandLink actions call prettyFacesRedirect, the code that contains HttpServletResponse.sendRedirect(). With the above changes, this method is never called, so the sendRedirect() never fires.

    @lincoln – Thanks for the note on the regex. You are correct, the ‘.’ does not need escaping. However, it does not appear to prevent ” (at least when testing via RegExr). That said, I really only need to prevent ‘?’ and changing to ^[^?]*$ achieves this.

    #22246

    @clemmonsm: It’s a really complex problem you are having. It’s difficult for me to think about what’s going wrong without actually having access to the code.

    Just one minor comment. You wrote that your processor sees the JSF URLs instead of the mapped pretty URLs. In this case you could use the PrettyContext to get the original URL like this:

    PrettyContext.getCurrentInstance(request).getRequestURL().toURL();

    I hope this helps.

    Christian

    #22247

    clemmonsm
    Participant

    Alright, I think I figured this out, so here it is for other ADF developers…

    Much like the solution I penned for outbound links, found at the URL below, I got this working by appending the params back onto the URL, this time for inbounds:

    PrettyFaces Processor and Rewrite rules for ADF developers

    The trick was twofold:

    1) Only process on the inbound call when the “_adf.ctrl-state” token is present. This ensures we are reapplying the correct “_afrLoop” token value, which can change between the first and second inbound calls.

    2) Add the ADF params back to the URL in the same order they were in before removing the unwanted params. ADF must be expecting a defined order – when I added the params back with “_adf.ctrl-state” as the first param, the page would not load correctly.

    Here is the rewrite rule:

    <!-- inbound rewrite rule to process inbound urls that have query parameters -->
    <rewrite outbound="false" match=".*(^/$|/about-drees/|/finance/|/build-on-your-lot/|/new-homes/|/request-info/|/career/)+.*(?)" processor="siteUtils.PrettyFacesAdfProcessor" redirect="301" />

    Here is the inbound processor code:

    public String processInbound(final HttpServletRequest request, final HttpServletResponse response, final RewriteRule rewrite, final String url) {

    // we have a URL with query params

    if (request.getParameterValues("_adf.ctrl-state") != null && url.contains("_adf.ctrl-state")) {
    // we have access to _adf.ctrl-state & query string includes _adf.ctrl-state, so we can begin rewriting the inbound
    String newUrl = url.replaceAll("\?(.*)", ""); // remove query string
    String params = "";

    // add other required ADF params back, in order
    if (request.getParameterValues("_afrWindowId") != null) {
    params = "?_afrWindowId=" + request.getParameterValues("_afrWindowId")[0];
    }

    if (request.getParameterValues("_afrLoop") != null) {
    params = params + (params.length() == 0 ? "?_afrLoop=" : "&_afrLoop=") + request.getParameterValues("_afrLoop")[0];
    }

    if (request.getParameterValues("_afrWindowMode") != null) {
    params = params + (params.length() == 0 ? "?_afrWindowMode=" : "&_afrWindowMode=") + request.getParameterValues("_afrWindowMode")[0];
    }

    newUrl = newUrl + params + (params.length() == 0 ? "?_adf.ctrl-state=" : "&_adf.ctrl-state=") + request.getParameterValues("_adf.ctrl-state")[0]; // add _adf.ctrl-state back

    return newUrl;
    }

    return url;
    }

    Thanks for the help guys!

    #22248

    Thanks for sharing this with the community. I’m sure this will help others too.

    #22249

    Yea! This is great! Actually, Christian, I think we should keep this in mind for Rewrite – we could probably get some help from the ADF guys on this.

    rewrite-integration-adf

    To encapsulate this for future users.

    #22250

    clemmonsm, is that something you might be intersted to do? this way anyone who uses ADF with future versions of prettyfaces would not have to struggle like you did!

    https://github.com/ocpsoft/rewrite/issues/15

    PS. What you did is very difficult! I think it would be great to share :) could even put up a blog post about what you’ve done~!

    ~Lincoln

Viewing 15 posts - 1 through 15 (of 23 total)

You must be logged in to reply to this topic.

Comments are closed.