32

What is the best way to URL-encode a String representing URL path (not request parameter) with JSTL?

<c:url value="/user/${user.name}"/>

According to any documentation I find, this should take care of it. But it does not. It encodes parameters beautifully (<c:url value="/user/${user.name}"><c:param name="section" value="employment 4u so good"/></c:url>) but I'm not passing any parameters. How can I safely encode a simple URL, like above, without fear of what ${user.name} could be?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Josh Johnson
  • 10,729
  • 12
  • 60
  • 83

5 Answers5

55

The <c:url> does not encode the URI as specified in its value, but just URL request parameters which are specified by a nested <c:param>. The IBM article which you linked also doesn't tell otherwise. I think that you confused it with "URL rewriting" (which is in essence nothing more than appending the jsessionid whenever necessary). The <c:url> indeed does that as well when cookies are disabled.

To achieve your requirement, of URI-encoding the path parameters, best is to create a custom EL function which delegates to URLEncoder#encode() and alters the outcome conform URI rules.

<a href="/user/${util:encodeURI(user.name)}">view profile</a>

with

public static String encodeURI(String value) throws UnsupportedEncodingException {
    return URLEncoder.encode(value, "UTF-8")
        .replace("+", "%20")
        .replace("%21", "!")
        .replace("%27", "'")
        .replace("%28", "(")
        .replace("%29", ")")
        .replace("%7E", "~");
}

In the 2nd part of this answer you can find a basic kickoff example how to declare and register custom EL functions.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Thanks, Balus C. This is what I'm currently doing. I hoped there was something built in but if this is the best way then so be it. – Josh Johnson Feb 21 '11 at 16:32
  • 16
    Curiously enough URLEncoder.encode() is actually not the correct way to encode a URL. It is the correct way to encode a URL *parameter.* It changes spaces to + for example. The correct technique is new URI(null, url, null).toASCIIString(), which for example changes spaces to %20. – user207421 Aug 03 '11 at 00:40
  • 1
    The question in your final link seems to have been deleted and is only viewable by 10k+ users. – Brant Bobby Sep 11 '12 at 19:01
  • 1
    @Brant: it's mirrored at http://balusc.blogspot.com/2010/01/hidden-features-of-jspservlet.html. There's another example in this answer: http://stackoverflow.com/questions/6395621/how-to-call-a-static-method-in-jsp-el/6396886#6396886 – BalusC Sep 11 '12 at 19:03
  • Sadly I didn't find any library for encoding URL path segments, therefore easiest way is replace(). ... – Christian Strempfer Jul 05 '16 at 12:09
5

I'm sure you already knew this was an alternative solution, but I decided for my particular use the most elegant solution was to use a request attribute.

So in my servlet:

req.setAttribute("myUrl", URLEncoder.encode(myUrl, "UTF-8"));

and in my JSP:

"...${myUrl}"
J. Dimeo
  • 829
  • 8
  • 10
  • This is incorrect. See [EJP's comment](http://stackoverflow.com/questions/5053975/how-to-url-encode-a-string-with-jstl#comment8244110_5064758). – Christian Strempfer Jul 05 '16 at 10:36
1

you could use the jakarta String TagLib, which has a encodeUrl tag: http://jakarta.apache.org/taglibs/doc/string-doc/string-1.1.0/index.html#encodeUrl

Follow these steps to configure your web application with this tag library:

  1. Copy the tag library descriptor file to the /WEB-INF subdirectory of your web application.
  2. Copy the tag library JAR file to the /WEB-INF/lib subdirectory of your web application.
  3. Add a element to your web application deployment descriptor in /WEB-INF/web.xml as said in the above link

To use the tags from this library in your JSP pages, add the following directive at the top of each page:

below is the example of usage in jsp:

<a href="str:decodeUrl>${URL}</str:decodeUrl)"/>
aymeric
  • 3,877
  • 2
  • 28
  • 42
  • 13
    There's a big red warning box on top of all Jakarta taglib pages which says *"2010-04-14 - Jakarta Taglibs has been retired."* This isn't just for decoration. You shouldn't use it anymore. – BalusC Sep 14 '12 at 19:43
1

Keep it simple in this way:

<%= java.net.URLEncoder.encode(request.getAttribute("user.name").toString() , "UTF-8") %>
Daniel De León
  • 13,196
  • 5
  • 87
  • 72
0

The correct technique is new URI(null, url, null).toASCIIString(), which for example changes spaces to %20

This could be helpful:

How to encode a String representing URL path with JSTL?

Jared Forth
  • 1,577
  • 6
  • 17
  • 32
AlexN
  • 29
  • 4