Вызов внешнего API в разделе локации Nginx

Я пытаюсь динамически разрешить значение proxy_pass (через веб-api) в nginx.

Мне нужно что-то вроде ниже:
Пример взят из: https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/

location /proxy-pass-uri {
    set $urlToProxy = CallWebAPI("http://localhost:8081/resolver?url = " + $url);
    proxy_pass $urlToProxy;         
}

Итак, мой вопрос в том, можно ли сделать HTTP-запрос или написать такой метод, как CallWebAPI?

Я знаю, что это может быть плохой практикой, но на веб-сайте, с которым я имею дело, есть тысячи веб-адресов, которые отображаются как пары ключ-значение, и 90% из них не подчиняются каким-либо конкретным правилам регулярных выражений. Итак, у меня есть база данных с отображением контента, и мне нужно динамически получать входящий URL-адрес с контентом.

Я пытаюсь использовать очень легкую веб-службу для поиска URL-адресов из Redis и возврата URL-адреса прокси.

Будет ли это допустимым сценарием, или есть какое-либо другое встроенное решение в nginx, подобное этому?

Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
1
0
384
1

Ответы 1

Я сомневаюсь, что это можно сделать с "чистым" nginx, но это определенно можно сделать с помощью открытость или ngx_http_lua_module с помощью метода ngx.location.capture. Например:

resolver 8.8.8.8;
location ~/proxy-pass-uri(/.*)$ {
    set $url $1;
    set $proxy "";
    access_by_lua_block {
       res = ngx.location.capture("http://localhost:8081/resolver?url = " .. ngx.var.url)
       ngx.var.proxy = res.body
    }
    proxy_pass $proxy$url;
}

Существует также ngx_http_js_module (документация, GitHub), который может выполнять подзапросы (пример), но я никогда не использовал его и не могу сказать, можно ли его использовать таким образом.

Важное обновление

Спустя почти три года с момента написания этого ответа выяснилось, что мне самому понадобилась аналогичная функциональность, и оказалось, что приведенный выше ответ полностью сломан и неработоспособен. Вы не можете выполнить подзапрос через ngx.location.capture ни к чему другому, кроме как к другому местоположению nginx. Итак, правильный (проверенный и подтвержденный работоспособностью) пример для вышеуказанного вопроса:

resolver 8.8.8.8;
location /resolver {
    internal;
    proxy_pass http://localhost:8081;
}
location ~ ^/proxy-pass-uri(/.*)$ {
    set $url $1;
    set $proxy "";
    access_by_lua_block {
        res = ngx.location.capture("/resolver?url = " .. ngx.var.url)
        if res.status == ngx.HTTP_OK then
            ngx.var.proxy = res.body
        else
            ngx.exit(res.status)
        end
    }
    proxy_pass $proxy$url$is_args$args;
}

В приведенном выше примере предполагается, что служба разрешения прокси действительно ожидает запроса в форме /resolver?url=<uri>. location /resolver { ... }, будучи внутренним, ведет себя как любое другое местоположение префикса, поэтому, если префикс /resolver для этого местоположения не может быть использован по какой-либо причине, его можно записать как

resolver 8.8.8.8;
location /get_proxy {
    internal;
    proxy_pass http://localhost:8081/resolver;
}
location ~ ^/proxy-pass-uri(/.*)$ {
    set $url $1;
    set $proxy "";
    access_by_lua_block {
        res = ngx.location.capture("/get_proxy?url = " .. ngx.var.url)
        if res.status == ngx.HTTP_OK then
            ngx.var.proxy = res.body
        else
            ngx.exit(res.status)
        end
    }
    proxy_pass $proxy$url$is_args$args;
}

Один JavaScript выглядит очень многообещающим, я проверю это и дам вам знать, спасибо!

Teoman shipahi 16.12.2018 19:37

Другие вопросы по теме