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_pass
parecen 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_path
la 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
/enjoy
y lo redirigiría al/joy
nivel ascendente. ¿Es esto realmente intencionado?Una solicitud de
/en
no 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 ejemplosrc="style.css"
(que podría hacer referencia a un idioma específicourl("menu.png")
, por ejemplo), entonces el navegador solicitará que como/style.css
en 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 que
proxy_redirect
directiva tenga el valor predeterminado dedefault
, reduciéndolo aoff
su lugar. Esto significa que si el canal ascendente respondeLocation: 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/en
solicitud 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 elupstream
directiva, 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 separadoproxy_redirect
para cada uno de ellos? También podría usar expresiones regulares dentro deproxy_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_pass
también tuvimos que eliminar la referencia a un servidor desde una upstream
directiva basada en -, para hacerlo proxy_redirect
má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;
}