diff --git a/doc/en/scripting/builtins/libnetwork.md b/doc/en/scripting/builtins/libnetwork.md index cb24e7bf..a93eaefa 100644 --- a/doc/en/scripting/builtins/libnetwork.md +++ b/doc/en/scripting/builtins/libnetwork.md @@ -7,7 +7,8 @@ A library for working with the network. ```lua -- Performs a GET request to the specified URL. -- 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: 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) -- 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. -- Currently, only `Content-Type: application/json` is supported -- 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 diff --git a/doc/ru/scripting/builtins/libnetwork.md b/doc/ru/scripting/builtins/libnetwork.md index 657ad7cf..0d33acf1 100644 --- a/doc/ru/scripting/builtins/libnetwork.md +++ b/doc/ru/scripting/builtins/libnetwork.md @@ -7,7 +7,8 @@ ```lua -- Выполняет GET запрос к указанному URL. -- После получения ответа, передаёт текст в функцию 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) @@ -15,12 +16,13 @@ network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/lat end) -- Вариант для двоичных файлов, с массивом байт вместо строки в ответе. -network.get_binary(url: str, callback: function(table|ByteArray)) +network.get_binary(url: str, callback: function(table|ByteArray), [опционально] onfailure: function(int)) -- Выполняет POST запрос к указанному URL. -- На данный момент реализована поддержка только `Content-Type: application/json` -- После получения ответа, передаёт текст в функцию 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-Соединения diff --git a/src/logic/scripting/lua/libs/libnetwork.cpp b/src/logic/scripting/lua/libs/libnetwork.cpp index 9a77b843..dc3b5731 100644 --- a/src/logic/scripting/lua/libs/libnetwork.cpp +++ b/src/logic/scripting/lua/libs/libnetwork.cpp @@ -12,11 +12,20 @@ static int l_get(lua::State* L, network::Network& network) { lua::pushvalue(L, 2); 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 bytes) { engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); - }); + }, std::move(onReject)); return 0; } @@ -26,6 +35,15 @@ static int l_get_binary(lua::State* L, network::Network& network) { lua::pushvalue(L, 2); 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 bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() @@ -33,7 +51,7 @@ static int l_get_binary(lua::State* L, network::Network& network) { engine->postRunnable([=]() { onResponse({buffer}); }); - }); + }, std::move(onReject)); return 0; } @@ -44,12 +62,22 @@ static int l_post(lua::State* L, network::Network& network) { lua::pushvalue(L, 3); 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; if (data.isString()) { string = data.asString(); } else { string = json::stringify(data, false); } + engine->getNetwork().post(url, string, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() @@ -57,7 +85,7 @@ static int l_post(lua::State* L, network::Network& network) { engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); - }); + }, std::move(onReject)); return 0; } diff --git a/src/network/Network.cpp b/src/network/Network.cpp index 2268ea67..b88aeed9 100644 --- a/src/network/Network.cpp +++ b/src/network/Network.cpp @@ -30,6 +30,9 @@ using SOCKET = int; using namespace network; +inline constexpr int HTTP_OK = 200; +inline constexpr int HTTP_BAD_GATEWAY = 502; + static debug::Logger logger("network"); static size_t write_callback( @@ -149,7 +152,7 @@ public: auto message = curl_multi_strerror(res); logger.error() << message << " (" << url << ")"; if (onReject) { - onReject(message); + onReject(HTTP_BAD_GATEWAY); } url = ""; } @@ -164,7 +167,7 @@ public: auto message = curl_multi_strerror(res); logger.error() << message << " (" << url << ")"; if (onReject) { - onReject(message); + onReject(HTTP_BAD_GATEWAY); } curl_multi_remove_handle(multiHandle, curl); url = ""; @@ -176,7 +179,7 @@ public: } int response; curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response); - if (response == 200) { + if (response == HTTP_OK) { long size; if (!curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &size)) { totalUpload += size; @@ -191,7 +194,7 @@ public: } else { logger.error() << "response code " << response << " (" << url << ")"; if (onReject) { - onReject(std::to_string(response).c_str()); + onReject(response); } } url = ""; diff --git a/src/network/Network.hpp b/src/network/Network.hpp index 83244094..33461e05 100644 --- a/src/network/Network.hpp +++ b/src/network/Network.hpp @@ -11,7 +11,7 @@ namespace network { using OnResponse = std::function)>; - using OnReject = std::function; + using OnReject = std::function; class Requests { public: