7 votes

La ligne de commande Curl fonctionne, mais pas la bibliothèque Curl C++.

J'essaie de faire des requêtes via la bibliothèque curl de C++. Je peux avec succès faire ma demande et obtenir la réponse correcte via ligne de commande mais je ne parviens pas à obtenir la réponse correcte via Le code C++ . Ma commande en ligne de commande ressemble à ceci

curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'Authorization: <some_hash_value>' -k <my_full_url> -data '<my_json_string>'

Cela fonctionne bien. J'essaie maintenant de faire la même demande en code C++. Mon code ressemble à ceci

void performRequest(const std::string& json, const void* userData, CallbackFunction callback)
{
    struct curl_slist* headers = NULL;

    headers = curl_slist_append(headers, "Accept: application/json");
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, (std::string("Authorization: ") + m_authorization).c_str());

    CURL* curlHandle = curl_easy_init();
    if (!curlHandle)
    {
        std::cerr << "Curl handler initialization failed";
    }

    curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, headers);

    // specify target URL, and note that this URL should include a file name, not only a directory
     curl_easy_setopt(curlHandle, CURLOPT_URL, m_url.c_str());

    // enable uploading
    curl_easy_setopt(curlHandle, CURLOPT_UPLOAD, 1L);

    // set HTTP method to POST
    curl_easy_setopt(curlHandle, CURLOPT_CUSTOMREQUEST, "POST");

    // set json data; I use EXACTLY the same string as in command line
    curl_easy_setopt(curlHandle, CURLOPT_COPYPOSTFIELDS, json.c_str());

    // set data size
    curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, json.size());

    // set user data for getting it in response
    curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, userData);    // pointer to a custom struct

    // set callback function for getting response
    curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, callback);    // some callback

    // send request
    curl_easy_perform(curlHandle);

    curl_easy_cleanup(curlHandle);
    curl_slist_free_all(headers);
}

Cependant, pour une raison quelconque, j'obtiens une erreur dans la réponse du serveur, ce qui me permet de supposer que la demande de mon code n'est pas équivalente à la commande de la ligne de commande. Il semble que le corps de la requête ne soit pas envoyé. Je ne peux pas voir le corps de ma requête Json lorsque j'utilise CURLOPT_DEBUGFUNCTION pour obtenir des informations de débogage.

Quel est le problème ici ? Qu'est-ce que je fais de mal ? Avez-vous des idées ?

1voto

BlakBat Points 558

Voici un exemple de code qui devrait fonctionner pour vous.

Remarquez que je :

  • Supprimé CURLOPT_UPLOAD car il ne semble pas que vous soyez en train de télécharger quelque chose mais plutôt de faire une simple POST .

  • Modifié CURLOPT_CUSTOMREQUEST à CURLOPT_POST (non que cela doive avoir de l'importance), mais je trouve cela plus propre.

  • Réorganisé CURLOPT_POSTFIELDSIZE_LARGE y CURLOPT_COPYPOSTFIELDS

  • Suppression de la CURLOPT_WRITEDATA pour les besoins de cet exemple de code.

J'ai testé ce qui suit seulement en me connectant à une instance de nc -l localhost 80

 static size_t callback(char *ptr, size_t size, size_t nmemb, void *userdata)
 {
   string s(ptr);
   cout << s << endl;
   return size * nmemb;
 }

 int main(int argc, char** argv)
 {
   string m_authorization("PWNED");
   string m_url("http://localhost");
   string m_json("{}");

   curl_global_init(CURL_GLOBAL_ALL);

   CURL* curlHandle = curl_easy_init();

   struct curl_slist* headers = nullptr;
   headers = curl_slist_append(headers, "Accept: application/json");
   headers = curl_slist_append(headers, "Content-Type: application/json");
   headers = curl_slist_append(headers, (std::string("Authorization: ") + m_authorization).c_str());

   curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, headers);

   // specify target URL, and note that this URL should include a file name, not only a directory
   curl_easy_setopt(curlHandle, CURLOPT_URL, m_url.c_str());

   // <= You are not uploading anything actually, this is a simple POST with payload
   // enable uploading
   // curl_easy_setopt(curlHandle, CURLOPT_UPLOAD, 1L);

   // set HTTP method to POST
   curl_easy_setopt(curlHandle, CURLOPT_POST, 1L);

   // set data size before copy
   curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, m_json.size());

   // set json data; I use EXACTLY the same string as in command line
   curl_easy_setopt(curlHandle, CURLOPT_COPYPOSTFIELDS, m_json.c_str());

   // set user data for getting it in response
   // curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, userData);    // pointer to a custom struct

   // set callback function for getting response
   curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, callback);    // some callback

   // send request
   curl_easy_perform(curlHandle);

   curl_slist_free_all(headers);

   curl_easy_cleanup(curlHandle);
   curl_global_cleanup();
   return 0;
 }

1voto

nabroyan Points 723

Le problème a été résolu grâce aux réservoirs de Rocki et drew010 Les commentaires de la Commission.

  1. J'ai enlevé CURLOPT_CUSTOMREQUEST , CURLOPT_UPLOAD y CURLOPT_NOSIGNAL les déclarations de fixation car elles ne sont pas nécessaires.
  2. J'ai également supprimé la ligne permettant de définir CURLOPT_POSTFIELDSIZE_LARGE bien qu'il fonctionne bien s'il est placé avant le réglage de l'appareil. CURLOPT_COPYPOSTFIELDS . Si la taille n'a pas été définie avant le CURLOPT_COPYPOSTFIELDS la donnée est supposée être une chaîne de caractères à terminaison zéro ; sinon, la taille stockée informe la bibliothèque du nombre d'octets à copier. Dans tous les cas, la taille ne doit pas être modifiée après que CURLOPT_COPYPOSTFIELDS à moins qu'un autre CURLOPT_POSTFIELDS o CURLOPT_COPYPOSTFIELDS est émise. (Voir : curl.haxx.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html;.%20If%20the%20size%20has%20not%20been%20set%20prior%20to%20CURLOPT_COPYPOSTFIELDS,%20the%20data%20is%20assumed%20to%20be%20a%20zero%20terminated%20string;%20else%20the%20stored%20size%20informs%20the%20library%20about%20the%20byte%20count%20to%20copy.%20In%20any%20case,%20the%20size%20must%20not%20be%20changed%20after%20CURLOPT_COPYPOSTFIELDS,%20unless%20another%20CURLOPT_POSTFIELDS%20or%20CURLOPT_COPYPOSTFIELDS%20option%20is%20issued.%20See:%20curl.haxx.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html) )

1voto

erfan zangeneh Points 119

Sous Windows, vous devez initier le truc winsock avec la fonction suivante

curl_global_init(CURL_GLOBAL_ALL);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X