Перенос/создание редиректов для nginx при помощи lua и redis

В процессе работы появилась задача организовать порядка 1500 редиректов для сайта. Конечно, можно просто сгенерировать локейшены и подцепить их инклудом, но подобное решение во-первых является не совсем красивым, а во-вторых довольно медленным, ведь nginx придется проходить для каждого запроса все локейшены. Выбор упал на lua + redis , так как redis является inmemory СУБД ( хоть и nosql ) и довольно быстра.
Итак, мы собрали nginx с модулем lua и готовы творить.
У меня получился вот такой конфиг :

server {
listen 80;
location / {
access_by_lua '
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
local key = ngx.var.request_uri
local res, err = red:get(key)
if res ~= ngx.null then
ngx.redirect(res, 301)
end
';
rewrite ^(.*)$ /index.html break;
}
location /value1 { return 505; }
}

Долго мучался с access_by_lua , так как глубоких знаний lua у меня пока нет, а во всех источниках люди пишут content_by_lua. В итоге, прошерстив документацию, я пришел к выводу, что content_by_lua можно использовать только тогда, когда в этом же локейшене нет других рерайтов, proxy_pass и прочего от nginx . В текущем конфиге с content_by_lua я получал безусловный рерайт на /index.html не учитывая мою логику lua. А access_by_lua учитывает подобное поведение, что мне на руку. Дополнительный локейшен /value1 использую для теста конфига. Если в redis есть ключ со значением /value1 , то мы получим редирект и 505 код, если же ключа не существует, то нам просто отдастся стандартная страница openresty ( я использовал docker образ openresty/openresty:alpine для тестирования ).

Итак,

стартуем образ nginx :

docker run --net host -d -v /srv/docker/nginx/:/etc/nginx/conf.d openresty/openresty:alpine

далее стартуем наш редис :

docker run --net host -d redis

вносим в redis наши данные :

redis-cli set /v1234 /value1

Проверяем :
http://localhost/v123 — ( нет такого ключа в редисе ) — получаем индексную страницу
http://localhost/v1234 — ( есть такой ключ со значением /value1 ) — получаем 301 редирект и 505 код. Ура.

Конечно, в коде нет проверки на корректность подключения и доступность самого редиса, но это черновой вариант с рабочей логикой, который расширить не составит никакого труда.

Tags: , , , ,

Leave a Reply