asio
asio copied to clipboard
Question: I tried to consume a Rest API which response was a chunked binary with the code below, but it doesn't work
I tried to consume a Rest API which response like the below
the response was like
x-proxy-by: Tif-APIGate
Set-Cookie: XSRF-TOKEN=ebcf70d2-8b00-46b9-a8f9-6dcbbc535ee9; Path=/
Content-Disposition: attachment; filename="202012303333629003180526491.txt.zip"
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Content-Type: application/octet-stream;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 23 Mar 2021 02:34:38 GMT
connection: Close
x-tif-nonce: kmlen6de-122075580
2a4
PK
and I tried to read the response with code below ,it's not working on the line which boost::asio::read(socket,response, boost::asio::transfer_exactly(chunk_bytes_to_read)); it occured exception which was 'end of file' excption, , any idea what wrong I have done? thank you so much
boost::asio::io_service io_service;
// Get a list of endpoints corresponding to the server name.
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(host, port);
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "POST " << target << " HTTP/1.1\r\n";
request_stream << "Host: " << host << "\r\n";
request_stream << "Accept: " << acceptwstr << "\r\n";
request_stream << "Content-Type: " << ContentTypewstr << "\r\n";
request_stream << "Content-Length: " << jsondata.length() << "\r\n";
request_stream << "x-tif-paasid: " << accessKey << "\r\n";
request_stream << "x-tif-timestamp: " << msecondstr << "\r\n";
request_stream << "x-tif-nonce: " << uuidstr << "\r\n";
request_stream << "x-tif-signature: " << signature << "\r\n";
request_stream << "Connection: Close\r\n\r\n";
request_stream << jsondata << "\r\n";
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
// Get till all the headers
boost::asio::read_until(socket, response, "\r\n\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
std::cout << "Version : " << http_version << std::endl;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
std::cerr << "invalid response";
return -1;
}
if (status_code != 200) {
std::cerr << "response did not returned 200 but " << status_code;
return -1;
}
//read the headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r") {
std::cout << "H: " << header << std::endl;
}
bool chunk_size_present = false;
std::string chunk_siz_str;
// Ignore the remaining additional '\r\n' after the header
std::getline(response_stream, header);
// Read the Chunk size
boost::asio::read_until(socket, response, "\r\n");
std::getline(response_stream, chunk_siz_str);
std::cout << "CS : " << chunk_siz_str << std::endl;
size_t chunk_size = (int)strtol(chunk_siz_str.c_str(), nullptr, 16);
// Now how many bytes yet to read from the socket ?
// response might have some additional data still with it
// after the last `read_until`
auto chunk_bytes_to_read = chunk_size - response.size();
std::cout << "Chunk Length = " << chunk_size << std::endl;
std::cout << "Additional bytes to read: " << response_stream.gcount() << std::endl;
std::error_code error;
size_t n = boost::asio::read(socket,response, boost::asio::transfer_exactly(chunk_bytes_to_read));// exception ocrred in this link which occred end of file exception
if (error) {
return -1; //throw boost::system::system_error(error);
}
std::ostringstream ostringstream_content;
ostringstream_content << &response;
auto str_response = ostringstream_content.str();
std::cout << str_response << std::endl;
}
catch (std::exception& e)
{
write_text_to_log_file(e.what());
return 9001;
}
return 0;