开发者

Encoding URL components with an ampersand &

Seems like a very simple question here:

I've got a program where someone is entering a string M&S in a form and running a query. I understand the & is a reserved character and therefore must be encoded. The problem is it seems to be requiring encoding twice in some contexts.

If the URL is used in a javascript onClick event, normal URL encoding seems to work fine (here the operator can click on a column header to sort):

<td onClick="AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%26S&sortmethod1=161')">

However, if the URL is used in an anchor (although the anchor actually uses AJAX), it seems to need encoding twice:

<a href="javascript:AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%2526S&sortmethod1=147')" title='Refresh'>Refresh</a>

Both of the examples above work fine. However they are hand-generated test cases. Unfortunately, in the application, when I'm actually generating the URL, I don't know how it's going to be used.

If I encode the URL parameter once (M%26S), it works fine in onCl开发者_运维问答ick. But used this way in the anchor, the server sees the URL as ...Qry147=M&S&sortmethod1=147... - so it must have been unencoded before being given back to the server.

If I encode it twice (M%2526S), the anchor works, but for the onClick, the server sees ...Qry147=M%2526S....

I get the feeling I'm missing something here. Is there a way to make this work the same in both cases?


If you construct the whole HTML text using simple steps, some of the difficulties will disappear. So, by taking your example, you want to encode the following query parameter:

M&S

When you embed this string as a query parameter in a URL, you have to urlencode it, as you already know. The urlencoded string is M%26S. The complete URL then looks like this:

http://10.0.0.195/program.exe?Qry147=M%26S&sortmethod1=147

Now this URL is embedded in JavaScript code, and in this case you only need single quotes at both ends:

'http://10.0.0.195/program.exe?Qry147=M%26S&sortmethod1=147'

The whole JavaScript code looks like this:

AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%2526S&sortmethod1=147')

Now this whole text is used in an HTML context that is interpreted as a URL, so you need to urlencode it again:

AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%2526S&sortmethod1=147')

And finally, since you are embedding this text in HTML, you need to htmlescape it:

AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%2526S&amp;sortmethod1=147')

That's why you end with:

<a href="javascript:AJAX_Get('http://10.0.0.195/program.exe?Qry147=M%2526S&amp;sortmethod1=147')" title='Refresh'>Refresh</a>

I usually avoid these encoding challenges by not putting the string M&S directly into the onclick event or the anchor. In general, you cannot encode the onclick event and the anchor in the same way, since the decoding process for both is different:

onclick: html -> js -> url
anchor: html -> url -> js -> url

But wait ... if you write a helper function like this, it works:

function myQuery(q) {
    var encodedQ = encodeURIComponent(q); // TODO: which character encoding is used here?
    var url = 'http://10.0.0.195/program.exe?Qry147=' + encodedQ + '&sortmethod1=147';
    var response = AJAX_Get(url);
    // TODO: handle errors
}

Now you can write:

<a href="javascript:myQuery('M&amp;S')">anchor</a>
<a onclick="myQuery('M&amp;S')">event</a>

This trick works because there is no % anymore in the anchor case.


I recommend storing the parameter in its unencoded form and then encoding at the time it is used, whether in the onClick event or the anchor.


I've been given a bit of a hack of a solution from elsewhere, but it's working fairly well.

Simply replacing:

<a href="javascript:AJAX_Get(...)">

with:

<a href="javascript:void(0);" onClick="AJAX_Get(...)">

The onClick action works identically on anchors and other elements. Obviously any bits of the application that have written their own HTML chunks may still have a problem, but it's a minor change to make this workaround in the core code, so I'm using this route for now.

EDIT : just spotted my answer here, and realised this solution caused more problems than it solved. I eventually made time to change it to work properly (so it uses the correct escaping method at the correct time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜