Description
It is allowed in HTTP 1.0 to have no "Content-Length" header field in the response-header: In this case closing of the connection indicates the end of the response-body. But in the current implementation reading the body of the response is skipped if there is no "Content-Length" field, resulting into an empty body.
The template function read_content(Stream& strm, T& x)
is used for the server (handle request) and for the client (handle response), but the handling for no "Content-Length" should only be applied to the response.
An example which demonstrates the problem (openssl-1.0.2l, Windows, Visual Studio 2017):
#include <iostream>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
int main(int argc, char* argv[]) {
httplib::SSLClient cli("bittrex.com", 443);
auto res = cli.get("/api/v1.1/public/getmarkets");
if (res && res->status == 200) {
std::cout << res->body << std::endl;
}
return 0;
}
I have created a template specialization for Response
which will work (but is maybe not optimal, because it adds bytes to the body one-by-one, similar to socket_gets
).
bool read_content(Stream& strm, Response& x)
{
auto len = get_header_value_int(x.headers, "Content-Length", 0);
if (len) {
x.body.assign(len, 0);
auto r = 0;
while (r < len) {
auto r_incr = strm.read(&x.body[r], len - r);
if (r_incr <= 0) {
return false;
}
r += r_incr;
}
} else { /* Start Added code */
for (;;) {
char byte;
auto n = strm.read(&byte, 1);
if (n < 1) {
if (x.body.size() == 0) {
return true; // no body
}
else {
break;
}
}
x.body += byte;
}
} /* End Added code */
return true;
}