Перейти к основному содержимому

express.lua – создание веб приложений на Lua

· 6 мин. чтения

lua-express-white-banner

🌕 express.lua это самый детализированный порт оригинального express.js, написанный на Lua. Пока кто-то не докажет обратного.

По сути, lua-express это минималистичный web фреймворк с почти полной совместимостью API с express.js, позволяющий создавать веб приложения на чистом Lua.

Сравнение
const express = require("express")
const app = express()

app.get("/", function(req, res) {
res.send("Hello World")
})

app.listen(3000)

Изначально идея создания этого порта появилась из-за желания отделить API одного сервиса с монолитного PHP приложения в отдельный микросервис, чтобы при атаках его было проще масштабировать.

Сейчас цель достигнута – express.lua работает в продакшене, API сервиса переписан и прямо сейчас успешно обрабатывает запросы, причем также асинхронно работая с mysql и redis (покликайте) без каких-либо крупных зависимостей, используя только copas и luasocket для асинхронности и связи с базами данных соответственно. Раньше такого в "чистом" Lua еще никто не делал. Решений просто не существовало.

Немного бекстейджа
Интересное

На первую рабочую версию lua-express ушло несколько недель, несмотря на небольшую базу кода. Дело в том, что express.js построен на базе nodejs, но у Lua полноценного И МИНИМАЛИСТИЧНОГО nodejs (по сути, встроенного веб сервера) просто не существовало.

Второй глобальной проблемой являлось то, что Lua привыкли рассматривать, как что-то, где асинхронности не существует, что означало бы, что один медленный запрос остановил бы все последующие. Поэтому перед созданием порта пришлось очень плотно изучить как делать штуки в lua "асинхронными". В кавычках, потому что Lua все же однопоточный ЯП, поэтому вместо настоящей асинхронности мы имеем крутой хак с сокетами и корутинами. Думаю, что на самом деле в JS все устроено так же, только Lua показал себя более производительным в бенчмарках на одинаковых задачах*.

* к сожалению, не в вопросах работы с сокетами

🤔 В итоге, что мы сейчас имеем?

Действительно полноценный express.js прямо в Lua, который работает, работает хорошо, работает на более простом (имхо), но производительном Lua, он не требует никаких openresty зависимостей, легко встраивается в любое готовое приложение (например, в телеграм боты, написанные на lua)

🌈 Преимущества:

sponge bob rainbow

  • Не требует больших зависимостей. Например, lapis требует целый openresty.
  • За основу взят express.js, который известен по всему миру своей простотой, гибкостью и производительностью.
  • Для тех, кто работал с express.js будет очень легко понять и перейти на express.lua – API почти на 100% идентичен.
  • Все входящие запросы можно обрабатывать асинхронно (non-blocking), использая copas. Это тысячи запросов в секунду.
  • Легко встраивать в скрипты и приложения любой сложности. lua-express легенький и из "сложного" требует только luasocket.
  • Прошел проверку боем. Используется в реальном приложении и приносит счастье.

🤔 Где взять, как установить?

Информацию по этому поводу искать в репозитории lua-express.

Если какой-то информации там не хватает, то можете создать Issue (я постоянно слежу за Issues), либо написать мне (внизу написано как) и я допишу все, что может потребоваться.

🖼️ Примеры

Для тех, кто использовал express – примером может быть любое написанное вами на express.js приложение. Lua версия будет отличаться лишь незначительно.

Если про express.js вы только слышали (не слышать о нем невозможно), то пример можете посмотреть тут: клик. Более продвинутый: тут

Примеры реализаций на Lua можно посмотреть в /examples репозитория lua-express.

👉 А вот тут можно посмотреть пример реализации long-polling сервера. Я использую его как единую точку сбора вебхуков со всех сервисов (github webhooks, telegram, luadev переписал на вебхуки, healthcheck, VK webhooks), затем с этого одного места забираю апдейты сразу с множеством микросервисов (например разные части одного телеграм бота работают как отдельные микросервисы на разных серверах). Здесь есть пост в блоге.


P.S.

  1. Мне очень нравится как в express устроены роутинги, поэтому если вы еще ими не пользовались или не знаете что это, то советую разобраться. Они позволяют "прикреплять" пути к определенному префиксу, а у префикса могут быть свои middlewares. Они значительно упрощают код и позволяют с легкостью масштабировать код приложения с минимальными изменениями. Условно, вы начали писать приложение чисто, как /api, но решили добавить /admin.. короче.. Роутеры в express это круто.

  2. Порт настолько детальный, что даже фишечка express с error handler middleware тоже была перенесена. Обычные мидлы выглядят вот так: (req, res, next), а с ошибкой вот так: (err, req, res, next). Т.е. если указано 4 параметра, то мидлвер будет считаться обработчиком ошибок, а не обычным мидлвером. Вот, смотрите. Красивое.

Похожие решения и полезные ссылки

Открыть спойлер
  • lor – минимальный фреймворк, требует openresty, на нем кстати написан веб интерфейс для redis
  • pegasus.lua - простой HTTP/1 сервер, с которого началась работа над express.lua
  • expresslua – чья-то попытка создания express.lua. Здесь даже старались реализовать асинхронность, но нет поддержки middlewares и отсутствуют десятки методов.
  • lapis – древний, мощный и до сих пор поддерживаемый веб фреймворк. Но требует openresty.
  • fasty – что-то новое, модное и хипстерское. Целая CMS на Lua, построенная на lapis и arangoDB (wow?)
  • luvit – большой старый веб сервер с активной поддержкой, который очень хотел быть похож на http сервер nodejs, но в итоге стал слишком большим и неповоротным. По крайней мере, у меня не удалось интегрировать его в ggram, чтобы получать вебхуки, потому что он сложно устанавливается или (и) я тупой.
  • turbo – целая солянка из всего. Веб запросы, веб фреймворк, веб сервер. Выглядит заброшенным и со сложным API, поэтому я обошел его стороной.
  • octopus – веб фреймворк, даже не знаю как я его нашел, но кажется, поцыент не подает признаков жизни :(. Возможно, пытался притвориться Django
  • lua-http – веб сервер. Страшненький.
  • xavante - веб сервер. Древний и сейчас бесполезный, но постоянно я на него попадаю

Немного о pegasus. Написание express началось как раз с него, как с базы веб сервера. На момент написания он активно поддерживался разработчиком и был минималистичным, но его проблема в том, что документация не поспевала за обновлениями, а некоторые вещи реализованы так, что их нельзя было просто взять и внедрить в express. Например, создание response объекта требует передачи в аргументе сложной конструкции ради простейшей цели. Кроме того, нельзя было просто взять и установить status code, который заранее не прописан в pegasus, потому что получалась ошибка. Тем не менее, он оказался очень ценным для меня в первое время


👨‍💻 Как и всегда, со мной можно связаться по контактам, которые есть на этой странице. Там я могу также индивидуально проконсультировать по поводу lua-express, если кому-то нужно