Get view-id from arbitrary pretty-url

Splash Forums Rewrite Users Get view-id from arbitrary pretty-url

This topic contains 12 replies, has 3 voices, and was last updated by  djmj 2 years, 11 months ago.

Viewing 13 posts - 1 through 13 (of 13 total)
  • Author
    Posts
  • #24687

    djmj
    Participant

    How can the original context url (view-id + params) be retrieved from a given pretty-url and vice versa?

    pretty-url –> url
    url –> pretty-url

    I need to create a basic jsf-converter for this case.

    Use case:
    I am passing a pretty-url obtained via view-param to realize a “back-button” on the target site which is not working anymore since using pretty-faces.

    • This topic was modified 2 years, 11 months ago by  djmj.
    #24689

    Hey there,

    Sorry for the slow response. I believe this is what you are looking for:

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

    To get “URL” you have to use:

    request.getAttribute("javax.servlet.forward.request_uri")
    The Servlet 3.1 spec says:

    The following request attributes must be set:
    
    javax.servlet.forward.request_uri
    javax.servlet.forward.context_path
    javax.servlet.forward.servlet_path
    javax.servlet.forward.path_info
    javax.servlet.forward.query_string

    However, if you want the back button to work, make sure that all of your JSF navigation uses ?faces-redirect=true – then the browser’s back button will work normally without the need for enhancement.

    #24690

    djmj
    Participant

    The support is free and you have other things to do so I am always thankfull,

    but your solution is for the current request, I am asking for a use case with an arbitrary pretty-url.

    Following mappings:

    /login -> /user/login.xhtml
    /main -> /main.xhtml

    Url:

    Pretty-url in browser bar: /login?from=/main?param1=value1

    <o:viewParam name="from" value="#{bean.from}" converter="package.converter.RewriteUrlConverter"/>

    I programmatically want to retrieve the view-id including query-params of /main?param1=value1 within the converter.

    For the example this results to: /main.xhtml?param1=value1

    • This reply was modified 2 years, 11 months ago by  djmj.
    #24692

    Then, I’m not sure I understand. What does this have to do with the browser URL bar if you want to convert an arbitrary pretty URL to its target viewId?

    #24694

    djmj
    Participant

    Nothing, it was just an example. Sorry if i confused you.

    Just programatically any arbitrary pretty-url.

    #24699

    You could try the PrettyURLBuilder class, in combination with PrettyContext.getCurrentInstance().getConfig().

    Otherwise, I’m not exactly sure why you want to do this. Why do you need the view-id?

    #24705

    djmj
    Participant

    I added rewrite-servlet-2.0.5.Final.jar to use rewrite but those two classes are not available.

    It is a basic redirect pattern. After login or other operation user gets redirected to previous page.

    <o:viewParam name="from" value="#{bean.from}" converter="package.converter.RewriteUrlConverter"/>

    Furthermore a button for back navigation should be placed on the site:

    <h:link value="Go back to previous page" outcome="#{bean.from}/> <– does not works with rewritten url needs view-id

    #24712

    Ah, I see. I thought you were using PrettyFaces – With Rewrite you have a few options, but the one I’d recommend is something like this:

    First you’ll need to add the JSF integration module: rewrite-integration-faces

    If you to return to previous page, you could record it (create a bean that records the current page (and last page)). Then navigate to the last page stored in that bean.

    .addRule()
    .when(Direction.isInbound().and(DispatchType.isRequest()))
    .perform(PhaseOperation.enqueue(new HttpOperation() {
       public void perform(HttpServletRewrite event, EvaluationContext context) {
          event.getRequest().getSession().setAttribute("LAST_PAGE", event.getRequest().getSession().getAttribute("CURRENT_PAGE"))
          event.getRequest().getSession().setAttribute("CURRENT_PAGE", FacesContext.getCurrentInstance().getViewRoot().getViewId());
       }
    }.after(PhaseId.RESTORE_VIEW)))

    If you want to do the above in a more JSF neutral way, then you could do the same thing in a JSF PhaseListener where you could save the value in a bean, instead of directly in the session map. If you are using JSF 2.2, you might even be able to inject the bean directly into the PhaseListener.

    Once you’ve saved the last viewId, you can just reference that new variable in any page using EL:

    <h:link value="Go back to previous page" outcome="#{sessionScope.LAST_PAGE}" />

    #24728

    djmj
    Participant

    Oh I thought it was clear since we are in RewriteUsers. I should have used “clean-url” instead of “pretty-url” not to confuse anyone.

    Much thanks and your answer looks interesting, but…

    About Session scoped navigation history

    But i already had something like a history NavigationHandler and I do not want to store this info in the session.
    First the windowId is necessary to make it work perfectly (what happens if user opens multiple windows/tabs?) since session-scope is to wide, and not using jsf 2.2 at the moment I have no access to windowId.

    Furthermore lets keep it as stateless as possible by appending the last url as a query-param.

    Somewhere in the deep code of rewrite there must be a method that takes a mapped “clean-url” and generates depending on the rules and patterns in the config the desired internal “view-id/url”.

    I have two options:

    • I: Use this method I am not aware of right now.
    • II: Simply use plain html anchor (which could have other drawbacks, but for my case it is sufficient)
    #24746

    IMHO you should go with your second option, meaning you should use a plain anchor element. I don’t think there is a really easy way to translate a clean URL to a view-ID without executing a complete rewriting lifecycle. And I don’t see any reason why you should use h:link instead if you already have the “clean-URL”. Wouldn’t it be weird to use some complex code to calculate the view-id for a clean-URL just to be able to use h:link which internally reverses this process by translating the view-id back to the clean URL?

    BTW: I know this sounds silly, but you could also use JavaScript to go back in history. Something like history.back(); for example. If you are consistently using Rewrite and the POST-Redirect-GET pattern, this should work fine. That’s one of the nice benefits you are getting from Rewrite/PrettyFaces: The BACK-Button will work as expected. 🙂

    #24752

    djmj
    Participant

    Yeah you are right, second option is the one to go. But this functionality could be maybe useful for others…

    … and there is a reason not to use it:

    Generating a valid view-id from the view-param is some kind of validation, since the view-id must be valid for h:link, else a “bad” user could input “hack” anything he wants in the view-parameter that will be used as a src including javascriptcode!

    For my use case the threat is minimal but there could be other use-cases and for now i will use option II.

    ————————————————————————————————————

    Using history.back(); is also an alternative but each of those alternatives have drawbacks.
    If redirection takes place in a Filter is the url in the browsers history?, I do not know right now.
    It is not guaranteed and also more often not the case that it really is the last url in history. I prefer the most generic versions as always.

    Long story short, I would prefer a public method like this. I would even go so far that the faces implementation should be responsible of it since it is just the reverse of “getBookmarkableURL()”.

    #24770

    You are right. If you add the view-id of the previous view into a query parameter, an attacker could modify it. That’s why everything that is part of the URL has to be validated and/or escaped correctly when processing it.

    I don’t see much issues with using the JavaScript history API. Whenever you redirect the user (from a filter or any other place), the browser will request a new page and the old URL will be placed in the history. So both the back button and the reload button will work as expected. That’s one of the major benefits of using the Post-Redirect-Get pattern.

    If you think that an API is required to transform an mapped URL to the real view ID, please open an issue for that. I cannot tell you whether this is easy to implement at the moment. But if you open a ticket, we will definitely discuss this in one of our next developer meetings.

    #24777

    djmj
    Participant

    Thanks for your time and answers, will maybe open an feature request later.

Viewing 13 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic.

Comments are closed.