0

I try to send and receive a protobuf object by using Microsoft REST SDK. If you are not familiar with protobuf, imagine that it can be any other raw data. On the client side the vector is empty. I think that I do not create correctly the streams on the server side.

The get method of the server looks like this:

void MyServer::handle_get(http_request message)
{
// a class created with protobuf
ns::user *user = new ns::user();
ns::user->set_id(-1);
ns::user->set_name("Dark");
ns::user->set_email("dark@foo.com");

// this schould be fine
int size = user->ByteSize();
void *buffer = malloc(size);
user->SerializeToArray(buffer, size);

// how to do?
concurrency::streams::container_buffer<std::vector<char>> inBuffer;
concurrency::streams::istream bodyStream = message.body();
inBuffer.putn((char*)buffer, size);
Concurrency::task<size_t> read = bodyStream.read_to_end(inBuffer);

message.reply(status_codes::OK, bodyStream, size, L"application/octet-stream");
delete user;
};

The client method like this:

    utility::ostringstream_t buf;
    buf << "Dark" << "/" << "Foo" << "?" << "id=" << "1";
    http_response response = CheckResponse("server/user", server.request(methods::GET, buf.str()).get());
        if (response.status_code() == status_codes::OK)
        {
            cout << "STATUS OK" << endl;

            Concurrency::streams::istream iStream = response.body();

            auto rslt0 = response.extract_vector();
            auto rslt = rslt0.get();
            cout << "Result has size: <" << rslt.size() << ">" << endl;
            for (unsigned int i = 0; i < rslt.size(); i++)
            {
                cout << "Data" << i << ": <" << rslt.at(i) << ">" << endl;
            }
Dark Foo
  • 11
  • 1
  • 3

2 Answers2

2

Server side:

std::vector<uint8_t> data;
//TODO: fill data
//convert the vector into a async istream
auto instream = Concurrency::streams::bytestream::open_istream(data);
message.reply(status_codes::OK, instream);

Client side:

wchar_t urlbuf[256];
//TODO: fill the url
client->request(web::http::methods::GET,urlbuf).then([](web::http::http_response& resp){
  if(resp.status_code() != status_codes::OK){
      DLogError("error: status != ok");                   
      return;                
  }
  Concurrency::streams::container_buffer<std::vector<uint8_t> >inBuffer;
  resp.body().read_to_end(inBuffer).then([](size_t bytesRead){
   //TODO: use it
  }
}
Changming Sun
  • 857
  • 2
  • 7
  • 19
1

I answer my own question. There is no need for stream; I can use the binary data by this way:

Server:

void MyServer::handle_get(http_request message)
{
// a class created with protobuf
ns::user *user = new ns::user();
ns::user->set_id(-1);
ns::user->set_name("Dark");
ns::user->set_email("dark@foo.com");

int size = user->ByteSize();
unsigned char *buffer = new unsigned char(size);

user->SerializeToArray(buffer, size);
std::string out;
user->SerializeToString(&out);

std::vector<unsigned char> data(buffer, buffer + size);
string_t outT = utility::conversions::to_base64(data);
message.reply(status_codes::OK, outT);
delete user;
};

Client:

utility::ostringstream_t buf;
buf << "Dark" << "/" << "Foo" << "?" << "id=" << "1";
http_response response = CheckResponse("server/user", server.request(methods::GET, buf.str()).get());
    if (response.status_code() == status_codes::OK)
    {
        cout << "STATUS OK" << endl;
            geopp::gnUser *user = new geopp::gnUser();

            auto rslt = response.extract_string();
            auto rslt0 = utility::conversions::from_base64(rslt.get());
            user->ParseFromArray(rslt0.data(), rslt0.size());

            cout << "Result: name <" << user->name() << ">, id <" <<   user->id() << ">" << endl;
};
Dark Foo
  • 11
  • 1
  • 3