asio icon indicating copy to clipboard operation
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

Open ghost opened this issue 4 years ago • 1 comments

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;

ghost avatar Mar 23 '21 08:03 ghost