I was making a small project where I wanted to get request multiple pieces of data at once using libcurl multi. Here is an example
CURL* array[] = {
curl_easy_init(),
curl_easy_init(),
curl_easy_init()
};
CURLM* multi = curl_multi_init();
curl_easy_setopt(array[0], CURLOPT_URL, "https://www.example.com/");
curl_easy_setopt(array[1], CURLOPT_URL, "https://www.example.com/");
curl_easy_setopt(array[2], CURLOPT_URL, "https://americas.api.riotgames.com/riot/account/v1/accounts/by-puuid/Dxon1TsoGLOAvUykGYErrEPAT_U9YkQ_jNFZpRxYpfRFwnaYVFULVshNQnZapa4qR_pe5sSBn5MQvw");
for (int i = 0; i < 3; i ) {
curl_multi_add_handle(multi, array[i]);
}
int retry = 3;
loop:
int run = 1;
while (run) {
CURLMcode mc = curl_multi_perform(multi, &run);
if (mc == CURLM_OK) {
mc = curl_multi_poll(multi, NULL, 0, 0, NULL);
}
if (mc != CURLM_OK) { // no else because catch both error possibilities
exit(0); // error in curl multi
}
}
CURLMsg *msg;
long rerun = 0;
int msgNum = 0;
while (msg = curl_multi_info_read(multi, &msgNum)) {
if (msg->msg == CURLMSG_DONE) {
if (msg->data.result != CURLE_OK) {
puts("ERROR");
exit(0); // error with transfer
}
long httpCode;
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &httpCode);
if (httpCode == 200) {
curl_multi_remove_handle(multi, msg->easy_handle);
} else { // error with serverside
rerun = httpCode;
printf("\nError : %d\n", rerun);
}
} else {
puts("ERROR");
exit(0); // return num not compelted?
}
}
puts("NExt");
if (rerun && --retry) {
printf("%d - %d\n", retry, rerun);
Sleep(1000);
goto loop;
}
puts("Finisheed");
exit(0);
So first I make an array of curl easy handles, fill in all the info, and put them into curl_multi to perform a request. The code works fine IF I set all the URLs to "https://www.example.com/".
But in my case, I request from a site that might not work at all (the URL in array[2]) so I made a retry mechanism. If there's an httpCode that's not 200, then I redo the request but only with the ones that failed (I remove all the easy handles that completed sucessfully).
However, the retry mechanism only seems to retry once (when it should retry 3 times) and seems to skip the rest. This is the output I get
...stuff from example.com...
Error : 401
NExt
2 - 401
NExt
Finisheed
As you can see, it only retries once and then stops, but there's obviously an error because it doesn't print out the correct response.
Can anyone point me in the right direction?
CodePudding user response:
curl easy is not subject for rerun if it is kept in curl multi. Remove and re-add it again. Otherwise you get !run
and !msg
on the second iteration.
if (msg->msg == CURLMSG_DONE) {
// ...
curl_multi_remove_handle(multi, msg->easy_handle);
long httpCode;
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &httpCode);
if (httpCode != 200) {
rerun = httpCode;
printf("\nError : %d\n", rerun);
curl_multi_add_handle(multi, msg->easy_handle);
}
// ...
}