2011-11-24 7 views
10

私のC++プログラムは現在、パイプ(popen("curl ..."))でcurlを呼び出し、JSONデータのファイルをWebサーバーにPOSTします。これは、JSONをファイルに保存し、サブシェルでカールを呼び出す必要があるため、明らかなパフォーマンス上の制限があります。私はlibcurlを使うためにそれを書き直したいのですが、これをどうやって行うのかは分かりません。私はpopen()に渡すコマンドラインは次のとおりです。私はそれを投稿する必要があります前に、libcurlを使用してJSONのバッファをPOSTするにはどうすればよいですか?

curl -s -S -D /dev/null -H "Content-Type: application/json" -X POST -d file-of-json http://server/handler.php 

(3K程度)JSONデータはRAM内のバッファに座っています。 libcurlのCURLOPT_READFUNCTIONを使用してlibcurlへのバッファをスプールすることを期待していました(ただし、私は選択肢がありません)。また、CURLOPT_WRITEFUNCTIONを使用してサーバーの応答をキャプチャしました。

これはすべて簡単です。混乱しているのは、CURLOPT_POST、CURLOPT_HTTPPOST、CURLOPT_POSTFIELDS、CURLOPT_HTTPHEADERのどの組み合わせが必要なのかです。私はこの主題についてたくさんの記事を読んできました。助言がありますか?

[このように、私は通常、任意のURLエンコードされたフォームフィールドを持っていないことに注意します。http:?I = = &私=クエリで&これら=を使用し&ません//server/handler.php]

答えて

9

このための例のコードはここにあります:http://curl.haxx.se/libcurl/c/post-callback.html

 

/*************************************************************************** 
*         _ _ ____ _ 
* Project      ___| | | | _ \| | 
*       /__| | | | |_) | | 
*       | (__| |_| | _ <| |___ 
*        \___|\___/|_| \_\_____| 
* 
* Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, 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. 
* 
***************************************************************************/ 
/* An example source code that issues a HTTP POST and we provide the actual 
* data through a read callback. 
*/ 
#include 
#include 
#include 

const char data[]="this is what we post to the silly web server"; 

struct WriteThis { 
    const char *readptr; 
    int sizeleft; 
}; 

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp) 
{ 
    struct WriteThis *pooh = (struct WriteThis *)userp; 

    if(size*nmemb sizeleft) { 
    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */ 
    pooh->readptr++;     /* advance pointer */ 
    pooh->sizeleft--;    /* less data left */ 
    return 1;      /* we return 1 byte at a time! */ 
    } 

    return 0;       /* no more data left to deliver */ 
} 

int main(void) 
{ 
    CURL *curl; 
    CURLcode res; 

    struct WriteThis pooh; 

    pooh.readptr = data; 
    pooh.sizeleft = strlen(data); 

    curl = curl_easy_init(); 
    if(curl) { 
    /* First set the URL that is about to receive our POST. */ 
    curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/index.cgi"); 

    /* Now specify we want to POST data */ 
    curl_easy_setopt(curl, CURLOPT_POST, 1L); 

    /* we want to use our own read function */ 
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); 

    /* pointer to pass to our read function */ 
    curl_easy_setopt(curl, CURLOPT_READDATA, &pooh); 

    /* get verbose debug output please */ 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 

    /* 
     If you use POST to a HTTP 1.1 server, you can send data without knowing 
     the size before starting the POST if you use chunked encoding. You 
     enable this by adding a header like "Transfer-Encoding: chunked" with 
     CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you must 
     specify the size in the request. 
    */ 
#ifdef USE_CHUNKED 
    { 
     struct curl_slist *chunk = NULL; 

     chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked"); 
     res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); 
     /* use curl_slist_free_all() after the *perform() call to free this 
     list again */ 
    } 
#else 
    /* Set the expected POST size. If you want to POST large amounts of data, 
     consider CURLOPT_POSTFIELDSIZE_LARGE */ 
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)pooh.sizeleft); 
#endif 

#ifdef DISABLE_EXPECT 
    /* 
     Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" 
     header. You can disable this header with CURLOPT_HTTPHEADER as usual. 
     NOTE: if you want chunked transfer too, you need to combine these two 
     since you can only set one list of headers with CURLOPT_HTTPHEADER. */ 

    /* A less good option would be to enforce HTTP 1.0, but that might also 
     have other implications. */ 
    { 
     struct curl_slist *chunk = NULL; 

     chunk = curl_slist_append(chunk, "Expect:"); 
     res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); 
     /* use curl_slist_free_all() after the *perform() call to free this 
     list again */ 
    } 
#endif 

    /* Perform the request, res will get the return code */ 
    res = curl_easy_perform(curl); 

    /* always cleanup */ 
    curl_easy_cleanup(curl); 
    } 
    return 0; 
} 
 
+0

これは完璧です。ありがとう。 –

+1

心配はいりません。ところで、もしC++を書いているのであれば、まっすぐなC libcurlのラッパーであるcurlppをチェックしてください。http://curlpp.org/index.php/examples/71- example-21 –

12

あなたはCURLOPT_POSTFIELDSを使用することができます。

CURL *curl = curl_easy_init(); 

curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/api/endpoint"); 
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"hi\" : \"there\"}"); 

curl_easy_perform(curl); 

CURLOPT_POSTFIELDSは何らかの形でペイロードを変更しないので、JSONデータをPOSTするのに非常に便利です。また、CURLOPT_POSTFIELDSが指定されている場合は、自動的にCURLOPT_POSTが有効になるため、要求にCURLOPT_POSTを指定する必要はありません。

+0

同じ方法でJSON配列または文字列を投稿しますか? [1、 "blah"]はフォームではなく、キーと値のペアはありません。このような場合は、明示的に言及する必要があります。 – dmitri

2

また、あなたの代わりに余分なバックスラッシュを追加するRAW入力を使用することがあります。

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, R"anydelim({"hi" : "there"})anydelim"); 

区切り文字またはそれなし。

3

Content-Typeヘッダーと一致するものはapplication/jsonのように、オペアンプが尋ねているのと同じですか?

上記の2つの回答のCURLOPT_POSTFIELDSCURLOPT_POSTを使用すると、Content-Typeは自動的にapplication/x-www-form-urlencodedに設定されます。私は正しく設定ヘッダを取得するための唯一の方法はこの答えに概説されているものを追加することでした

JSON requests in C using libcurl

関連する問題