我在C.使用libcurl的限定与JSON请求体PUT请求
这怎么我做它:
sprintf(jsonObj, "\"name\" : \"%s\", \"age\" : \"%s\"", name, age);
struct curl_slist *headers = NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_slist_append(headers, "charsets: utf-8");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
res = curl_easy_perform(curl);
请求主体到达这样的:
{ '"name" : "Pedro", "age" : "22"' }
随着{ '
开始和' }
结尾。
- - 更多信息 - - -
如果我宣布这个代码
char* jsonObj = "{ \"name\" : \"Pedro\" , \"age\" : \"22\" }";
struct curl_slist *headers = NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_slist_append(headers, "charsets: utf-8");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
res = curl_easy_perform(curl);
服务器收到此作为请求体:
{ '{ "name" : "Pedro" , "age" : "22" }': '' }
我的问题是:
是的libcurl预格式化/编码自动JSON请求?
顺便说一句,请问有libcurl的编码JSON对象的某种方式?
非常感谢!
Answer 1:
该问题可能是与头。 当你配置你的curl_slist标题我想你应该curl_slist_append的输出分配回标题:
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, "charsets: utf-8");
Answer 2:
首先,让我们来看一些事情。 要下手,是Daniel Stenberg发明是正确的(因为我希望他会是这样,因为他写的代码):libcurl中没有任何数据追加到你的代码。 我可以用这个示例程序,这是喜欢你的例子,但与一些额外的设置/拆卸代码证明这一点。 这是所有的代码:有没有别的在座的:
#include <curl/curl.h>
int main (int argc, char *argv[]) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl == NULL) {
return 128;
}
char* jsonObj = "{ \"name\" : \"Pedro\" , \"age\" : \"22\" }";
struct curl_slist *headers = NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_slist_append(headers, "charsets: utf-8");
curl_easy_setopt(curl, CURLOPT_URL, "http://http2bin.org/put");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return res;
}
分组捕获使用Wireshark请求表明,该发射下面的HTTP请求:
PUT /put HTTP/1.1
Host: http2bin.org
User-Agent: libcrp/0.1
Accept: */*
Content-Length: 35
Content-Type: application/x-www-form-urlencoded
{ "name" : "Pedro" , "age" : "22" }
正如你所看到的,这正是你要求发送的JSON数据。 没有额外的数据在这里,没有花括号。
这意味着,正在由您的服务器或一些中间中间设备添加额外的括号。 我的猜测是,你的服务器加入它,因为它被强制试图把任何的身体不是一个application/json
考虑整个身体的字符串体为一体。
您的服务器不认为这是一个JSON身体的原因是这里的另一个答案封装:你没有正确设置你的头。 curl_slist_append
返回一个新的struct curl_slist *
您需要分配回你的headers
变量。 这意味着你需要更改这些四行:
struct curl_slist *headers = NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_slist_append(headers, "charsets: utf-8");
这四种:
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, "charsets: utf-8");
这应该说服您发送JSON数据服务器。
在未来,我建议你熟悉Wireshark的解决这样的问题。 这是非常有益的,看看你发送的实际要求。 如果做不到这一点,如果你不想,你可以使用CURLOPT_DEBUGFUNCTION
来获取数据卷曲发送验证它。
Answer 3:
libcurl中将派正是你问它来发送的字节数。 它没有JSON的知识都没有。
见@ Lukasa的更好和更出色的细节和更详细的答案。
Answer 4:
我有一个类似的问题。
我发现了curl命令的-libcurl选项。 它帮助了很多! 只需将它添加到你的工作curl命令的结束。
最后,它帮助我建立这个代码:
CURLcode ret;
CURL *hnd;
struct curl_slist *slist1;
std::string jsonstr = "{\"username\":\"bob\",\"password\":\"12345\"}";
slist1 = NULL;
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "http://u/r/l");
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, jsonstr.c_str());
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.38.0");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
curl_slist_free_all(slist1);
slist1 = NULL;
快速临危此JSON为:
{ username: 'bob', password: '12345' }
我希望这有帮助!
Answer 5:
了解系统是否正常运作的一个关键部分是看到什么程序实际上是通过网络发送。 因此,另一种方式来检查字节流,而不是在你的服务器指向它(和/或运行Wireshark的),是刚刚运行的netcat在测试机上一个单独的窗口实例:
nc -l 8080
并且在点的代码(CURLOPT_URL) “ HTTP://本地主机:8080 ”。
你需要按下Control-d在nc
窗口,使卷曲完成终止连接,但你也可以输入预先测试回归文本,如果你期待某种答复再次进行测试的,可以是有用的。
Answer 6:
我用JSON-C的编码和解码jsons和它的工作非常出色。 该文档也很容易理解。 https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/
文章来源: JSON requests in C using libcurl