2016-04-30 1 views
1

J'ai une application fonctionnant derrière nginx. Pour permettre aux clients d'ajouter leurs propres outils sous le même nom d'hôte, nous utilisons une sorte location de comme ceci:Comment puis-je créer des emplacements personnalisés dans nginx?

location /some-extension { 
    rewrite ^/(.*) /$1 break; 
    proxy_pass http://customers-app/$1/$args; 
} 

Maintenant, je voudrais faire cette dynamique de sorte qu'un client donné peut créer zéro ou plusieurs de ces endroits. Puisque l'application est déployée avec Docker, cela ne peut pas être fait manuellement en éditant la configuration de nginx.

Nginx est compilé avec perl et le soutien de lua, donc je pensais à quelque chose comme ceci:

  • utiliser une variable evironment sur le formulaire path1 url1 path-2 url2 ... pathn urln pour configurer un outil externe.
  • Dans une configuration spéciale location, faites correspondre le premier segment de chemin de l'URL de la requête avec la variable d'environnement et proxy_pass à l'URL correspondante si elle est trouvée.

Jusqu'à présent, voici ce que j'ai:

location/{ 
    content_by_lua ' 
     local target_path = ngx.var.uri; 
     local name = nil 

     if target_path:len() > 0 then 
     startAt = target_path:find("/") + 1 
     endAt = target_path:find("/", startAt) - 1 
     name = target_path:sub(startAt,endAt) 
     ngx.say(name) 
     end 

     if name then 
     local custom_proxies = os.getenv("CUSTOM_PROXIES"); 
     inString = custom_proxies:find("another ") 
     if not inString then 
      ngx.say("not in string") 
     else 
      startAt = custom_proxies:find(" ", inString + 1) + 1 
      endAt = custom_proxies:find(" ", startAt) 

      url = custom_proxies:sub(startAt,endAt) 
      ngx.say(url) 

     end 
     end 

    '; 
    } 

Je sais que je ne devrais pas être en utilisant content_by_lua mais il semble genre de travail. La question est comment puis-je obtenir ceci à proxy_pass à l'URL indiquée?

Répondre

0

Je l'ai résolu de la manière suivante:

  • La variable d'environnement doit être un espace liste séparée des noms et des URL; key http://example.com/app1 key2 http://acme.com. Un script Lua lit la variable d'environnement dans un table avec key comme clé et l'URL suivante comme valeur. Un bloc nginx location traitera la requête et utilisera le script Lua pour trouver le module à utiliser.

  • Une fonction acceptera le chemin de requête et en trouvera la clé, puis recherchera l'URL dans la table.

Voici le scénario:

local custom_proxies = os.getenv("CUSTOM_PROXIES") 
local custom_modules = {} 

local cutFrom = 0 
local cutTo = 0 

while cutTo < custom_proxies:len() do 
    cutFrom = cutTo 
    cutTo = custom_proxies:find(" ", cutFrom + 1) 
    local name = custom_proxies:sub(cutFrom, cutTo - 1) 
    cutFrom = cutTo + 1 
    cutTo = custom_proxies:find(" ", cutFrom) 

    if not cutTo then 
    cutTo = custom_proxies:len() + 1 
    end 

    local url = custom_proxies:sub(cutFrom, cutTo - 1) 
    custom_modules[name] = url 
    cutTo = cutTo + 1 
end 

function custom_modules.get_url(target_path) 
    local name = nil 

    local startAt = target_path:find("/", 6) + 1 
    local endAt = target_path:find("/", startAt) 
    if not endAt then 
    endAt = target_path:len() 
    else 
    endAt = endAt - 1 
    end 
    name = target_path:sub(startAt,endAt) 
    if name then 
    return custom_modules[name] 
    else 
    ngx.log(ngx.STDERR, "Not able to deduct module name from URI") 
    return "" 
    end 
end 

return custom_modules 

Voici le nginx location:

location /custom/ { 
    set_by_lua $redirect_to ' 
    local custom_modules = require "read_proxies" 
    local url = custom_modules.get_url(ngx.var.uri) 

    if not url then 
     ngx.log(ngx.STDERR, "Not a known custom module.") 
    end 
    return url 
    '; 

    if ($redirect_to = '') { 
    return 404 'Unknown custom module.'; 
    } 

    rewrite ^/custom/\w+/(.*) /$1 break; 
    proxy_pass $redirect_to$1?$args; 

} 

L'idée est qu'une demande telle que /custom/foobar/path/to/something?page=2 utilisera foobar comme clé pour rechercher l'URL et proxy_pass avec le reste du chemin et des arguments.