2016-11-17 6 views
0

残りのフレームワークモジュールを使用してDjangoにRESTエンドポイントを作成しました。簡単なコードは以下のようになります:私は使用してPOSTリクエストを送信しようとしたlibcurlとjsoncppでdjangoにPOST要求を送信中にユニコードが無効

class DataSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Data 
     fields = ('name', 'description') 

views.py

def data_list(request): 
    """ 
    List all data. 
    """ 
    if request.method == 'GET': 
     categories = Data.objects.all() 
     serializer = DataSerializer(categories, many=True) 
     return JSONResponse(serializer.data) 

    elif request.method == 'POST': 
     data = JSONParser().parse(request) 
     serializer = DataSerializer(data=data) 
     if serializer.is_valid(): 
      serializer.save() 
      return JSONResponse(serializer.data, status=201) 
     return JSONResponse(serializer.errors, status=400) 

models.py

class Data(models.Model): 
    name = models.CharField(max_length=256) 
    description = models.TextField() 

    def __str__(self): 
     return self.name 

serializers.py Firefox用のRESTClientプラグインを使用して、それがそのまま動作することを検証できます。

私は、C++アプリケーションでlibcurlを使用してデータベースに書きたいと思っています。

私はJSONオブジェクトを作成するjsoncppを使用して、以下のように、POSTリクエストを作るためのlibcurlを使用する場合:私は、Djangoのサーバからエラーを取得

void main() { 
    Json::Value submitted_data; 
    submitted_data["name"] = "data id"; 
    submitted_data["description"] = "data description"; 
    Json::StyledWriter writer; 

    CURL *curl; 
    CURLcode res; 

    curl_global_init(CURL_GLOBAL_ALL); 

    curl = curl_easy_init(); 
    if (curl) { 
     curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:8000/data/"); 
     struct curl_slist *headers = NULL; 
     headers = curl_slist_append(headers, "Content-Type: application/json; charset=UTF-8"); 
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 
     curl_easy_setopt(curl, CURLOPT_POST, 1); 
     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, writer.write(submitted_data).c_str()); 

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

     curl_easy_cleanup(curl); 
    } 
} 

File "C:\Python27\lib\site-packages\rest_framework\parsers.py", line 67, in parse 
    raise ParseError('JSON parse error - %s' % six.text_type(exc)) 
ParseError: JSON parse error - 'utf8' codec can't decode byte 0xdd in position 0: invalid continuation byte 

投稿要求は成功しません。

  • ジャンゴ休止フレームワークは、UTF-8エンコードされたJSON文字列を期待し、
  • jsoncppがUTF-8で文字列を符号化し、
  • libcurlのエンコードとのデータを扱いについてとらわれない:私の理解では、ということですバイトレベル

私はこれに少し驚き、トラブルシューティングを開始する方法がわかりません。誰かが私のC++アプリケーションとdjangoアプリケーションを一緒に動作させる方法を理解する手助けができますか?

ありがとうございました!

+0

'strace'やその他の手段でコードを実行してネットワークトラフィックを捕捉します。おそらく、あなたの前提の1つが間違っていて、ISO-8859-1でエンコードされたデータが出力されていることがわかります。 –

+0

Hmm。私はWindows 10上でアプリケーションを実行していて、Wiresharkがループバックトラフィックをキャプチャできないように見えることに失望しました。 Windowsで使うことのできるものはありますか? –

+0

要求を同じWindowsボックスに送信する必要はありません。それを他のWindowsまたはLinuxボックスに送ってください。 –

答えて

2

CURLOPT_POSTFIELDS documentationパー:

データは、ライブラリによってコピーされていないために指さ:関連した転送がを終了するまで、結果として、それは、呼び出し元のアプリケーションによって保存されなければなりません。この動作は、CURLOPT_COPYPOSTFIELDSオプションを設定することによって変更できます(libcurlはデータをコピーします)。

あなたはCURLOPT_POSTFIELDS一時的char*ポインタを渡しています。これは、Json::StyledWriter::write()がを呼び出しているの一時的なstd::stringを返すためです。 curl_easy_setopt()の呼び出しが完了すると、std::stringが破壊され、curlが保持されているポインタchar*が無効になります。 Curlは解放されたメモリからガベージデータを送信することになります。これはの定義されていない動作です。あなたのコードは完全にクラッシュしていないのは幸いです。

だから、あなたがいずれかを行う必要があります。

std::string json = writer.write(submitted_data); 
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); 
  • 使用CURLOPT_COPYPOSTFIELDS代わりのCURLOPT_POSTFIELDS

    curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, writer.write(submitted_data).c_str()); 
    
  • curl_easy_perform()が終了するまで

    1. はローカル変数にstd::stringを保存します

    +0

    それはそれを解決したようだ。本当にありがとう! –

    +0

    私の場合、私はノードjs httpサーバーにリクエストをしようとしていましたが、私は同じエラーが出たので、この解決策を試しました。本当にありがとう! –

    関連する問題