http_client sending json

Nov 18, 2013 at 6:44 AM
Hi,
I've my listener set up to listen to any incoming methods. Now I'm trying to send via a client a json value. This is the point which doesn't work. If I want to send any Values I'm getting a Segmentation Fault Error. After running my Code in Debug Mode, the Programm stops at this method
void set_body(const json::value &body_data)
    {
        auto body_text = utility::conversions::to_utf8string(body_data.to_string());
        auto length = body_text.size();
        set_body(concurrency::streams::bytestream::open_istream(std::move(body_text)), length, _XPLATSTR("application/json"));
    }
it's in the http_msg.h on line 1156. My System is an Ubuntu 12.04.

hsgimit
Nov 18, 2013 at 6:45 PM
Hi hsgimit,

can you please provide us with your code (your handler) so we will try to reproduce and see what's going on.

Thanks!
Nov 19, 2013 at 6:50 AM
hi ohhysobe,
#include <cpprest/http_client.h>
#include <cpprest/json.h>

using namespace web;
using namespace web::http;
using namespace web::http::client;

#include <iostream>

using namespace std;

void display_field_map_json(json::value & jvalue)
{
    if(!jvalue.is_null())
    {
        for (auto const & e : jvalue)
        {
            cout << e.first.as_string() << " : " << e.second.as_string() << endl;
        }
    }
}

pplx::task<http_response> make_task_request(http_client & client,
        method mtd,
        json::value const & jvalue) {

    return (mtd == methods::GET || mtd == methods::HEAD) ?
            client.request(mtd, "/restdemo") :
            client.request(mtd, "/restdemo", jvalue);
}

void make_request(http_client & client, method mtd, json::value const & jvalue) {
    make_task_request(client, mtd, jvalue)
            .then([](http_response response) {
                if (response.status_code() == status_codes::OK) {
                    return response.extract_json();
                }
                return pplx::task_from_result(json::value());
            })
    .then([](pplx::task<json::value> previousTask) {
        try {
            display_field_map_json(previousTask.get());
        } catch (http_exception const & e) {
            wcout << e.what() << endl;
        }
    })
    .wait();
}

int main() {
    http_client client("http://192.168.2.102:8000");

    json::value::field_map putvalue;
    
    putvalue.push_back(make_pair(json::value(L"one"), json::value(L"100")));
    putvalue.push_back(make_pair(json::value(L"two"), json::value(L"200")));

    cout << "\nput values\n";
    make_request(client, methods::PUT, json::value::object(putvalue));

    return 0;
}
Thanks for helping
hsgimit
Nov 19, 2013 at 11:47 PM
So the problem is in using L"strings". Try removing L and the problem should be solved.
Explanation:
Casablanca is a cross-platform library and we support (by default) different types of strings on different platforms. On Windows we have wide strings (based on wchar_t), while on Linux (and soon OS X) we support regular non-wide (based on char). Furthermore we have a macro U used as U("your string") which is defined as wide string on Windows and normal string on other platforms. So if you want your code to be cross-platform including Windows you should use U macro.

Please let me know if it helps.
Nov 20, 2013 at 6:54 AM
Hi,
now it works! Thanks very much! Great Explanation btw.

hsgimit
Feb 9, 2014 at 6:36 PM
And how to do with string variables? I'm trying send a reply from the server but I'm not understanding how to send strings.
Coordinator
Feb 10, 2014 at 1:23 AM
Hi Ichibection,

There are a couple of ways you can reply to a request with strings. The easiest is using the reply over load that takes a string on the http_request class:
    /// <summary>
    /// Responses to this HTTP request.
    /// </summary>
    /// <param name="status">Response status code.</param>
    /// <param name="content_type">Content type of the body.</param>
    /// <param name="body_data">String containing the text to use in the response body.</param>
    /// <returns>An asynchronous operation that is completed once response is sent.</returns>
    /// <remarks>
    /// The response may be sent either synchronously or asychronously depending on an internal
    /// algorithm on whether we decide or not to copy the body data. Either way callers of this function do NOT
    /// need to block waiting for the response to be sent to before the body data is destroyed or goes
    /// out of scope.
    /// </remarks>
    pplx::task<void> reply(http::status_code status, const utility::string_t &body_data, utility::string_t content_type = _XPLATSTR("text/plain")) const
Another option is directly construct the http_response class yourself and call one of the set_body(...) overloads that takes a string.

Steve
Dec 16, 2014 at 9:24 AM
Hi there

I noticed that the MSDN samples use L"" at http://msdn.microsoft.com/en-us/library/jj950081.aspx

That would be misleading for a large proportion of casablanca users I suspect. Perhaps a change request could be put into MSDN somehow?

James