Servindo vários pontos de extremidade de proxy em um local no Nginx


13

Eu tenho alguns pontos de extremidade da API que desejo servir em um único local, /apicom subcaminhos indo para pontos de extremidade diferentes. Especificamente, quero que os webdis estejam disponíveis em /apie uma API proprietária disponível em /api/mypath.

Não estou preocupado com conflitos com a API webdis porque estou usando subcaminhos que dificilmente colidirão com nomes de comando redis e também tenho controle total sobre o design da API para evitar conflitos.

Aqui está o arquivo de configuração do meu servidor de teste no qual eu tenho invadido:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # temporary hardcoded workaround
  location = /api/mypath/about {
    proxy_pass http://localhost:3936/v1/about;
  }

  location /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }

  # tried this but it gives "not found" error
  #location ^~ /api/mypath/ {
  #  rewrite ^/api/mypath/(.*)$ /$1 break;
  #  proxy_pass http://localhost:3936/v1/;
  #}
  #
  #location ^~ /api {
  #  rewrite ^/api/(.*)$ /$1 break;
  #  proxy_pass http://localhost:7379/;
  #}
}

Como posso alterar minha solução alternativa para que quaisquer solicitações /api/mypath/*sejam encaminhadas para o terminal na porta 3936 e tudo mais para a porta 7379?


Como assim tried this to no avail? O que aconteceu quando você habilita essa diretiva de local? Tempo limite de conexão? O local não corresponde?
Masegaloeh 08/12/14

Ah, obrigado pelo prompt, ele está dando um erro não encontrado. Em uma investigação mais detalhada, parece que o erro está vindo da minha API e está funcionando! : D Mas a regra de reescrita obviamente não é porque eu tenho que adicionar v1 à URL ( localhost / api / mypath / v1 / about ) ... :(
hamstar

Respostas:


23

Você não precisa reescrever isso.

server {
  ...

  location ^~ /api/ {
    proxy_pass http://localhost:7379/;
  }
  location ^~ /api/mypath/ {
    proxy_pass http://localhost:3936/v1/;
  }
}

De acordo com a documentação nginx

Um local pode ser definido por uma sequência de prefixos ou por uma expressão regular. Expressões regulares são especificadas com o ~*modificador anterior (para correspondência sem distinção entre maiúsculas e minúsculas) ou o ~modificador (para correspondência com distinção entre maiúsculas e minúsculas). Para encontrar um local que corresponda a uma determinada solicitação, o nginx primeiro verifica os locais definidos usando as sequências de prefixos (localizações do prefixo). Entre eles, o local com o prefixo correspondente mais longo é selecionado e lembrado. Em seguida, as expressões regulares são verificadas, na ordem em que aparecem no arquivo de configuração. A pesquisa de expressões regulares termina na primeira correspondência e a configuração correspondente é usada. Se nenhuma correspondência com uma expressão regular for encontrada, a configuração do local do prefixo lembrado anteriormente será usada.

Se o local do prefixo correspondente mais longo tiver o ^~modificador, as expressões regulares não serão verificadas.

Portanto, qualquer solicitação que comece com /api/mypath/será sempre atendida pelo segundo bloco, pois esse é o local do prefixo correspondente mais longo .

Qualquer solicitação que comece com /api/não imediatamente seguida por mypath/sempre será atendida pelo primeiro bloco, já que o segundo bloco não corresponde, tornando o primeiro bloco o local do prefixo correspondente mais longo .


2
Se você olhar para os modificadores de localização ( =, ~*, ~e ^~) que possa parecer contra-intuitivo que ^~exclui as expressões regulares (uma vez que ~indica uma expressão regular) ... No entanto, se você se lembra, ^dentro de uma classe de caracteres regex (por exemplo [^a-z]) nega que classe (de modo que o exemplo significa (qualquer caractere, exceto os de az); da mesma forma, ^~nega quaisquer possíveis blocos de localização de expressões regulares.
Doktor J

6

OK, entendi, pensei que o erro "não encontrado" vinha do nginx, mas na verdade era da minha API. Esta é a minha solução se alguém estiver interessado:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # automatically go to v1 of the (grape) API
  location ^~ /api/mypath/ {
    rewrite ^/api/mypath/(.*)$ /v1/$1 break;
    proxy_pass http://localhost:3936/;
  }

  location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.