Merge pull request #523 from MihailRis/http-error-callback

HTTP error callback
This commit is contained in:
MihailRis 2025-04-30 19:45:52 +03:00 committed by GitHub
commit 50aae8b98b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 49 additions and 14 deletions

View File

@ -7,7 +7,8 @@ A library for working with the network.
```lua ```lua
-- Performs a GET request to the specified URL. -- Performs a GET request to the specified URL.
-- After receiving the response, passes the text to the callback function. -- After receiving the response, passes the text to the callback function.
network.get(url: str, callback: function(str)) -- In case of an error, the HTTP response code will be passed to onfailure.
network.get(url: str, callback: function(str), [optional] onfailure: function(int))
-- Example: -- Example:
network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s) network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s)
@ -15,12 +16,13 @@ network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/lat
end) end)
-- A variant for binary files, with a byte array instead of a string in the response. -- A variant for binary files, with a byte array instead of a string in the response.
network.get_binary(url: str, callback: function(table|ByteArray)) network.get_binary(url: str, callback: function(table|ByteArray), [optional] onfailure: function(int))
-- Performs a POST request to the specified URL. -- Performs a POST request to the specified URL.
-- Currently, only `Content-Type: application/json` is supported -- Currently, only `Content-Type: application/json` is supported
-- After receiving the response, passes the text to the callback function. -- After receiving the response, passes the text to the callback function.
network.post(url: str, data: table, callback: function(str)) -- In case of an error, the HTTP response code will be passed to onfailure.
network.post(url: str, data: table, callback: function(str), [optional] onfailure: function(int))
``` ```
## TCP Connections ## TCP Connections

View File

@ -7,7 +7,8 @@
```lua ```lua
-- Выполняет GET запрос к указанному URL. -- Выполняет GET запрос к указанному URL.
-- После получения ответа, передаёт текст в функцию callback. -- После получения ответа, передаёт текст в функцию callback.
network.get(url: str, callback: function(str)) -- В случае ошибки в onfailure будет передан HTTP-код ответа.
network.get(url: str, callback: function(str), [опционально] onfailure: function(int))
-- Пример: -- Пример:
network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s) network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s)
@ -15,12 +16,13 @@ network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/lat
end) end)
-- Вариант для двоичных файлов, с массивом байт вместо строки в ответе. -- Вариант для двоичных файлов, с массивом байт вместо строки в ответе.
network.get_binary(url: str, callback: function(table|ByteArray)) network.get_binary(url: str, callback: function(table|ByteArray), [опционально] onfailure: function(int))
-- Выполняет POST запрос к указанному URL. -- Выполняет POST запрос к указанному URL.
-- На данный момент реализована поддержка только `Content-Type: application/json` -- На данный момент реализована поддержка только `Content-Type: application/json`
-- После получения ответа, передаёт текст в функцию callback. -- После получения ответа, передаёт текст в функцию callback.
network.post(url: str, data: table, callback: function(str)) -- В случае ошибки в onfailure будет передан HTTP-код ответа.
network.post(url: str, data: table, callback: function(str), [опционально] onfailure: function(int))
``` ```
## TCP-Соединения ## TCP-Соединения

View File

@ -12,11 +12,20 @@ static int l_get(lua::State* L, network::Network& network) {
lua::pushvalue(L, 2); lua::pushvalue(L, 2);
auto onResponse = lua::create_lambda_nothrow(L); auto onResponse = lua::create_lambda_nothrow(L);
network::OnReject onReject = nullptr;
if (lua::gettop(L) >= 3) {
lua::pushvalue(L, 3);
auto callback = lua::create_lambda_nothrow(L);
onReject = [callback](int code) {
callback({code});
};
}
network.get(url, [onResponse](std::vector<char> bytes) { network.get(url, [onResponse](std::vector<char> bytes) {
engine->postRunnable([=]() { engine->postRunnable([=]() {
onResponse({std::string(bytes.data(), bytes.size())}); onResponse({std::string(bytes.data(), bytes.size())});
}); });
}); }, std::move(onReject));
return 0; return 0;
} }
@ -26,6 +35,15 @@ static int l_get_binary(lua::State* L, network::Network& network) {
lua::pushvalue(L, 2); lua::pushvalue(L, 2);
auto onResponse = lua::create_lambda_nothrow(L); auto onResponse = lua::create_lambda_nothrow(L);
network::OnReject onReject = nullptr;
if (lua::gettop(L) >= 3) {
lua::pushvalue(L, 3);
auto callback = lua::create_lambda_nothrow(L);
onReject = [callback](int code) {
callback({code});
};
}
network.get(url, [onResponse](std::vector<char> bytes) { network.get(url, [onResponse](std::vector<char> bytes) {
auto buffer = std::make_shared<util::Buffer<ubyte>>( auto buffer = std::make_shared<util::Buffer<ubyte>>(
reinterpret_cast<const ubyte*>(bytes.data()), bytes.size() reinterpret_cast<const ubyte*>(bytes.data()), bytes.size()
@ -33,7 +51,7 @@ static int l_get_binary(lua::State* L, network::Network& network) {
engine->postRunnable([=]() { engine->postRunnable([=]() {
onResponse({buffer}); onResponse({buffer});
}); });
}); }, std::move(onReject));
return 0; return 0;
} }
@ -44,12 +62,22 @@ static int l_post(lua::State* L, network::Network& network) {
lua::pushvalue(L, 3); lua::pushvalue(L, 3);
auto onResponse = lua::create_lambda_nothrow(L); auto onResponse = lua::create_lambda_nothrow(L);
network::OnReject onReject = nullptr;
if (lua::gettop(L) >= 4) {
lua::pushvalue(L, 4);
auto callback = lua::create_lambda_nothrow(L);
onReject = [callback](int code) {
callback({code});
};
}
std::string string; std::string string;
if (data.isString()) { if (data.isString()) {
string = data.asString(); string = data.asString();
} else { } else {
string = json::stringify(data, false); string = json::stringify(data, false);
} }
engine->getNetwork().post(url, string, [onResponse](std::vector<char> bytes) { engine->getNetwork().post(url, string, [onResponse](std::vector<char> bytes) {
auto buffer = std::make_shared<util::Buffer<ubyte>>( auto buffer = std::make_shared<util::Buffer<ubyte>>(
reinterpret_cast<const ubyte*>(bytes.data()), bytes.size() reinterpret_cast<const ubyte*>(bytes.data()), bytes.size()
@ -57,7 +85,7 @@ static int l_post(lua::State* L, network::Network& network) {
engine->postRunnable([=]() { engine->postRunnable([=]() {
onResponse({std::string(bytes.data(), bytes.size())}); onResponse({std::string(bytes.data(), bytes.size())});
}); });
}); }, std::move(onReject));
return 0; return 0;
} }

View File

@ -30,6 +30,9 @@ using SOCKET = int;
using namespace network; using namespace network;
inline constexpr int HTTP_OK = 200;
inline constexpr int HTTP_BAD_GATEWAY = 502;
static debug::Logger logger("network"); static debug::Logger logger("network");
static size_t write_callback( static size_t write_callback(
@ -149,7 +152,7 @@ public:
auto message = curl_multi_strerror(res); auto message = curl_multi_strerror(res);
logger.error() << message << " (" << url << ")"; logger.error() << message << " (" << url << ")";
if (onReject) { if (onReject) {
onReject(message); onReject(HTTP_BAD_GATEWAY);
} }
url = ""; url = "";
} }
@ -164,7 +167,7 @@ public:
auto message = curl_multi_strerror(res); auto message = curl_multi_strerror(res);
logger.error() << message << " (" << url << ")"; logger.error() << message << " (" << url << ")";
if (onReject) { if (onReject) {
onReject(message); onReject(HTTP_BAD_GATEWAY);
} }
curl_multi_remove_handle(multiHandle, curl); curl_multi_remove_handle(multiHandle, curl);
url = ""; url = "";
@ -176,7 +179,7 @@ public:
} }
int response; int response;
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response); curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response);
if (response == 200) { if (response == HTTP_OK) {
long size; long size;
if (!curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &size)) { if (!curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &size)) {
totalUpload += size; totalUpload += size;
@ -191,7 +194,7 @@ public:
} else { } else {
logger.error() << "response code " << response << " (" << url << ")"; logger.error() << "response code " << response << " (" << url << ")";
if (onReject) { if (onReject) {
onReject(std::to_string(response).c_str()); onReject(response);
} }
} }
url = ""; url = "";

View File

@ -11,7 +11,7 @@
namespace network { namespace network {
using OnResponse = std::function<void(std::vector<char>)>; using OnResponse = std::function<void(std::vector<char>)>;
using OnReject = std::function<void(const char*)>; using OnReject = std::function<void(int)>;
class Requests { class Requests {
public: public: