Pregunta Nginx proxy inverso + reescritura de URL


Nginx se está ejecutando en el puerto 80, y lo estoy usando para revertir las direcciones URL de proxy con ruta /foo hacia el puerto 3200 de esta manera:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $host;
}

Esto funciona bien, pero tengo una aplicación en el puerto 3200, para lo cual no quiero la inicial /foo para ser enviado a Es decir, cuando accedo http://localhost/foo/barSolo quiero /bar Para ser el camino que ha recibido la aplicación. Así que intenté agregar esta línea al bloque de ubicación de arriba:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;

Esto provoca una redirección 302 (cambio en la URL), pero quiero 301. ¿Qué debo hacer?


95
2018-04-15 17:31


origen


Si tienes algún problema con el caso Grafana debes usar estas recetas: docs.grafana.org/installation/behind_proxy/… - mohsen saeedi


Respuestas:


Cualquier redireccionamiento a localhost no tiene sentido desde un sistema remoto (por ejemplo, el navegador web del cliente). Entonces el reescribir banderas Permanent (301) o Redirect (302) no se pueden utilizar en su caso.

Por favor, intente la siguiente configuración usando una regla de reescritura transparente:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}

Utilizar curl -i para probar su reescritura. Un cambio muy sutil a la regla puede hacer que nginx realice una redirección.


117
2018-04-15 17:56



La ruta de la URL aún comienza con / foo en mi aplicación cuando hago eso ... - jeffreyveon
Debe haber un problema diferente. Reproducí este escenario con éxito, hace apenas unos minutos. URL original: http: // desarrollo / foo / testme / 1234 - REQUEST_URI de un script PHP que se ejecuta en un Apache conectado como back-end de proxy: '/ testme / 1234' - Jens Bradler
El regex probablemente debería ser /foo(.*)de lo contrario example.com/foo no será emparejado. (que es probablemente lo que experimentó jeffreyveon) - Benno
Este tipo de trabajo, pero mi cuerpo que estoy configurando con proxy_set_body se está eliminando. - Justin Thomas
reescribir /(.*) /socket.io/ break; GUARDAR MI DIA PARA SOCKET.IO - user956584


La coincidencia de prefijo de ubicación simple funciona para esto sin usar una regla de reescritura siempre que especifique un URI en la directiva proxy_pass:

location /foo {
  proxy_pass http://localhost:3200/;
}

Note el adicional / al final de proxy_pass directiva. NGINX eliminará el prefijo correspondiente /foo y pase el resto al servidor backend en el URI /. Por lo tanto, http://myserver:80/foo/bar publicaremos en el backend en http://localhost:3200/bar.

Desde el NGINX docs en proxy_pass:

Si la directiva proxy_pass se especifica con un URI, entonces cuando un   La solicitud se pasa al servidor, la parte de una URI de solicitud normalizada   La coincidencia con la ubicación se sustituye por un URI especificado en la directiva:


86
2017-09-29 03:30



Funciona para mí lo que he agregado / a la ubicación / foo / { - Andrei N
¡Esto era precisamente lo que estaba buscando! - anbiniyar
Esta es una solución muy limpia, preferiría que esta fuera la respuesta canónica a la pregunta. - ralien
Tomó demasiado tiempo para darse cuenta de la importancia de mantener o eliminar barra diagonal. - Parvez
Esto realmente pasará //xyz al anfitrión si haces eso. - Archimedes Trajano


La forma más correcta y la mejor práctica es generalmente como sigue:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • Tenga en cuenta la extrema importancia de la barra de arrastre en proxy_pass, que altera automáticamente el $uri variable para tener el /foo/ en la parte delantera se corresponden con / en el backend No hay necesidad de un explícito. rewrite directiva.

  • Además, tenga en cuenta que el al final / en el location también es muy importante: sin él, corre el riesgo de tener direcciones URL de aspecto extraño en su sitio en un momento dado (por ejemplo, una /fooen además de /foo/en).

    Además, el final / en el location con proxy_pass también asegura algunos manejo especial, según la documentación de la location directiva, para causar efectivamente una implícita location = /foo {return 301 /foo/;} también.

    Así, definiendo un location con la barra diagonal final como la anterior, no solo se asegura de que las URL de sufijo sin barra como /fooen No será válido, sino también que un /foo sin una barra inclinada continuará trabajando también.


Documentación de referencia:


30
2017-08-26 21:12



¡Esta es la mejor respuesta aquí! - Mo Friedrich
Parece que $args Esta perdido: http://frontend/foo?bar=baz será enviado a http://backend/. Tenga en cuenta que args no son la parte de url - Vanuan
@Vanuan, ¿estás seguro de eso? Estoy bastante seguro $args aún debe manejarse adecuadamente si usa el código anterior, ya que están separados de $uri, y debería volver a ensamblarse, a menos que esté utilizando variables explícitas en su proxy_pass. - cnst
@ArchimedesTrajano, usted es incorrecto, ya que hay un manejo especial para /foo para redirigir a /foo/, entonces, a menos que estés haciendo algo raro en el backend, incluso /foo Las solicitudes seguirán funcionando con el código anterior. (Esto es en realidad ya parte de la respuesta, BTW). - cnst
¡Esta es la mejor respuesta! Esto debe subir. - phegde


tratar

location /foo {
    proxy_pass http://localhost:3200/;
    ....

o

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....

0
2018-01-21 16:20



Esta respuesta sería buena si da alguna explicación de por qué debe configurarse como se indicó anteriormente. - masegaloeh
Esto realmente pasará //xyz al anfitrión si haces eso. - Archimedes Trajano