Ошибка говорит вам, что response
объекты не могут быть скопированы, и что вы пытаетесь сделать именно это.
struct response {
std::istream& is; // can't be copied: istream( const istream&) = delete;
Poco::Net::HTTPResponse& response; // also not copyable or movable
};
Однако в коде, который вы показали, нет ничего, что пытаетсясделайте это.
receiveResponse()
возвращает ссылку на std::istream
, что становится проблематичным в случае его выброса. Когда вы ловите исключение, вам нечего возвращать, поэтому вы не можете - и входите в страну неопределенного поведения.
Вы также можете прочитать данные в лямбде async
и сохранить их. в вашем RES
напрямую.
#include <Poco/Exception.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/Net/SecureStreamSocket.h>
#include <Poco/URI.h>
#include <future>
#include <iostream>
#include <map>
#include <vector>
#include <memory>
// a slightly modified version of your RES struct
struct RES {
std::vector<std::string> data{}; // the document data
// using a unique_ptr to make HTTPResponse easier to move
std::unique_ptr<Poco::Net::HTTPResponse>
response = std::make_unique<Poco::Net::HTTPResponse>();
bool ok = false; // if reading was done without an exception
};
class HttpClient {
public:
static std::future<RES> get(Poco::Net::HTTPSClientSession& session,
Poco::URI url,
std::map<std::string, std::string> headers = {});
};
std::future<RES> HttpClient::get(Poco::Net::HTTPSClientSession& session,
Poco::URI url,
std::map<std::string, std::string> headers) {
return std::async(std::launch::async, [&session, url, headers]() {
RES res;
try {
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
url.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
// add request headers
for(const auto&[field, value]: headers)
request.add(field, value);
session.sendRequest(request);
std::istream& is = session.receiveResponse(*res.response);
// read document data
std::string line;
while(std::getline(is, line))
res.data.push_back(line);
res.ok = true; // reading was done without an exception
} catch(Poco::Exception& exc) {
std::cout << exc.displayText().c_str() << "\n";
}
// always return according to what you declared
return res;
});
}
Пример использования:
class SSLInitializer {
public:
SSLInitializer() { Poco::Net::initializeSSL(); }
~SSLInitializer() { Poco::Net::uninitializeSSL(); }
};
int main() {
SSLInitializer sslInitializer;
Poco::URI uri{"https://www.google.com/"};
const Poco::Net::Context::Ptr context = new Poco::Net::Context(
Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE, 9,
false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
Poco::Net::HTTPSClientSession sess(uri.getHost(), uri.getPort(), context);
std::future<RES> fut_res = HttpClient::get(sess, uri);
fut_res.wait();
RES res = fut_res.get();
std::cout << std::boolalpha << "Response OK: " << res.ok << "\n---\n";
if(res.ok) {
Poco::Net::HTTPResponse& header = *res.response
std::cout << "HTTPResponse header:\n";
for(const auto& [field, value] : header) {
std::cout << field << " = " << value << "\n";
}
std::cout << "--- DOCUMENT DATA ---\n";
for(const auto& s : res.data) {
std::cout << s << "\n";
}
}
}