I have a http client that I wrote in python in tornado framework:
http_client = httpclient.HTTPClient()
request = httpclient.HTTPRequest("http://127.0.0.1:8000", method='PUT', body=str("data"))
response = http_client.fetch(request)
on the other side I have an asynchronous server that I wrote in c++ using cpp-netlib. It basically has to read the request and print its body
class Server;
typedef http::async_server<Server> server;
class Server {
public:
void operator()(server::request const & request, server::connection_ptr connection)
{
boost::shared_ptr<connection_handler> h(new connection_handler());
(*h)(request, connection);
server::response_header headers[] = { {"Connection","close"} ,{"Content-Type", "text/plain"} };
connection->set_headers(boost::make_iterator_range(headers, headers+2));
connection->set_status(server::connection::accepted);
connection->write("helloworld");
}
int main()
{
Server handler;
server::options options(handler);
server instance(
options.thread_pool(boost::make_shared<utils::thread_pool>(5))
.address("0.0.0.0")
.port("8000"));
instance.run();
return 0;
}
and the connection handler looks like this:
struct connection_handler : boost::enable_shared_from_this<connection_handler>
{
struct read_post_callback
{
typedef boost::shared_ptr<connection_handler> handler_ptr_t;
read_post_callback(handler_ptr_t handler_ptr) : handler(handler_ptr) {}
void operator()(server::connection::input_range range, boost::system::error_code error, size_t size, server::connection_ptr conn)
{
handler->read_sofar += size;
handler->cond.notify_one();
}
handler_ptr_t handler;
};
void operator()(server::request const &req, server::connection_ptr conn)
{
int cl;
server::request::headers_container_type const &hs = req.headers;
for(server::request::headers_container_type::const_iterator it = hs.begin(); it!=hs.end(); ++it)
{
if(boost::to_lower_copy(it->name)=="content-length")
{
cl = boost::lexical_cast<int>(it->value);
break;
}
}
cout<< req.body << endl;
read_sofar = 0;
while(read_sofar<cl)
{
boost::unique_lock<boost::mutex> lock(mtx);
server::connection::read_callback_function cc = read_post_callback(shared_from_this());
conn->read(cc);
cond.wait(lock);
}
}
int read_sofar;
boost::condition_variable cond;
boost::mutex mtx;
};
But request body is always empty and instead of the response I send back ("hello world") most of the time I get something like this (the number could be different)
Error: HTTP 0: Unknown
Can you tell me why the body is empty or why the response doesn't reach?
EDIT:
Why the body was empty is in the answer. What I was doing wrong that I wouldn't receive the response was this: I was setting the connection status after setting connection headers in my server. Just swapped their order and it worked like a charm.
server::response_header headers[] = { {"Connection","close"} ,{"Content-Type", "text/plain"} };
connection->set_status(server::connection::accepted);
connection->set_headers(boost::make_iterator_range(headers, headers+2));
connection->write("helloworld");
With cpp-netlib, asynchronous reads have to be done as follows. req.body doesn't get loaded with the data read from the asynchronous. So have to have your own holder for data.
Also you may want to change
BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE
defined inboost/network/protocol/http/serversync_connection.hpp
to a higher value so that you can avoid multiple context switches. It is not configurable at present.