Гайд Асинхронные HTTP запросы через Lua C API

delanov

Участник
Автор темы
47
46
Базовые HTTP запросы для выполнениях неблокирующих HTTP-запросов с обработкой ответов через функции обратного вызова (callbacks). Он поддерживает настройку параметров запроса (например, заголовки, таймауты, настройки SSL) и включает минимальный JSON-парсер для обработки ответов. Модуль потокобезопасен благодаря использованию mutex для выполнения калбэков в основном потоке Lua.

Основные преимущества:
Асинхронные запросы: Выполнение HTTP-запросов без блокировки Lua потока.
Настраиваемые параметры: Поддержка методов, заголовков, тела запроса, таймаутов, SSL и других опций.
Парсинг JSON: Встроенный минимальный JSON-парсер, поддерживающий объекты, массивы, строки, числа, булевы значения и null.
Потокобезопасность: Использование мьютекса для защиты очереди калбэков, и выполнения их в основном потоке.
Загрузка файлов: Поддержка multipart/form-data для отправки файлов на сервер.


Модуль предоставляет базовый набор параметров для настройки HTTP-запросов. Модуль извлекает следующие поля из таблицы:

ПолеОписание
methodHTTP-метод (GET, POST, PUT, DELETE и др.)
headersТаблица HTTP-заголовков: { ["Content-Type"] = "application/json" }
bodyТело запроса (например, JSON-строка)
timeoutТаймаут в секундах
follow_redirectsСледовать ли редиректам (true/false)
proxyАдрес прокси (http://proxy:8080)
verify_sslПроверять SSL-сертификаты (true/false)
ca_certПуть к CA-сертификату
client_certПуть к клиентскому сертификату
client_keyПуть к приватному ключу клиента
query_paramsТаблица для GET-параметров: { key1 = "value1" }
filesТаблица файлов для отправки: { ["file"] = "path/to/file.txt" }


Базовый пример использования:
local http = require("HTTP_ASYNC")

http.http_async_request("https://jsonplaceholder.typicode.com/posts/1", function(response)
    if response.error then
        print("Ошибка GET: " .. response.error)
    else
        print("GET Статус: " .. response.status)
        print("GET Данные: ")
        for key, value in pairs(response.data) do
            print(key .. ": " .. tostring(value))
        end
    end
end, {
    method = "GET",
    headers = { ["Content-Type"] = "application/json" },
    timeout = 10
})

http.http_async_request("https://jsonplaceholder.typicode.com/posts", function(response)
    if response.error then
        print("Ошибка POST: " .. response.error)
    else
        print("POST Статус: " .. response.status)
        print("POST Данные: ")
        for key, value in pairs(response.data) do
            print(key .. ": " .. tostring(value))
        end
    end
end, {
    method = "POST",
    headers = { ["Content-Type"] = "application/json" },
    body = '{"title":"foo","body":"bar","userId":1}',
    timeout = 10
})

http.http_async_request("https://api.example.com", callback, {
    method = "POST",
    headers = {
        ["Content-Type"] = "application/json",
        ["Authorization"] = "Bearer token123"
    },
    body = '{"data":"test"}',
    timeout = 15,
    follow_redirects = true,
    verify_ssl = true,
    proxy = "http://proxy:8080",
    ca_cert = "path/to/ca.pem",
    client_cert = "path/to/client.pem",
    client_key = "path/to/key.pem",
    query_params = { key1 = "value1", key2 = "value2" },
    files = { ["file"] = "path/to/file.txt" }
})

local running = true
while running do
    http.http_async_process_callbacks()
end

function onScriptTerminate(script, quitGame)
    if script == thisScript() then
        http.http_async_cleanup()
    end
end

Lua:
http.http_async_process_callbacks()
используется для проверки на наличие ответов в очередях "queue". Таймаута встроенного нету, поэтому ответ может лежать хоть всю сессию скрипта. На остановке работы скрипта стоит вызвать
Lua:
http.http_async_clean()
чтобы избежать утечек памяти.

Используется MSVC C++ 2015 года.
Требуется ОС минимум Windows 7 32-bit.
Для HTTP запросов используется libcurl.
Самая частая ошибка которую можно заметить "Не является приложением Win32". Для этого установите Visual C++ Redistributable х86 от 2022 до 2013 года.
Если не будет проблем с использованием, то расширю функционал библиотеки, в противном случае снесу эту тему. Source code будет немного позже.

🫢Что-то пошло не так? Я в домике
 

Вложения

  • HTTP_ASYNC.dll
    1.2 MB · Просмотры: 8

delanov

Участник
Автор темы
47
46
Можно ли что-то сделать с весом? 1.2мб многовато
Нет, это и так самый минимальный размер для HTTP запросов и обертки в Lua C API. (libcurl(13мб) и LuaJIT 2.1.0(10мб)). Поэтому в ближайшее время что-либо делать с размером я пока не планирую.
 

delanov

Участник
Автор темы
47
46
Сжал библиотеку через UPX. Антивирусы только такой вариант не одобряют :)
 

Вложения

  • HTTP_ASYNC.dll
    566 KB · Просмотры: 3
  • Вау
Реакции: The Spark

sosal_0x

Новичок
8
2
Lua:
http.http_async_request("https://api.ipify.org", function(response)

    if response.error then

        print("Ошибка GET: " .. response.error)

    else

        print("GET Статус: " .. response.status)

        print("GET Данные: ")

        for key, value in pairs(response.data) do

            print(key .. ": " .. tostring(value))

        end

    end

end, {

    method = "GET",

    timeout = 30

})
Отправлял запросы, но в консоли дальше HTTP async request scheduled ничего не происходило, не понимаю в чем может быть проблема
Lua:
[05:01:45.096251] (script)    Test: HTTP async request scheduled
[05:01:57.410451] (script)    Test: HTTP async request scheduled
[05:01:58.432684] (script)    Test: HTTP async request scheduled
[05:01:58.640732] (script)    Test: HTTP async request scheduled
[05:01:58.817772] (script)    Test: HTTP async request scheduled
[05:02:01.221319] (script)    Test: HTTP async request scheduled
[05:02:02.013500] (script)    Test: HTTP async request scheduled
 

вайега52

Eblang головного мозга
Модератор
2,892
2,872
Lua:
http.http_async_request("https://api.ipify.org", function(response)

    if response.error then

        print("Ошибка GET: " .. response.error)

    else

        print("GET Статус: " .. response.status)

        print("GET Данные: ")

        for key, value in pairs(response.data) do

            print(key .. ": " .. tostring(value))

        end

    end

end, {

    method = "GET",

    timeout = 30

})
Отправлял запросы, но в консоли дальше HTTP async request scheduled ничего не происходило, не понимаю в чем может быть проблема
Lua:
[05:01:45.096251] (script)    Test: HTTP async request scheduled
[05:01:57.410451] (script)    Test: HTTP async request scheduled
[05:01:58.432684] (script)    Test: HTTP async request scheduled
[05:01:58.640732] (script)    Test: HTTP async request scheduled
[05:01:58.817772] (script)    Test: HTTP async request scheduled
[05:02:01.221319] (script)    Test: HTTP async request scheduled
[05:02:02.013500] (script)    Test: HTTP async request scheduled
У меня такое же было вроде бы, но по идее, это связано с тем, что каллбеки не обновляются
 

delanov

Участник
Автор темы
47
46
Lua:
http.http_async_request("https://api.ipify.org", function(response)

    if response.error then

        print("Ошибка GET: " .. response.error)

    else

        print("GET Статус: " .. response.status)

        print("GET Данные: ")

        for key, value in pairs(response.data) do

            print(key .. ": " .. tostring(value))

        end

    end

end, {

    method = "GET",

    timeout = 30

})
Отправлял запросы, но в консоли дальше HTTP async request scheduled ничего не происходило, не понимаю в чем может быть проблема
Lua:
[05:01:45.096251] (script)    Test: HTTP async request scheduled
[05:01:57.410451] (script)    Test: HTTP async request scheduled
[05:01:58.432684] (script)    Test: HTTP async request scheduled
[05:01:58.640732] (script)    Test: HTTP async request scheduled
[05:01:58.817772] (script)    Test: HTTP async request scheduled
[05:02:01.221319] (script)    Test: HTTP async request scheduled
[05:02:02.013500] (script)    Test: HTTP async request scheduled
Лишний дебаг оставил случайно, а насчет проблемы - скорее всего каллбэк не включен
 
  • Нравится
Реакции: sosal_0x

sosal_0x

Новичок
8
2
Лишний дебаг оставил случайно, а насчет проблемы - скорее всего каллбэк не включен
А сложно его включать?
Я использовал это из примера:

Lua:
local running = true

while running do

    http.http_async_process_callbacks()

end


Но зависала намертво игра , поставил в main() while http.http_async_process_callbacks() , то так же после Test: HTTP async request scheduled ничего не происходило?

UPD:
Кажется я понял как нужно сделать (извините если я что-то по глупому пишу, я новичок в lua)
После отправки запроса , нужно его активировать функцией http.http_async_cleanup(), например я отправил и ввёл команду:

Код:
  sampRegisterChatCommand('tests', function()
    http.http_async_cleanup()
  end)
и ответ возвращается в callback функции отправки. Я в правильном направлении?
 
Последнее редактирование:

delanov

Участник
Автор темы
47
46
А сложно его включать?
Я использовал это из примера:

Lua:
local running = true

while running do

    http.http_async_process_callbacks()

end


Но зависала намертво игра , поставил в main() while http.http_async_process_callbacks() , то так же после Test: HTTP async request scheduled ничего не происходило?

UPD:
Кажется я понял как нужно сделать (извините если я что-то по глупому пишу, я новичок в lua)
После отправки запроса , нужно его активировать функцией http.http_async_cleanup(), например я отправил и ввёл команду:

Код:
  sampRegisterChatCommand('tests', function()
    http.http_async_cleanup()
  end)
и ответ возвращается в callback функции отправки. Я в правильном направлении?
Пример:
local http = require('HTTP_ASYNC')


function scheduleHTTP()
http.http_async_request("https://api.ipify.org", function(response)

    if response.error then

        print("Ошибка GET: " .. response.error)

    else

        print("GET Статус: " .. response.status)

        print("GET Данные: ")

        for key, value in pairs(response.data) do

            print(key .. ": " .. tostring(value))

        end

    end

end, {

    method = "GET",

    timeout = 30

})
end

function main()
    while not isSampAvailable() do wait(0) end
        scheduleHTTP()
    while true do
        wait(0)
        http.http_async_process_callbacks()
    end
end
function onScriptTerminate()
    http.http_async_cleanup()
end

Вот пример для MoonLoader скрипта

1746984027603.png
 

sosal_0x

Новичок
8
2
Пример:
local http = require('HTTP_ASYNC')


function scheduleHTTP()
http.http_async_request("https://api.ipify.org", function(response)

    if response.error then

        print("Ошибка GET: " .. response.error)

    else

        print("GET Статус: " .. response.status)

        print("GET Данные: ")

        for key, value in pairs(response.data) do

            print(key .. ": " .. tostring(value))

        end

    end

end, {

    method = "GET",

    timeout = 30

})
end

function main()
    while not isSampAvailable() do wait(0) end
        scheduleHTTP()
    while true do
        wait(0)
        http.http_async_process_callbacks()
    end
end
function onScriptTerminate()
    http.http_async_cleanup()
end

Вот пример для MoonLoader скрипта

Посмотреть вложение 270057
Это работает , но если переместить scheduleHTTP() в функцию команды или в другое место откуда вызывать , то дальше [ML] (script) Test: HTTP async request scheduled не продвинется , не понимаю почему ☹️