使用C的原始libcurl JSON PUT请求 [英] a raw libcurl JSON PUT request using C

查看:310
本文介绍了使用C的原始libcurl JSON PUT请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在编写一个类似REST的客户端,只需要执行PUT请求即可。

I am currently writing a REST-like client that only is required to do PUT requests.

问题:

运行程序无法在URL的API上给我正确的结果,我也不知道为什么。

Problem:
Running the program is not giving me the correct results on the URL's API and I do not know why.

使用curl_easy_perform(curl)不会在调用时引发错误。但是,预期的结果不是在URL的API上生成的。

Using curl_easy_perform(curl) does not throw an error when called. But the expected result is not generated on the URL's API.

使用curl_easy_send(curl,..,.....)会抛出:不支持的协议错误

Using curl_easy_send(curl,..,..,..) throws a : unsupported protocol error

假设:

我假设我使用curl_easy_opts的顺序有问题吗?我什至缺少几个关键点?

Assumption:
I am assuming the order in which I am using the curl_easy_opts is a problem? And I am even missing a couple of key lines?

我一直在这里阅读其他人如何进行PUT请求并一直使用他们的方法。

I have been reading on here of how other people do PUT requests and have been using their methods.

程序摘要:

我的程序提示用户输入一些字符串/字符数据,然后,我自己构造诸如标头和有效负载。标头和有效负载均为JSON格式,但有效负载只是一个字符串(在这种情况下,为char * str =(char *)mallo ..等)。标头的构造如下所示。

My program prompts the user for some string/character data, and from that, I construct the strings myself such as the header and the payload. The header and payload are both in JSON format but the payload is simply a string ( in this case, a char *str = (char *)mallo.. etc). How the header is constructed is shown below.

我的标头使用

struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Accept: application/json");
//there is more content being appended to the header

CURL函数调用:

    //init winsock stuff
    curl_global_init(CURL_GLOBAL_ALL);

    //get a curl handle
    curl = curl_easy_init();

if(curl){
    //append the headers
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    //specify the target URL
    curl_easy_setopt(curl, CURLOPT_URL, url);

    //connect ( //i added this here since curl_easy_send() says it requires it. )
    curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY,1L); 

    //specify the request (PUT in our case)
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");

    //append the payload
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);

    res = curl_easy_perform(curl);
    //res = curl_easy_send(curl, payload, strlen(payload),&iolen);

    //check for errors
    if(res != CURLE_OK)
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));

    curl_easy_cleanup(curl);
}


推荐答案

您不应该使用 CURLOPT_CONNECT_ONLY 选项或 curl_easy_send()函数,这些功能旨在用于自定义非HTTP协议。

You should not be using the CURLOPT_CONNECT_ONLY option or curl_easy_send() function, those are intended to be used for custom, non-HTTP protocols.

请参见此页面一个使用libcurl进行PUT请求的示例。基本上,您想启用 CURLOPT_UPLOAD CURLOPT_PUT 选项,以表示您正在执行PUT请求并启用上传带有请求的正文,然后设置 CURLOPT_READDATA CURLOPT_INFILESIZE_LARGE 选项以告诉libcurl如何读取数据

See this page for an example of how to do a PUT request with libcurl. Basically, you want to enable the CURLOPT_UPLOAD and CURLOPT_PUT options to say that you're doing a PUT request and to enable uploading a body with the request, and then you set the CURLOPT_READDATA and CURLOPT_INFILESIZE_LARGE options to tell libcurl how to read the data you're uploading and how big the data is.

在您的情况下,如果您已经在内存中存储了数据,则无需从中读取数据一个文件,就可以在读取回调中将它 memcpy()包起来。

In your case, if you already have the data in memory, then you don't need to read it out of a file, and you can just memcpy() it inside your read callback.

下面复制的示例代码:

/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/ 
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>

/*
 * This example shows a HTTP PUT operation. PUTs a file given as a command
 * line argument to the URL also given on the command line.
 *
 * This example also uses its own read callback.
 *
 * Here's an article on how to setup a PUT handler for Apache:
 * http://www.apacheweek.com/features/put
 */ 

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t retcode;
  curl_off_t nread;

  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */ 
  retcode = fread(ptr, size, nmemb, stream);

  nread = (curl_off_t)retcode;

  fprintf(stderr, "*** We read %" CURL_FORMAT_CURL_OFF_T
          " bytes from file\n", nread);

  return retcode;
}

int main(int argc, char **argv)
{
  CURL *curl;
  CURLcode res;
  FILE * hd_src ;
  struct stat file_info;

  char *file;
  char *url;

  if(argc < 3)
    return 1;

  file= argv[1];
  url = argv[2];

  /* get the file size of the local file */ 
  stat(file, &file_info);

  /* get a FILE * of the same file, could also be made with
     fdopen() from the previous descriptor, but hey this is just
     an example! */ 
  hd_src = fopen(file, "rb");

  /* In windows, this will init the winsock stuff */ 
  curl_global_init(CURL_GLOBAL_ALL);

  /* get a curl handle */ 
  curl = curl_easy_init();
  if(curl) {
    /* we want to use our own read function */ 
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

    /* enable uploading */ 
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    /* HTTP PUT please */ 
    curl_easy_setopt(curl, CURLOPT_PUT, 1L);

    /* specify target URL, and note that this URL should include a file
       name, not only a directory */ 
    curl_easy_setopt(curl, CURLOPT_URL, url);

    /* now specify which file to upload */ 
    curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);

    /* provide the size of the upload, we specicially typecast the value
       to curl_off_t since we must be sure to use the correct data size */ 
    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                     (curl_off_t)file_info.st_size);

    /* Now run off and do what you've been told! */ 
    res = curl_easy_perform(curl);
    /* Check for errors */ 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */ 
    curl_easy_cleanup(curl);
  }
  fclose(hd_src); /* close the local file */ 

  curl_global_cleanup();
  return 0;
}

这篇关于使用C的原始libcurl JSON PUT请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆