How to receive binary data (protobuf) via REST SDK?

4.3k Views Asked by At

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("[email protected]");

// 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;
            }
2

There are 2 best solutions below

0
On BEST ANSWER

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("[email protected]");

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;
};
0
On

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
  }
}