有curl --data-urlencode的libcurl curl_easy_setopt()版本吗

pqwbnv8z  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(93)

我正在尝试连接到最新的皇家邮政API V4以获得基于C和libcurl中现有工作代码的令牌,以连接到V3。我有一个curl示例脚本,它使用--data-urlencode获取一个令牌,返回一个令牌。

curl -k --location 'https://authentication.proshipping.net/connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=AAAAAAA' \
--data-urlencode 'client_secret=BBBBBBBBB' \
--data-urlencode 'grant_type=client_credentials'

字符串
我在C和libcurl中尝试了以下操作

curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, FALSE);

curl_easy_setopt(hnd, CURLOPT_URL, "https://authentication.proshipping.net/connect/token");
curl_easy_setopt(hnd, CURLOPT_POST, TRUE);

headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);

postfields = curl_slist_append(postfields, "client_id=AAAAAAA");
postfields = curl_slist_append(postfields, "client_secret=BBBBBBBBB");
postfields = curl_slist_append(postfields, "grant_type=client_credentials");
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, postfields);

curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &s);

res = curl_easy_perform(hnd);


但是libcurl示例返回输出

{"error":"invalid_client"}


有人能在libcurl中使用--data-urlencode或等效命令吗?谢啦,谢啦

krcsximq

krcsximq1#

似乎没有一个easy option可以模仿--data-urlencode的全部功能,其中包括使用特殊语法加载和编码文件的功能,还可以将其参数连接起来形成一个blob。
用于对以空值结尾的字节字符串进行URL编码的库函数是curl_easy_escape。当使用者使用完之后,产生的字串必须传递至curl_free

char *curl_easy_escape(CURL *curl, const char *string, int length);
void curl_free(void *ptr);

字符串

  • (内部data_urlencode(实现--data-urlencode)使用curl_easy_escape。)*

至于CURLOPT_POSTFIELDS

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDS, char *postdata);


第三个参数应该是以空值结尾的字节字符串(默认情况下;可以使用CURLOPT_POSTFIELDSIZE手动调整大小)。
根据您的示例,--libcurl生成:

curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "client_id=AAAAAAA&client_secret=BBBBBBBBB&grant_type=client_credentials");


另请参阅:http-post.c
--data-urlencode最基本功能(name=content语法)的一个模糊的模仿大概是:

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int data_append(char **to, const char *name, const char *field)
{
    /* 1 if initial segment, 0 if concat, justifies & below */
    unsigned init = (NULL == *to);

    /* first argument ignored in 7.82.0+, otherwise modify `data_append` */
    char *escaped_field = curl_easy_escape(NULL, field, 0);

    if (!escaped_field)
        return 0;

    /* previous */
    size_t offset = !init ? strlen(*to) : 0;
    /* name=escaped */
    size_t length = strlen(name) + 1 + strlen(escaped_field);

    /* previous&name=escaped\0 */
    char *result = realloc(*to, offset + !init + length + 1);

    if (result) {
        sprintf(result + offset, "&%s=%s" + init, name, escaped_field);
        *to = result;
    }

    curl_free(escaped_field);

    return NULL != result;
}

int main(void)
{
    CURL *curl = curl_easy_init();

    char *data = NULL;
    data_append(&data, "name", "field");
    data_append(&data, "foo", "hello world!");
    fprintf(stderr, "DEBUG: Sending: <%s>\n", data);

    curl_easy_setopt(curl, CURLOPT_URL, "https://mockbin.org/request");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);

    curl_easy_perform(curl);
    curl_easy_cleanup(curl);

    free(data);
}


结果如下:

./a.out 
DEBUG: Sending: <name=field&foo=hello%20world%21>
...
...
  "postData": {
    "mimeType": "application/x-www-form-urlencoded",
    "text": "name=field&foo=hello%20world%21",
    "params": {
      "name": "field",
      "foo": "hello world!"
    }
  }
...
...


这是 * 大致 *

$ curl -L 'https://mockbin.org/request' --data-urlencode 'name=field' --data-urlencode 'foo=hello world!'

  • --data-urlencode实现了RFC1866中所述的' ' => '+'转换。)*

另外:还有CURLOPT_MIMEPOST,可用于 * 多部分/表单数据 *。

相关问题