mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-04 18:41:51 +00:00
add HttpResponse
This commit is contained in:
parent
fc877f09cb
commit
58c974a3a1
4 changed files with 108 additions and 63 deletions
|
|
@ -115,16 +115,24 @@ static int l_request(lua::State* L, network::Network& network) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentRequestId = request_id++;
|
int currentRequestId = request_id++;
|
||||||
request.onResponse = [currentRequestId](std::vector<char> bytes) {
|
request.onResponse = [currentRequestId](network::HttpResponse response) {
|
||||||
push_event(NetworkEvent(
|
push_event(NetworkEvent(
|
||||||
RESPONSE,
|
RESPONSE,
|
||||||
ResponseEventDto {200, false, currentRequestId, std::move(bytes)}
|
ResponseEventDto {
|
||||||
|
response.status,
|
||||||
|
false,
|
||||||
|
currentRequestId,
|
||||||
|
std::move(response.body)}
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
request.onReject = [currentRequestId](int code, std::vector<char> bytes) {
|
request.onReject = [currentRequestId](network::HttpResponse response) {
|
||||||
push_event(NetworkEvent(
|
push_event(NetworkEvent(
|
||||||
RESPONSE,
|
RESPONSE,
|
||||||
ResponseEventDto {code, false, currentRequestId, std::move(bytes)}
|
ResponseEventDto {
|
||||||
|
response.status,
|
||||||
|
false,
|
||||||
|
currentRequestId,
|
||||||
|
std::move(response.body)}
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,28 @@ static size_t write_callback(
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t header_callback(
|
||||||
|
char* buffer, size_t size, size_t nitems, void* userdata
|
||||||
|
) {
|
||||||
|
auto* headers = static_cast<std::vector<std::string>*>(userdata);
|
||||||
|
size_t len = size * nitems;
|
||||||
|
std::string header(buffer, len);
|
||||||
|
|
||||||
|
while (!header.empty() &&
|
||||||
|
(header.back() == '\r' || header.back() == '\n')) {
|
||||||
|
header.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
headers->push_back(std::move(header));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
struct ProcessingRequest {
|
struct ProcessingRequest {
|
||||||
CURLM* multiHandle;
|
CURLM* multiHandle;
|
||||||
CURL* curl;
|
CURL* curl;
|
||||||
HttpRequest request;
|
HttpRequest request;
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
|
std::vector<std::string> headers;
|
||||||
|
|
||||||
ProcessingRequest(CURLM* multiHandle) : multiHandle(multiHandle) {
|
ProcessingRequest(CURLM* multiHandle) : multiHandle(multiHandle) {
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
|
|
@ -81,6 +98,8 @@ public:
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, request.followLocation);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, request.followLocation);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &entry->buffer);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &entry->buffer);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &entry->headers);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.81.0");
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.81.0");
|
||||||
if (request.timeoutMs > 0) {
|
if (request.timeoutMs > 0) {
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, request.timeoutMs);
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, request.timeoutMs);
|
||||||
|
|
@ -102,7 +121,7 @@ public:
|
||||||
auto message = curl_multi_strerror(res);
|
auto message = curl_multi_strerror(res);
|
||||||
logger.error() << message << " (" << request.url << ")";
|
logger.error() << message << " (" << request.url << ")";
|
||||||
if (request.onReject) {
|
if (request.onReject) {
|
||||||
request.onReject(HTTP_BAD_GATEWAY, {});
|
request.onReject({HTTP_BAD_GATEWAY, {}, {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry->request = std::move(request);
|
entry->request = std::move(request);
|
||||||
|
|
@ -112,69 +131,78 @@ public:
|
||||||
void update() override {
|
void update() override {
|
||||||
int messagesLeft;
|
int messagesLeft;
|
||||||
int running;
|
int running;
|
||||||
CURLMsg* msg;
|
|
||||||
CURLMcode res = curl_multi_perform(multiHandle, &running);
|
CURLMcode res = curl_multi_perform(multiHandle, &running);
|
||||||
if (res != CURLM_OK) {
|
if (res != CURLM_OK) {
|
||||||
auto message = curl_multi_strerror(res);
|
auto message = curl_multi_strerror(res);
|
||||||
logger.error() << message;
|
logger.error() << message;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((msg = curl_multi_info_read(multiHandle, &messagesLeft)) != nullptr) {
|
CURLMsg* msg = curl_multi_info_read(multiHandle, &messagesLeft);
|
||||||
auto curl = msg->easy_handle;
|
if (msg == nullptr) {
|
||||||
auto found = std::find_if(
|
return;
|
||||||
requests.begin(), requests.end(),
|
}
|
||||||
[curl](const std::unique_ptr<ProcessingRequest>& entry) {
|
auto curl = msg->easy_handle;
|
||||||
return entry->curl == curl;
|
auto found = std::find_if(
|
||||||
}
|
requests.begin(),
|
||||||
);
|
requests.end(),
|
||||||
if (found == requests.end()) {
|
[curl](const std::unique_ptr<ProcessingRequest>& entry) {
|
||||||
logger.error() << "could not find request for cURL handle";
|
return entry->curl == curl;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
auto entry = std::move(*found);
|
);
|
||||||
auto& req = entry->request;
|
if (found == requests.end()) {
|
||||||
|
logger.error() << "could not find request for cURL handle";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto entry = std::move(*found);
|
||||||
|
auto& req = entry->request;
|
||||||
|
|
||||||
requests.erase(found);
|
requests.erase(found);
|
||||||
|
|
||||||
if(msg->msg == CURLMSG_DONE) {
|
if (msg->msg == CURLMSG_DONE) {
|
||||||
curl_multi_remove_handle(multiHandle, curl);
|
curl_multi_remove_handle(multiHandle, curl);
|
||||||
|
}
|
||||||
|
int response = -1;
|
||||||
|
CURLcode result = msg->data.result;
|
||||||
|
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response);
|
||||||
|
auto headers = std::move(entry->headers);
|
||||||
|
if (response == HTTP_OK) {
|
||||||
|
long size;
|
||||||
|
if (!curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &size)) {
|
||||||
|
totalUpload += size;
|
||||||
}
|
}
|
||||||
int response = -1;
|
if (!curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size)) {
|
||||||
CURLcode result = msg->data.result;
|
totalDownload += size;
|
||||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response);
|
}
|
||||||
if (response == HTTP_OK) {
|
totalDownload += entry->buffer.size();
|
||||||
long size;
|
if (req.onResponse) {
|
||||||
if (!curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &size)) {
|
req.onResponse({
|
||||||
totalUpload += size;
|
response,
|
||||||
}
|
std::move(headers),
|
||||||
if (!curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size)) {
|
std::move(entry->buffer),
|
||||||
totalDownload += size;
|
});
|
||||||
}
|
}
|
||||||
totalDownload += entry->buffer.size();
|
} else if (response == 0) {
|
||||||
if (req.onResponse) {
|
auto message = std::string(curl_easy_strerror(result));
|
||||||
req.onResponse(std::move(entry->buffer));
|
logger.error() << message << " (" << req.url << ")";
|
||||||
}
|
if (req.onReject) {
|
||||||
} else if (response == 0) {
|
req.onReject(
|
||||||
auto message = std::string(curl_easy_strerror(result));
|
{response,
|
||||||
logger.error() << message << " (" << req.url << ")";
|
std::move(headers),
|
||||||
if (req.onReject) {
|
std::vector<char>(
|
||||||
req.onReject(
|
message.data(), message.data() + message.size()
|
||||||
response,
|
)}
|
||||||
std::vector<char>(
|
);
|
||||||
message.data(), message.data() + message.size()
|
}
|
||||||
)
|
} else {
|
||||||
);
|
logger.error() << "response code " << response << " (" << req.url
|
||||||
}
|
<< ")"
|
||||||
} else {
|
<< (entry->buffer.empty()
|
||||||
logger.error()
|
? ""
|
||||||
<< "response code " << response << " (" << req.url << ")"
|
: std::to_string(entry->buffer.size()) +
|
||||||
<< (entry->buffer.empty()
|
" byte(s)");
|
||||||
? ""
|
totalDownload += entry->buffer.size();
|
||||||
: std::to_string(entry->buffer.size()) + " byte(s)");
|
if (req.onReject) {
|
||||||
totalDownload += entry->buffer.size();
|
req.onReject({response, {}, std::move(entry->buffer)});
|
||||||
if (req.onReject) {
|
|
||||||
req.onReject(response, std::move(entry->buffer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace network {
|
namespace network {
|
||||||
using OnResponse = std::function<void(std::vector<char>)>;
|
struct HttpResponse;
|
||||||
using OnReject = std::function<void(int, std::vector<char>)>;
|
|
||||||
|
using OnResponse = std::function<void(HttpResponse)>;
|
||||||
|
using OnReject = std::function<void(HttpResponse)>;
|
||||||
using ConnectCallback = std::function<void(u64id_t, u64id_t)>;
|
using ConnectCallback = std::function<void(u64id_t, u64id_t)>;
|
||||||
using ConnectErrorCallback = std::function<void(u64id_t, std::string)>;
|
using ConnectErrorCallback = std::function<void(u64id_t, std::string)>;
|
||||||
using ServerDatagramCallback = std::function<void(u64id_t sid, const std::string& addr, int port, const char* buffer, size_t length)>;
|
using ServerDatagramCallback = std::function<void(u64id_t sid, const std::string& addr, int port, const char* buffer, size_t length)>;
|
||||||
|
|
@ -31,6 +33,12 @@ namespace network {
|
||||||
long timeoutMs = 0;
|
long timeoutMs = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HttpResponse {
|
||||||
|
int status;
|
||||||
|
std::vector<std::string> headers;
|
||||||
|
std::vector<char> body;
|
||||||
|
};
|
||||||
|
|
||||||
class Requests {
|
class Requests {
|
||||||
public:
|
public:
|
||||||
virtual ~Requests() {}
|
virtual ~Requests() {}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,12 @@ TEST(curltest, curltest) {
|
||||||
network::HttpRequest request {};
|
network::HttpRequest request {};
|
||||||
request.url = "https://raw.githubusercontent.com/MihailRis/VoxelEngine-Cpp/refs/"
|
request.url = "https://raw.githubusercontent.com/MihailRis/VoxelEngine-Cpp/refs/"
|
||||||
"heads/curl/res/content/base/blocks/lamp.json";
|
"heads/curl/res/content/base/blocks/lamp.json";
|
||||||
request.onResponse = [](std::vector<char> data) {
|
request.onResponse = [](network::HttpResponse response) {
|
||||||
if (data.empty()) {
|
if (response.body.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto view = std::string_view(data.data(), data.size());
|
auto view =
|
||||||
|
std::string_view(response.body.data(), response.body.size());
|
||||||
auto value = json::parse(view);
|
auto value = json::parse(view);
|
||||||
std::cout << value << std::endl;
|
std::cout << value << std::endl;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue