0

Redirecting using the following partial response (inside a Servlet filter). It is an attempt to redirect to a target resource, when a user successfully logs in.

private void redirect(HttpServletRequest request, HttpServletResponse response, String redirectURL) throws IOException {
    if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
        response.setContentType("text/xml");
        response.setCharacterEncoding("UTF-8");
        response.getWriter()
                .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
                .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", redirectURL);
    } else {
        response.sendRedirect(response.encodeRedirectURL(redirectURL));
    }
}

Request / response headers :

General

    Request URL:https://localhost:8443/ContextRoot/utility/Login
    Request Method:POST
    Status Code:302 Found
    Remote Address:127.0.0.1:8443

Response Headers

    Cache-Control:no-cache, no-store, must-revalidate
    Connection:keep-alive
    Content-Length:0
    Date:Thu, 17 Mar 2016 11:12:58 GMT
    Expires:Thu, 01 Jan 1970 00:00:00 GMT
    Location:https://localhost:8443/ContextRoot/admin/Home.xhtml
    Pragma:no-cache
    Server:WildFly/10
    X-Powered-By:Undertow/1

Request Headers

    Accept:application/xml, text/xml, */*; q=0.01
    Accept-Encoding:gzip, deflate
    Accept-Language:en-US,en;q=0.8
    Connection:keep-alive
    Content-Length:256
    Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    Cookie:JSESSIONID=0a-fKcNyfWx_Cu30m5fZUusrQ4g-qbHqhvojrNCU.om-f6b0ea3ad206; __utma=111872281.616526714.1454485589.1454485589.1454485589.1; __utmz=111872281.1454485589.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
    Faces-Request:partial/ajax
    Host:localhost:8443
    Origin:https://localhost:8443
    Referer:https://localhost:8443/ContextRoot/admin/RatingDetails?product=10&id=2
    User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
    X-Requested-With:XMLHttpRequest

Form Data

    view URL encoded
    javax.faces.partial.ajax:true
    javax.faces.source:login
    javax.faces.partial.execute:loginForm
    javax.faces.partial.render:loginForm
    login:login
    loginForm:loginForm
    userName:admin
    password:admin
    javax.faces.ViewState:-5804174403308424993:4075605247268615317

As can be seen, the response status code is "302 Found" but redirect to the target resource does not happen.

The culprit is & in the query-string :

https://localhost:8443/ContextRoot/admin/RatingDetails?product=10&id=2

The following with a single query-string parameter works just fine:

https://localhost:8443/ContextRoot/admin/RatingDetails?product=10

There is a parse error :

<partial-response>
    <parsererror style="display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black">
        <h3>This page contains the following errors:</h3>
        <div style="font-family:monospace;font-size:12px">error on line 1 at column 118: EntityRef: expecting ';'
        </div>
        <h3>Below is a rendering of the page up to the first error.</h3>
    </parsererror>
</partial-response>

response.encodeURL(redirectURL) or response.encodeRedirectURL(redirectURL) in this case does not help either.

Any suggestion?

Tiny
  • 27,221
  • 105
  • 339
  • 599

1 Answers1

1

error on line 1 at column 118: EntityRef: expecting ';'

The & is a special character in XML representing the start of an entity, which is supposed to end with the ; character, e.g. &lt;, &#xA0;, etc. This explains that part of the error message.

However, you're using that character as a query string parameter separator without any entity reference name and the end character ;. Hence, the XML parser will fall over it.

Escaping the & as &amp; should solve it. The redirect URL has to end up in this format:

https://localhost:8443/ContextRoot/admin/RatingDetails?product=10&amp;id=2

The encodeURL()/encodeRedirectURL() serves a different purpose which is explained in In the context of Java Servlet what is the difference between URL Rewriting and Forwarding?

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Those parameters are appended dynamically at run-time using ``, ``. Therefore, an `&` is automatically inserted between each key / value pair of parameters being passed in the query-string. Depending upon the number of parameters being passed, `&` may or may not be present. Does it require to manually escape `&` after grabbing the query-string from `redirectURL` in the Servlet filter? – Tiny Mar 17 '16 at 14:37
  • Where exactly does `redirectURL` come from? – BalusC Mar 17 '16 at 14:38
  • In one case : The URL is a fallback or return URL which itself is appended as a query-string parameter : (inside ``), `` and in another case : The URL is obtained via `context.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI)` and `context.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING)`. – Tiny Mar 17 '16 at 14:54
  • I assumed that I would have to do something like `redirectURL.replaceAll("&", "&")` anyway. – Tiny Mar 18 '16 at 15:33
  • It boils down to that, yes. – BalusC Mar 18 '16 at 15:39