Cómo eliminar la ruta con un nginx proxy_pass

Cómo eliminar la ruta con un nginx proxy_pass

Tengo una aplicación web en ejecución en http://example.com/y quiero "montar" otra aplicación en un servidor separado en http://example.com/en. Servidores ascendentes y proxy_passparecen funcionar, pero por un problema:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

Al abrir example.com/en, mi aplicación ascendente regresa 404 not found /en. Esto tiene sentido, ya que el río arriba no tiene el camino /en.

¿Es proxy_pathla solución correcta? ¿Debería reescribir "upstream" para que escuche /en, como ruta raíz? ¿O existe una directiva que me permite reescribir la ruta pasada hacia arriba?

Respuesta1

Esta es probablemente la forma más eficiente de hacer lo que desea, sin el uso de expresiones regulares:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

Respuesta2

Me gustaría abordar una respuesta más nueva basada en expresiones regulares que ha ido ganando popularidad.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

La solución puede parecer más linda a primera vista, pero es incorrecta por múltiples razones.

  • La expresión regular anterior coincidiría con un uri de solicitud de /enjoyy lo redirigiría al /joynivel ascendente. ¿Es esto realmente intencionado?

  • Una solicitud de /enno dará lugar a ningún redireccionamiento, y servirá directamente desde el nivel ascendente (casi como si se hubiera realizado /una solicitud , pero no del todo). /en/Si utiliza URI relativos dentro de su página raíz ascendente (de lo contrario, ¿por qué no tendría el /en/prefijo allí mismo dentro de los URI ascendentes?), por ejemplo src="style.css"(que podría hacer referencia a un idioma específico url("menu.png"), por ejemplo), entonces el navegador solicitará que como /style.cssen lugar de /en/style.css. (O incluso si usa URI absolutos en todas partes, ¿qué pasa si alguien hace referencia relativamente a un recurso semiopcional oscuro?) Vaya, de repente es posible que el sitio no funcione, pero solo a veces o en casos extremos.

  • según miconsejo anterior sobre otra pregunta ya mencionada por la propia respuesta del OP, el uso de expresiones regulares evita queproxy_redirectdirectiva tenga el valor predeterminado de default, reduciéndolo a offsu lugar. Esto significa que si el canal ascendente responde Location: http://127.0.0.1:8080/en/dir/cuando se realiza una solicitud /en/dir, eso es lo que verá el cliente, lo que obviamente no funcionará correctamente. (Lo que habría sido especialmente irónico para una /ensolicitud que solicita el uso de expresiones regulares en primer lugar, pero esta implementación específica sufre otro problema como ya se mencionó anteriormente). Además, si ya está utilizando elupstreamdirectiva, entonces podría volverse aún más feo si simplemente intenta utilizar uno personalizado, especialmente si puede tener más de un servidor ascendente: ¿cómo puede tener uno separado proxy_redirectpara cada uno de ellos? También podría usar expresiones regulares dentro de proxy_redirect, tal vez incluso para que coincidan con cualquier host, pero ¿qué pasa si decide realizar una redirección entre dominios en el futuro?

Para intentar abordar algunos de los puntos anteriores con una única ubicación basada en expresiones regulares, podríamos hacer lo siguiente (tenga en cuenta que proxy_passtambién tuvimos que eliminar la referencia a un servidor desde una upstreamdirectiva basada en -, para hacerlo proxy_redirectmás sencillo):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

Entonces, si me preguntas, elSolución original con las dos ubicaciones hermanas de nivel superior.Seguiría siendo una mejor idea que meterse en una madriguera de conejo y seguir la ruta de las expresiones regulares.

Respuesta3

Así que encontré elrespuesta en stackoverflow:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

Básicamente: pasar una expresión regular a la ubicación y pasar la referencia inversa a la URL proxy_pass.

Respuesta4

Jugué con la solución aceptada anterior, pero descubrí que estaba provocando redireccionamientos poco fiables para todos los recursos CSS y JS. Al final, encontré inspiración en la forma en que se realizan las configuraciones de LinuxServer SWAG Nginx. puedes encontrarlosaquí. Echa un vistazo a pihole.subfolder.conf.sample.

Como tal, mi solución se ve así:

location /en {
    return 302 $scheme://$host/en/;
}

location ^~ /en/ {
    set $upstream_app lixxxx.members.linode.com;
    set $upstream_port 9001;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    rewrite /en(.*) $1 break;
}

información relacionada