Home > Blockchain >  Handling curly braces in curl/libcurl
Handling curly braces in curl/libcurl

Time:11-26

From the command line, I have a curl request with two query parameters that use curly braces. However, one only works when URL-encoded and the other only works when it is not URL-encoded.

Here's an example of a request that (weirdly) works from the command line and returns data for 3 IDs. I wouldn't expect it to work because TIME is URL-encoded with curly braces ({ and }) but P_ID is not:

  1. curl -X GET "https://example.com/search?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}"

Even weirder, the following calls don't work and seem to ignore the P_ID field and give me data for every person:

  1. curl -X GET "https://example.com/search?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}"

  2. curl -X GET "https://example.com/search?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3"

  3. curl -X GET "https://example.com/search?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3"

Given these constraints, where the first call works as I want it to, but the second and third do not, then how do I use libcurl in C such that the first call is replicated? I know CURLOPT_URL encodes everything, so it would encode both the braces in TIME and P_ID. I've tried using CURLUPART like below, but to no avail.

void *curlHandle;
curl_easy_reset(curlHandle);
CURLU *url = curl_url();
curl_url_set(url, CURLUPART_URL, "example.com", 0);
curl_url_set(url, CURLUPART_QUERY, "P_ID={1,2,3}", CURLU_APPENDQUERY);
curl_url_set(url, CURLUPART_QUERY, "TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}", CURLU_APPENDQUERY);
curl_url_set(url, CURLUPART_SCHEME, "https", 0);
curl_url_set(url, CURLUPART_PATH, "/search/", 0);
curl_easy_setopt(curlHandle, CURLOPT_CURLU, url);
curl_easy_perform(curlHandle);

I'm getting this response:

* No URL set
Curl failed with error 3: URL using bad/illegal format or missing URL. 0 retries remaining

In summary: how do I get libcurl to make a bizarre curl request like the first one up top? Because that is the only way I can execute from the command line with the expected result of only getting the 3 people's data.

Alternatively, is there perhaps another way to try this curl request other than the 4 attempts above? Should I just reach out to the API owner and ask why it likes { encoded in some places and not others?

CodePudding user response:

These are your 4 query strings after being url decoded.

TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}
TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}
TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3
TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3

None of the characters in your query strings need to be urlencoded.
Given you basically have two urls.
These are both urls, and the query strings url decoded on the server:

https://example.com?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3
TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID=1&P_ID=2&P_ID=3


https://example.com?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}
TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3}

I do not think your query string is causing the error.
It appears you got this wrong:

CURLU *url = curl_url();

Maybe it should be:

CURLU *url= curl_url();
curl_url_set(url, CURLUPART_URL,
R"(https://example.com?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3})", 0);

Or just pass the URL directly to the easy handle:

curl_easy_setopt(curlHandle, CURLOPT_URL, R"(https://example.com?TIME={"TIME_TYPE":"MESSAGE","MESSAGENUMBER":5}&P_ID={1,2,3})");
  • Related