0

In my RestResource, I need to validate the source of an incoming RestRequest. To do so, I need to create a hash using a concatenated string that includes the full request URL, including the query parameters. However, I don't see any property on the RestRequest that returns the full URL and the params property does not preserve the original order of the parameters.

Is there any way to get the original order of query parameters?

1 Answer 1

3

There's something called the "robustness principle", and it goes like this: be conservative in what you do, be liberal in what you accept from others. Accordingly, most of the things that were written and codified back then allowed for tolerance. Query string parameter rules for duplicate keys/order preservation/etc were never set. Servers were allowed to implement almost anything they wanted, as long as it met some bare minimum, and clients were free to do whatever they want, as long as the RFCs were likewise met.

All kinds of servers have special rules for the query string. As a related example, in PHP, duplicate keys overwrite previous values unless you use the array syntax (lang=ruby&lang=rails returns a different value than lang[]=ruby&lang[]=rails). Similarly, in Salesforce, you're not allowed duplicate parameters, and you're not guaranteed of the order. That's how they chose to implement it, and so that's how it is. For better or worse, this is what we're stuck with.

So, to answer your question, you need to come up with an alternative solution. If you look at Amazon's Task 1: Create a canonical request for Signature Version 4, you'll find that you must sort the keys in a certain manner when creating the signature request. In other words, the only acceptable format is for the query parameters to be calculated in a certain order (note: you can, however, send the parameters in any order you want, if I remember correctly).

If you don't want to do this, you can also specify that the user-client must send the query parameters in the order they wish to be processed. For example, you might introduce an X-Query-Order header that you can read through RestContext.request.headers.get('x-query-order'). You could even decide to just request the client URI-encode the entire query string and pass it in as a parameter, then decode it.

There are workarounds for this problem, but the main point here is that technically, Apex Rest is behaving in a manner that is technically agreeable with the specifications. You'll have to work within the limits. In the meantime, you might want to post an idea on the Idea Exchange.

1
  • Thank you. I suppose I'll ask HubSpot to provide an alternative so that their requests can actually be verified when I receive them. Currently, I can assume a query order, but there's obviously no guarantee that HubSpot will maintain it.
    – Diego
    Commented Jul 25, 2022 at 3:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .