Prevent double encoding

I am trying to accept a header named 'token' and convert it to a queryParam named 'token'.

The header values have already been url-encoded, so for example, a "+" has been converted to '%2B".

I'm using the AssignMessage policy to convert the header into a queryparam and then remove the header like this:

<Set>
        <QueryParams>
            <QueryParam name="token">{request.header.token}</QueryParam>            
        </QueryParams>
</Set>
<Remove>
        <Headers>
            <Header name="token"/>
        </Headers>
</Remove>

When Apigee sends the request to the backend, it is URL encoding the queryparam again, so '%2B' is getting changed to "%252B", so then the backend says it is not a valid token.

Is there a way to specify that the param is already encoded so it doesn't double-encode it?

Solved Solved
0 4 2,535
1 ACCEPTED SOLUTION

If the other answer is not your case, maybe decode the incoming url-encoded header and then use that value in Setting QueryParam, so even if it url-encodes again your backend server will not give an error.

Use JS Policy,

 var token = context.getVariable("request.header.token");
 decodedToken = decodeURIComponent(token);
 context.setVariable("decodedToken", decodedToken);

View solution in original post

4 REPLIES 4

I have tried a similar example and it is working fine, not sure if I understood your query.

I am using http://httpbin.org/anything

 <Set>
        <QueryParams>
            <QueryParam name="token">{request.header.token}</QueryParam>
        </QueryParams>
        <Headers>
            <Header name="token22222">{request.header.token}</Header>
        </Headers>
</Set>
<Remove>
        <Headers>
            <Header name="token"/>
        </Headers>
</Remove>

Try this URL https://onlineman477-eval-test.apigee.net/anything

with a token header = a%2Bb

{
    "args": {
        "token": "a%2Bb" <!----------- added queryparam------------>
    },
    "data": "",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-US,en;q=0.9",
        "Cache-Control": "no-cache",
        "Host": "httpbin.org",
        "Postman-Token": "a09f5d0a-944f-1a72-38c7-b11ccc430926",
        "Token22222": "a%2Bb",   <!----------- added header ------------>
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
    },
    "json": null,
    "method": "GET",
    "origin": "192.8.229.10, 104.154.179.1, 192.8.229.10",
    "url": "https://httpbin.org/anything?token=a%252Bb"
}

8228-apigee-encoding.png

Thank you for taking the time to work on this! In your JSON response above, the last field 'url' shows '?token=a%252Bb'. This has been double-encoded, as it changed '%2B' into '%252B'.

When the backend receives the request, this is what they receive. I'm guessing httpbin.org is decoding the url before putting the value into the json response in 'args'.

8237-2019-02-26-07-49-04-prevent-double-encoding.png

Oh yeah, I completely missed it. Thanks for pointing it out.

If the other answer is not your case, maybe decode the incoming url-encoded header and then use that value in Setting QueryParam, so even if it url-encodes again your backend server will not give an error.

Use JS Policy,

 var token = context.getVariable("request.header.token");
 decodedToken = decodeURIComponent(token);
 context.setVariable("decodedToken", decodedToken);