From 9871bf12920abd9bf9f382632b77eb9925292c48 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 8 Sep 2025 23:46:37 +0300 Subject: [PATCH 1/3] add 'headers' argument to network.get, network.get_binary and network.post --- src/logic/scripting/lua/libs/libnetwork.cpp | 45 ++++++++++++++++++--- src/network/Network.cpp | 33 +++++++++++++-- src/network/Network.hpp | 4 ++ 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/logic/scripting/lua/libs/libnetwork.cpp b/src/logic/scripting/lua/libs/libnetwork.cpp index 94390c93..96517c6d 100644 --- a/src/logic/scripting/lua/libs/libnetwork.cpp +++ b/src/logic/scripting/lua/libs/libnetwork.cpp @@ -12,7 +12,7 @@ static int l_get(lua::State* L, network::Network& network) { auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; - if (lua::gettop(L) >= 3) { + if (!lua::isnoneornil(L, 3)) { lua::pushvalue(L, 3); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { @@ -20,11 +20,22 @@ static int l_get(lua::State* L, network::Network& network) { }; } + std::vector headers; + + if (lua::istable(L, 4)) { + int len = lua::objlen(L, 4); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i, 4); + headers.push_back(lua::tostring(L, -1)); + lua::pop(L); + } + } + network.get(url, [onResponse](std::vector bytes) { engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); - }, std::move(onReject)); + }, std::move(onReject), std::move(headers)); return 0; } @@ -35,7 +46,7 @@ static int l_get_binary(lua::State* L, network::Network& network) { auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; - if (lua::gettop(L) >= 3) { + if (!lua::isnoneornil(L, 3)) { lua::pushvalue(L, 3); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { @@ -43,6 +54,17 @@ static int l_get_binary(lua::State* L, network::Network& network) { }; } + std::vector headers; + + if (lua::istable(L, 4)) { + int len = lua::objlen(L, 4); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i, 4); + headers.push_back(lua::tostring(L, -1)); + lua::pop(L); + } + } + network.get(url, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() @@ -50,7 +72,8 @@ static int l_get_binary(lua::State* L, network::Network& network) { engine->postRunnable([=]() { onResponse({buffer}); }); - }, std::move(onReject)); + }, std::move(onReject), std::move(headers)); + return 0; } @@ -62,7 +85,7 @@ static int l_post(lua::State* L, network::Network& network) { auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; - if (lua::gettop(L) >= 4) { + if (!lua::isnoneornil(L, 4)) { lua::pushvalue(L, 4); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { @@ -77,6 +100,16 @@ static int l_post(lua::State* L, network::Network& network) { string = json::stringify(data, false); } + std::vector headers; + if (lua::istable(L, 5)) { + int len = lua::objlen(L, 5); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i, 5); + headers.push_back(lua::tostring(L, -1)); + lua::pop(L); + } + } + engine->getNetwork().post(url, string, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() @@ -84,7 +117,7 @@ static int l_post(lua::State* L, network::Network& network) { engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); - }, std::move(onReject)); + }, std::move(onReject), std::move(headers)); return 0; } diff --git a/src/network/Network.cpp b/src/network/Network.cpp index 234197e4..b0482258 100644 --- a/src/network/Network.cpp +++ b/src/network/Network.cpp @@ -57,6 +57,7 @@ struct Request { long maxSize; bool followLocation = false; std::string data; + std::vector headers; }; class CurlRequests : public Requests { @@ -86,10 +87,18 @@ public: const std::string& url, OnResponse onResponse, OnReject onReject, + std::vector headers, long maxSize ) override { Request request { - RequestType::GET, url, onResponse, onReject, maxSize, false, ""}; + RequestType::GET, + url, + onResponse, + onReject, + maxSize, + false, + "", + std::move(headers)}; processRequest(std::move(request)); } @@ -98,10 +107,18 @@ public: const std::string& data, OnResponse onResponse, OnReject onReject=nullptr, + std::vector headers = {}, long maxSize=0 ) override { Request request { - RequestType::POST, url, onResponse, onReject, maxSize, false, ""}; + RequestType::POST, + url, + onResponse, + onReject, + maxSize, + false, + "", + std::move(headers)}; request.data = data; processRequest(std::move(request)); } @@ -121,6 +138,10 @@ public: curl_easy_setopt(curl, CURLOPT_POST, request.type == RequestType::POST); curl_slist* hs = NULL; + + for (const auto& header : request.headers) { + hs = curl_slist_append(hs, header.c_str()); + } switch (request.type) { case RequestType::GET: @@ -817,9 +838,10 @@ void Network::get( const std::string& url, OnResponse onResponse, OnReject onReject, + std::vector headers, long maxSize ) { - requests->get(url, onResponse, onReject, maxSize); + requests->get(url, onResponse, onReject, std::move(headers), maxSize); } void Network::post( @@ -827,9 +849,12 @@ void Network::post( const std::string& fieldsData, OnResponse onResponse, OnReject onReject, + std::vector headers, long maxSize ) { - requests->post(url, fieldsData, onResponse, onReject, maxSize); + requests->post( + url, fieldsData, onResponse, onReject, std::move(headers), maxSize + ); } Connection* Network::getConnection(u64id_t id) { diff --git a/src/network/Network.hpp b/src/network/Network.hpp index ddde70b5..41ebbe13 100644 --- a/src/network/Network.hpp +++ b/src/network/Network.hpp @@ -25,6 +25,7 @@ namespace network { const std::string& url, OnResponse onResponse, OnReject onReject=nullptr, + std::vector headers = {}, long maxSize=0 ) = 0; @@ -33,6 +34,7 @@ namespace network { const std::string& data, OnResponse onResponse, OnReject onReject=nullptr, + std::vector headers = {}, long maxSize=0 ) = 0; @@ -144,6 +146,7 @@ namespace network { const std::string& url, OnResponse onResponse, OnReject onReject = nullptr, + std::vector headers = {}, long maxSize=0 ); @@ -152,6 +155,7 @@ namespace network { const std::string& fieldsData, OnResponse onResponse, OnReject onReject = nullptr, + std::vector headers = {}, long maxSize=0 ); From 40543128d09d94dc2b1f2e6a28838b7bd4c2457c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 8 Sep 2025 23:56:13 +0300 Subject: [PATCH 2/3] update doc/*/scripting/builtins/libnetwork.md --- doc/en/scripting/builtins/libnetwork.md | 31 +++++++++++++++++++++---- doc/ru/scripting/builtins/libnetwork.md | 31 +++++++++++++++++++++---- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/doc/en/scripting/builtins/libnetwork.md b/doc/en/scripting/builtins/libnetwork.md index a93eaefa..e4e83048 100644 --- a/doc/en/scripting/builtins/libnetwork.md +++ b/doc/en/scripting/builtins/libnetwork.md @@ -6,9 +6,15 @@ 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. --- 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)) +network.get( + url: str, + -- Function to call when response is received + callback: function(str), + -- Error handler + [optional] onfailure: function(int), + -- List of additional request headers + [optional] headers: table +) -- Example: network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s) @@ -16,13 +22,28 @@ 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), [optional] onfailure: function(int)) +network.get_binary( + url: str, + callback: function(table|ByteArray), + [optional] onfailure: function(int), + [optional] headers: table +) -- 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. -- 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)) +network.post( + url: str, + -- Request body as a table (will be converted to JSON) or string + body: table|string, + -- Function called when response is received + callback: function(str), + -- Error handler + [optional] onfailure: function(int), + -- List of additional request headers + [optional] headers: table +) ``` ## TCP Connections diff --git a/doc/ru/scripting/builtins/libnetwork.md b/doc/ru/scripting/builtins/libnetwork.md index c9cc890c..dc960d5c 100644 --- a/doc/ru/scripting/builtins/libnetwork.md +++ b/doc/ru/scripting/builtins/libnetwork.md @@ -6,9 +6,15 @@ ```lua -- Выполняет GET запрос к указанному URL. --- После получения ответа, передаёт текст в функцию callback. --- В случае ошибки в onfailure будет передан HTTP-код ответа. -network.get(url: str, callback: function(str), [опционально] onfailure: function(int)) +network.get( + url: str, + -- Функция, вызываемая при получении ответа + callback: function(str), + -- Обработчик ошибок + [опционально] onfailure: function(int), + -- Список дополнительных заголовков запроса + [опционально] headers: table +) -- Пример: network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/latest", function (s) @@ -16,13 +22,28 @@ network.get("https://api.github.com/repos/MihailRis/VoxelEngine-Cpp/releases/lat end) -- Вариант для двоичных файлов, с массивом байт вместо строки в ответе. -network.get_binary(url: str, callback: function(table|ByteArray), [опционально] onfailure: function(int)) +network.get_binary( + url: str, + callback: function(table|ByteArray), + [опционально] onfailure: function(int), + [опционально] headers: table +) -- Выполняет POST запрос к указанному URL. -- На данный момент реализована поддержка только `Content-Type: application/json` -- После получения ответа, передаёт текст в функцию callback. -- В случае ошибки в onfailure будет передан HTTP-код ответа. -network.post(url: str, data: table, callback: function(str), [опционально] onfailure: function(int)) +network.post( + url: str, + -- Тело запроса в виде таблицы, конвертируемой в JSON или строки + body: table|string, + -- Функция, вызываемая при получении ответа + callback: function(str), + -- Обработчик ошибок + [опционально] onfailure: function(int), + -- Список дополнительных заголовков запроса + [опционально] headers: table +) ``` ## TCP-Соединения From d70e987714a0667a68d4f7d1add345670d566de1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 9 Sep 2025 00:06:25 +0300 Subject: [PATCH 3/3] cleanup --- src/logic/scripting/lua/libs/libnetwork.cpp | 45 ++++++++------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/logic/scripting/lua/libs/libnetwork.cpp b/src/logic/scripting/lua/libs/libnetwork.cpp index 96517c6d..18d26644 100644 --- a/src/logic/scripting/lua/libs/libnetwork.cpp +++ b/src/logic/scripting/lua/libs/libnetwork.cpp @@ -5,6 +5,19 @@ using namespace scripting; +static std::vector read_headers(lua::State* L, int index) { + std::vector headers; + if (lua::istable(L, index)) { + int len = lua::objlen(L, index); + for (int i = 1; i <= len; i++) { + lua::rawgeti(L, i, index); + headers.push_back(lua::tostring(L, -1)); + lua::pop(L); + } + } + return headers; +} + static int l_get(lua::State* L, network::Network& network) { std::string url(lua::require_lstring(L, 1)); @@ -20,16 +33,7 @@ static int l_get(lua::State* L, network::Network& network) { }; } - std::vector headers; - - if (lua::istable(L, 4)) { - int len = lua::objlen(L, 4); - for (int i = 1; i <= len; i++) { - lua::rawgeti(L, i, 4); - headers.push_back(lua::tostring(L, -1)); - lua::pop(L); - } - } + auto headers = read_headers(L, 4); network.get(url, [onResponse](std::vector bytes) { engine->postRunnable([=]() { @@ -54,16 +58,7 @@ static int l_get_binary(lua::State* L, network::Network& network) { }; } - std::vector headers; - - if (lua::istable(L, 4)) { - int len = lua::objlen(L, 4); - for (int i = 1; i <= len; i++) { - lua::rawgeti(L, i, 4); - headers.push_back(lua::tostring(L, -1)); - lua::pop(L); - } - } + auto headers = read_headers(L, 4); network.get(url, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( @@ -100,15 +95,7 @@ static int l_post(lua::State* L, network::Network& network) { string = json::stringify(data, false); } - std::vector headers; - if (lua::istable(L, 5)) { - int len = lua::objlen(L, 5); - for (int i = 1; i <= len; i++) { - lua::rawgeti(L, i, 5); - headers.push_back(lua::tostring(L, -1)); - lua::pop(L); - } - } + auto headers = read_headers(L, 5); engine->getNetwork().post(url, string, [onResponse](std::vector bytes) { auto buffer = std::make_shared>(