Reputation: 6768
I use the basic example from boost::asio to connect to an enpoint and get back a json reponse. Here is the code
boost::asio::streambuf response;
boost::asio::read_until(socket_, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
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/") {
LOG_ERROR << "invalid response";
return -1;
}
resp_status_code_ = status_code;
resp_status_code_ = status_code;
if (status_code != 200) {
LOG_ERROR << "response did not returned 200 but " << status_code;
return -1;
}
//read until the response headers termination
boost::asio::read_until(socket_, response, "\r\n\r\n");
//read the headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r") {
;
}
std::ostringstream ostringstream_content;
if (response.size() > 0)
ostringstream_content << &response;
boost::system::error_code error;
boost::system::error_code error;
while (true) {
size_t n = boost::asio::read(socket_, response, boost::asio::transfer_at_least(1), error);
if (!error)
{
if (n)
ostringstream_content << &response;
}
if (error == boost::asio::error::eof)
break;
if (error)
return -1; //throw boost::system::system_error(error);
}
str_response_ = ostringstream_content.str();
However when the string returns back I am reading this
1 [5a0
2 {"a_token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030"}
3 0
4
5 ]
The [ and ] are marks from my code to debug the begin and end of data correspondingly. I have more than one lines, 3 problematic characters at the first line, ie 5a0, the json string in the second line which is correct and then a zero and a blank line. How can I get exactly the json string only?
Upvotes: 0
Views: 739
Reputation: 6901
I reworked on your example and it works fine for me. Note that I have made few shortcuts for reading the response. I am reading the status line and the header in one shot instead of reading separately (purely out of laziness)
#include <asio.hpp>
#include <iostream>
#include <sstream>
#include <istream>
int main(int argc, const char * argv[]) {
static asio::io_service ios;
asio::ip::tcp::endpoint
endpoint(asio::ip::address::from_string("127.0.0.1"), 8000);
asio::generic::stream_protocol::socket socket{ios};
socket.connect(endpoint);
std::string req = "GET /api\n\r\n\r\n";
std::error_code ec;
socket.write_some(asio::buffer(req, req.size()), ec);
std::cout << "Request sent" << std::endl;
if (ec == asio::error::eof) {
std::cerr << "Premature termination\n";
return 1;
}
//while (true) {
{
asio::streambuf response;
// Get till all the headers
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 << "V : " << 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;
}
std::ostringstream ostringstream_content;
if (response.size() > 0) {
ostringstream_content << &response;
}
std::error_code error;
while (true) {
size_t n = asio::read(socket, response, asio::transfer_at_least(1), error);
if (!error) {
if (n) {
ostringstream_content << &response;
}
}
if (error == asio::error::eof) {
break;
}
if (error) {
return -1; //throw boost::system::system_error(error);
}
}
auto str_response = ostringstream_content.str();
std::cout << str_response << std::endl;
}
//}
return 0;
}
And my python server for test:
Python 2.7.10 (default, Jul 14 2015, 19:46:27)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket as s
>>> sd = s.socket(s.AF_INET, s.SOCK_STREAM)
>>> sd.bind(("127.0.0.1", 8000))
>>> sd.listen(1)
>>> c, a = sd.accept()
>>> resp = "HTTP/1.1 200 OK\nDate: Fri, 31 Dec 1999 23:59:59 GMT\nContent-Type: text/plain\nTransfer-Encoding: chunked\n\r\n\r\n{\"token\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030\"}"
>>> c.send(resp)
173
>>> exit()
ASIO output:
MacBook-Pro:asio_test amuralid$ ./json_read_so
Request sent
V : HTTP/1.1
H: Date: Fri, 31 Dec 1999 23:59:59 GMT
H: Content-Type: text/plain
H: Transfer-Encoding: chunked
{"token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030"}
Upvotes: 1