I had some problems making libcurl work with C++ JsonCpp library and, after a lot of research, I came up with this code:
int post(const string& call, const string& key, const string& value) {
// (...)
char* char_data=NULL;
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: application/json; charset=UTF-8");
Json::Value root;
root[key] = value;
Json::StyledWriter writer;
string data = writer.write(root);
char_data = (char*) malloc((strlen(data.c_str())+1) * sizeof(char));
strcpy(char_data, data.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, char_data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(char_data));
// (...)
}
This works fine, as long as the data
(C++ std::string
that holds the JSON string representation) doesn't have any non-ascii chars. When it does, I get an error from the backend (written in Rails 3):
Started POST "/deployments/4c904f607d7c4249cf00002c/log.json" for 67.23.79.89 at Wed Sep 15 00:45:40 -0400 2010
Processing by DeploymentsController#log as JSON
Parameters: {"log"=>"0 upgraded, 0 newly \214\211K########talled, 0 to remove and 46 not upgraded.\n", "id"=>"4c904f607d7c4249cf00002c"}
Completed in 6ms
BSON::InvalidStringEncoding (String not valid UTF-8):
app/models/deployment.rb:161:in `log'
app/models/deployment.rb:160:in `each'
app/models/deployment.rb:160:in `log'
app/controllers/deployments_controller.rb:54:in `log'
What is the best way to take a C++ sctring (in this case data), and safely convert it UTF-8, and then to a *char
variable that would play nice with libcurl?