- Updated file handling to ensure proper opening in binary mode for reading, addressing issues with the PhysFS backend. - Refactored audio source management by renaming and consolidating stream unregistration methods to prevent potential deadlocks. - Enhanced mouse position handling to ensure reliable updates in SDL, particularly when window focus is lost. - Added new tests for filesystem operations and HTTP request handling, including verification of SSL behavior in HTTPS requests.
117 lines
4.1 KiB
C++
117 lines
4.1 KiB
C++
#include "network/HttpRequest.h"
|
|
#include "network/Network.h"
|
|
#include "network/NetWorker.h"
|
|
#include "data/ByteData.h"
|
|
|
|
#include <Poco/URI.h>
|
|
#include <Poco/Timespan.h>
|
|
#include <Poco/Net/HTTPClientSession.h>
|
|
#include <Poco/Net/HTTPRequest.h>
|
|
#include <Poco/Net/HTTPResponse.h>
|
|
#include <Poco/StreamCopier.h>
|
|
#include <Poco/Exception.h>
|
|
|
|
#include <sstream>
|
|
#include <thread>
|
|
|
|
namespace eve::network {
|
|
|
|
HttpRequest::HttpRequest(Network* net, std::string method, std::string url)
|
|
: net_(net), method_(std::move(method)), url_(std::move(url)) {}
|
|
|
|
void HttpRequest::setHeader(std::string k, std::string v) {
|
|
headers_[std::move(k)] = std::move(v);
|
|
}
|
|
|
|
void HttpRequest::setBody(eve::data::ByteData* data) {
|
|
if (!data) {
|
|
body_.reset();
|
|
return;
|
|
}
|
|
body_ = std::make_shared<std::vector<char>>(
|
|
static_cast<char*>(data->getData()),
|
|
static_cast<char*>(data->getData()) + data->getSize());
|
|
}
|
|
|
|
void HttpRequest::setBodyString(std::string s) {
|
|
body_ = std::make_shared<std::vector<char>>(s.begin(), s.end());
|
|
}
|
|
|
|
void HttpRequest::setTimeout(int ms) {
|
|
timeoutMs_ = ms;
|
|
}
|
|
|
|
void HttpRequest::setVerifySsl(bool verify) {
|
|
verifySsl_ = verify ? 1 : 0;
|
|
}
|
|
|
|
bool HttpRequest::submit() {
|
|
if (!net_) return false;
|
|
auto* self = this;
|
|
auto method = method_;
|
|
auto url = url_;
|
|
auto headers = headers_;
|
|
auto body = body_;
|
|
int timeoutMs = timeoutMs_ >= 0 ? timeoutMs_ : net_->getTimeout();
|
|
// -1 = inherit Network default; request-level setVerifySsl overrides.
|
|
const bool verifySsl = verifySsl_ < 0 ? net_->getVerifySsl() : (verifySsl_ != 0);
|
|
|
|
// Dedicated thread: HTTP would block NetWorker and prevent accept/poll.
|
|
std::thread([self, method, url, headers, body, timeoutMs, verifySsl]() {
|
|
NetCompletion c;
|
|
c.kind = NetKind::Http;
|
|
c.handle = self;
|
|
try {
|
|
Poco::URI uri(url);
|
|
if (uri.getScheme() == "https") {
|
|
// TLS stack (Poco NetSSL) is not linked yet; honor verifySsl once HTTPS is enabled.
|
|
(void)verifySsl;
|
|
c.type = NetEvType::Err;
|
|
c.reason = "tls";
|
|
self->net_->post(std::move(c));
|
|
return;
|
|
}
|
|
Poco::Net::HTTPClientSession session(uri.getHost(), uri.getPort());
|
|
session.setTimeout(Poco::Timespan(timeoutMs / 1000, (timeoutMs % 1000) * 1000));
|
|
std::string path = uri.getPathAndQuery();
|
|
if (path.empty()) path = "/";
|
|
Poco::Net::HTTPRequest req(method, path, Poco::Net::HTTPMessage::HTTP_1_1);
|
|
req.setHost(uri.getHost());
|
|
for (auto& kv : headers) req.set(kv.first, kv.second);
|
|
if (body && !body->empty()) {
|
|
req.setContentLength(static_cast<std::streamsize>(body->size()));
|
|
}
|
|
std::ostream& os = session.sendRequest(req);
|
|
if (body && !body->empty()) {
|
|
os.write(body->data(), static_cast<std::streamsize>(body->size()));
|
|
}
|
|
Poco::Net::HTTPResponse resp;
|
|
std::istream& rs = session.receiveResponse(resp);
|
|
std::ostringstream oss;
|
|
Poco::StreamCopier::copyStream(rs, oss);
|
|
std::string content = oss.str();
|
|
c.type = NetEvType::HttpResp;
|
|
c.status = static_cast<int>(resp.getStatus());
|
|
c.bytes = std::make_shared<std::vector<char>>(content.begin(), content.end());
|
|
self->net_->post(std::move(c));
|
|
} catch (const Poco::Exception& ex) {
|
|
c.type = NetEvType::Err;
|
|
std::string msg = ex.displayText();
|
|
if (msg.find("timed") != std::string::npos || msg.find("Timeout") != std::string::npos)
|
|
c.reason = "timeout";
|
|
else if (msg.find("host") != std::string::npos || msg.find("DNS") != std::string::npos)
|
|
c.reason = "dns";
|
|
else
|
|
c.reason = "refused";
|
|
self->net_->post(std::move(c));
|
|
} catch (...) {
|
|
c.type = NetEvType::Err;
|
|
c.reason = "refused";
|
|
self->net_->post(std::move(c));
|
|
}
|
|
}).detach();
|
|
return true;
|
|
}
|
|
|
|
} // namespace eve::network
|