cURL 发布模式参数无效

cURL Release Mode Invalid Parameter

我正在开发一个 C++ 程序,该程序使用 cURL 来“登录”我的 Valorant 帐户。该代码在调试模式下运行良好(Visual Studio 2019),但当我切换到发布模式时出现无效参数错误。做了一些研究后,我发现这是因为 libcurl,但网上没有修复。我还使用 json 和一小段用于 base64 解码的代码片段,但我认为这些无关紧要。我的项目属性是默认属性,我什至尝试创建一个新项目并复制我的代码,但得到了相同的结果。 代码:

#include <iostream>
#include "json.hpp"
#include <curl/curl.h>
#include <string>
#include <sstream>
#include "base64.hpp"
#include <stdio.h>

using json = nlohmann::json;


CURL* hnd = curl_easy_init();


size_t WriteCallback(char* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

void authCookies()
{

    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");

    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);

    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"client_id\":\"play-valorant-web-prod\",\"nonce\":\"1\",\"redirect_uri\":\"https://playvalorant.com/opt_in\",\"response_type\":\"token id_token\"}");

    CURLcode ret = curl_easy_perform(hnd);
}


std::string getAuthToken(std::string username, std::string password)
{
    std::string token = "";
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/api/v1/authorization");

    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    std::string response;
    json toSend = {
        {"type", "auth"},
        {"username", username},
        {"password", password},
        {"remember", false},
        {"language", "en_US"}
    };

    std::string sendText = toSend.dump(4);
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, sendText.c_str());
    curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
    CURLcode ret = curl_easy_perform(hnd);
    json resp = json::parse(response);

    //parse the uri and look for a token
    std::string uri = std::string(resp["response"]["parameters"]["uri"]);
    size_t loc = uri.find("#access_token=");

    for (int i = loc + 14; i < uri.length(); i++)
    {
        if (uri[i] != '&') { token += uri[i]; }
        else { break; }
    }
    return token;
}

void cookieReauth()
{
    std::string response;
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://auth.riotgames.com/authorize?redirect_uri=https%3A%2F%2Fplayvalorant.com%2Fopt_in&client_id=play-valorant-web-prod&response_type=token%20id_token");
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");
    curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
    CURLcode ret = curl_easy_perform(hnd);
}

std::string getEntitlement(std::string token)
{
    std::string out = "";

    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://entitlements.auth.riotgames.com/api/token/v1");

    struct curl_slist* headers = NULL;
    std::string auth = "Authorization: Bearer " + token;
    headers = curl_slist_append(headers, auth.c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "");

    curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &out);
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);

    CURLcode ret = curl_easy_perform(hnd);

    json resp = json::parse(out);
    return std::string(resp["entitlements_token"]);
}

struct valorantUser
{
    std::string displayName;
    std::string puuid;
    std::string name;
    std::string tag;
};

std::vector<valorantUser> getUsersByPuuid(std::string token, std::string entitlement, json puuidList, std::string region)
{
    std::vector<valorantUser> userList;
    std::string response;
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
    curl_easy_setopt(hnd, CURLOPT_URL, std::string("https://pd." + region + ".a.pvp.net/name-service/v2/players").c_str());

    struct curl_slist* headers = NULL;

    std::string auth = "Authorization: Bearer " + token;
    std::string ent = "Entitlements: " + entitlement;
    headers = curl_slist_append(headers, auth.c_str());
    headers = curl_slist_append(headers, ent.c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);

    std::string toSend = puuidList.dump();
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, toSend.c_str());


    curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &response);
    CURLcode ret = curl_easy_perform(hnd);
    
    json resData = json::parse(response);
    for (int i = 0; i < resData.size(); i++)
    {
        valorantUser dat;
        dat.displayName = std::string(resData[i]["DisplayName"]);
        dat.puuid = std::string(resData[i]["Subject"]);
        dat.name = std::string(resData[i]["GameName"]);
        dat.tag = std::string(resData[i]["TagLine"]);
        userList.push_back(dat);
    }

    return userList;
}

std::string getTokenPuuid(std::string token)
{
    std::vector<std::string> toks;
    std::stringstream test(token);
    std::string cur;
    while (std::getline(test, cur, '.'))
    {
        toks.push_back(cur);
    }

    json decoded = json::parse(base64_decode(toks[1]));
    
    return decoded["sub"];
}

int main()
{
    
    curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
    
    authCookies(); //get auth cookies
    std::string token = getAuthToken("username", "password"); //get auth token
    cookieReauth(); //get more auth cookies
    
    std::string entitlement = getEntitlement(token); //get entitlement token
    
    std::string puuid = getTokenPuuid(token); //get user puuid from token
    json puuidList = json::array({puuid});
    valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid

    std::cout << "Signed in as " << botData.name << "#" << botData.tag;
}

谢谢

编辑: 通过注释掉我所有的功能,错误停止了。如果我什至从 authCookies() 函数中删除评论,错误又回来了。也是很奇怪,直到代码结束才出现错误

int main()
{

    curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(hnd, CURLOPT_COOKIEJAR, "");
    
    /*
    authCookies(); //get auth cookies
    std::string token = getAuthToken("username", "password"); //get auth token
    cookieReauth(); //get more auth cookies

    std::string entitlement = getEntitlement(token); //get entitlement token

    std::string puuid = getTokenPuuid(token); //get user puuid from token
    json puuidList = json::array({ puuid });
    valorantUser botData = getUsersByPuuid(token, entitlement, puuidList, "na")[0]; //get user name from puuid

    std::cout << "Signed in as " << botData.name << "#" << botData.tag;*/
    curl_easy_cleanup(hnd);
    return 0;
}

当调用 authCookies() 时,WriteCallbackuserp 设置为 (void*)stdout(如果未分配 CURLOPT_WRITEDATA 则为默认值)。 ((std::string*)userp)->append((char*)contents, size * nmemb);FILE* 取消引用为 std::string*


为什么要将 char* contents 转换为 char*