2016-04-18 21 views
7

Tôi đang cố thực hiện một số yêu cầu qua thư viện curl của C++. Tôi có thể thành công thực hiện yêu cầu của tôi và nhận được phản hồi chính xác qua dòng lệnh, nhưng tôi không thể nhận được phản hồi chính xác qua mã C++. Lệnh dòng lệnh của tôi trông giống như thế nàyCông cụ dòng lệnh Curl, thư viện curl C++ không

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>' 

Điều đó hoạt động tốt. Bây giờ tôi cố gắng thực hiện cùng một yêu cầu trong mã C++. Mã của tôi trông như thế này

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); 
} 

Tuy nhiên, đối với một số lý do tôi nhận được một lỗi trong phản hồi từ máy chủ, từ đó tôi có thể giả định rằng yêu cầu mã của tôi là không tương đương với lệnh dòng lệnh của. Có vẻ như cơ thể không được gửi đi. Tôi không thể nhìn thấy yêu cầu của tôi Json cơ thể khi tôi sử dụng CURLOPT_DEBUGFUNCTION để bán phá giá thông tin gỡ lỗi.

Sự cố ở đây là gì? Tôi đang làm gì sai? Bất kỳ ý tưởng?

+0

Bạn có chẩn đoán Wireshark có sẵn? –

+0

Tôi sợ - không, tôi không có. – nabroyan

+4

Bạn nên xóa 'curl_easy_setopt (curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, json.size());'. Nếu kích thước chưa được đặt trước CURLOPT_COPYPOSTFIELDS, dữ liệu được giả định là một chuỗi đã kết thúc bằng không; khác kích thước được lưu trữ thông báo cho thư viện về số byte để sao chép. Trong mọi trường hợp, kích thước không được thay đổi sau CURLOPT_COPYPOSTFIELDS, trừ khi tùy chọn CURLOPT_POSTFIELDS hoặc CURLOPT_COPYPOSTFIELDS khác được phát hành. Xem: https://curl.haxx.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html – Rocki

Trả lời

1

Vấn đề đã được giải quyết xe tăng để Rocki 's và drew010 bình luận của.

  1. Tôi đã xóa CURLOPT_CUSTOMREQUEST, CURLOPT_UPLOADCURLOPT_NOSIGNAL thiết lập sao kê là không cần thiết.
  2. Tôi cũng đã xóa dòng để đặt CURLOPT_POSTFIELDSIZE_LARGE, mặc dù nó hoạt động tốt nếu được đặt trước khi đặt CURLOPT_COPYPOSTFIELDS. Nếu kích thước chưa được đặt trước CURLOPT_COPYPOSTFIELDS, dữ liệu được giả định là một chuỗi đã kết thúc bằng không; khác kích thước được lưu trữ thông báo cho thư viện về số byte để sao chép. Trong mọi trường hợp, kích thước không được thay đổi sau CURLOPT_COPYPOSTFIELDS, trừ khi tùy chọn khác CURLOPT_POSTFIELDS hoặc CURLOPT_COPYPOSTFIELDS được phát hành.(Xem: curl.haxx.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html)
+0

Câu trả lời có thể được lặp lại một cách nào đó để nhấn mạnh vào những gì đã sai thay vì "Tôi đã làm một đống các công cụ và sau đó nó hoạt động"? – Andreas

1

Đây là mã mẫu có thể hoạt động cho bạn.

Chú ý rằng tôi:

  • Removed CURLOPT_UPLOAD vì nó không có vẻ như bạn đang thực sự tải lên một cái gì đó mà chỉ cần làm một đơn giản POST.

  • Đã thay đổi CURLOPT_CUSTOMREQUEST thành CURLOPT_POST (không phải là vấn đề), nhưng tôi thấy nó sạch hơn.

  • sắp xếp lại CURLOPT_POSTFIELDSIZE_LARGECURLOPT_COPYPOSTFIELDS

  • Removed dòng CURLOPT_WRITEDATA vì lợi ích của mẫu mã này.

Tôi đã thử nghiệm sau đây chỉ bằng cách kết nối đến một instance của 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; 
} 
1

Trong cửa sổ, bạn phải init những thứ winsock với bên dưới chức năng

curl_global_init(CURL_GLOBAL_ALL); 
Các vấn đề liên quan