CFLOCATION encoding of URL

I’ve noticed that <cflocation /> under Lucee 5 (I think all versions, but confirmed under 5.3.8.206 and 5.3.9.61-SNAPSHOT), that it appears to automatically encode parameters, but not always.

For example, the following will end up encoding the x variable twice:

<cfset x = "hello world" />
<cflocation url="/index.cfm?#(len(x) ? '&x=' & encodeForUrl(x) : '')#" />

However, if you build the URL outside of the <cflocation /> tag, then the x parameter is only encoded once:

<cfset x = "hello world" />
<cfset y = "/index.cfm?#(len(x) ? '&x=' & encodeForUrl(x) : '')#" />
<cflocation url="#y#" />

In ACF, you must manual encode parameters, so this is creating an incompatibility issue. We can go through all of our code and make sure that URLs are always built outside the <cflocation /> tag, but that does not seem like it should be necessary.

I know there are a few threads about <cflocation /> and encoding (Cflocation url encoding & CFLocation double-encoding values in strange combination), but neither cover this specific issue.

What is the expected behavior in Lucee?

I’ve always heard that ACF compatibility issues are considered bugs, so it would seem like the <cflocation /> tag should not doing any kind of automatically encoding. If Lucee sees this as a bug with ACF, then the encoding should at least be under an Admin setting so it can be toggled depending on whether ACF compatibility is required.

I need to work on fixing this in our code base, but want to know how I should fix it. Should I assume that a URL built outside the location tag will not automatically encode?

So I’m not sure what happened, but now I’m always seeing the URLs encoded, which makes sense because in looking at the code for the {{}} tag, it’s sending the URL to the lucee.commons.net.HTTPUti.encode() method:

The lucee.commons.net.HTTPUti.encode() looks like it always tries to encode the URL parameters, which IMO, is not correct. It’s definitely not compatible with ACF.

As a temporary step, I’ve implemented a Location.cfc custom tag that can be dropped into the lucee-server/context/library/tag folder. After restarting Lucee, this custom tag will replace the native tag. I wrote the tag using the exact same Java logic from the 5.3.9.x branch of code, the only difference is to encoding is disabled by default and to use the auto encoding, you need to add encode="true" to the tag.

You can read more in the Lucee issue (and download the code):
https://luceeserver.atlassian.net/browse/LDEV-2164?focusedCommentId=50300

1 Like

It seems really strange that there should be a difference in behavior based on where you’re building the string?! Because, ultimately, it’s the already-built string that is being passed into the Location tag. That’s some spooky behavior at a distance right there.

@bennadel

So I’m not sure what happened and where my confusion came in, but the example above that shows how encoding is handled differently is wrong. Those examples actually do the same thing.

However, I believe that urlEncodedFormat() and encodeForUrl() behave different. encodeForUrl() produces the + for encoded spaces, while urlEncodedFormat() produces %20 and I believe I saw that the encoding helper that Lucee uses will leave %20 alone. So I expect maybe I had tested with urlEncodedFormat() originally when I was seeing the difference in behavior.

Yes, one of the methods is definitely a bit more aggressive than the other one from what I remember. Though, I can’t remember which is which :laughing: