Reescribiendo nginx para pushState-URL''s
backbone.js rewrite (5)
Estoy tratando de hacer que nginx
funcione con mi pushState
de URI basado en pushState
que backbone.js
administra para mí en una aplicación de Javascript.
Ahora mismo accediendo a los URI con un nivel, ej. example.com/users
funciona bien, pero no con URI de dos niveles o más profundos, como example.com/users/all
, que se menciona en la documentación de Backbone :
Por ejemplo, si tiene una ruta de / documents / 100, su servidor web debe poder servir esa página, si el navegador visita esa URL directamente
Por lo tanto, al estar lejos de conocer las opciones de reescritura de nginx, estoy seguro de que puedo hacer algo como rewrite ^ /index.html;
para redirigir todo a mi index.html
, pero perdiendo cualquier archivo estático eventual (imágenes, javascript y css) almacenado en el mismo servidor al que necesito poder acceder.
Entonces, ¿qué debo hacer con la configuración actual que se muestra a continuación para que esto funcione?
server {
listen 80;
server_name example.com;
location / {
root /var/www/example.com;
try_files $uri /index.html;
}
}
Con las rutas de acceso del lado del cliente:
/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123
Utilizar:
server {
listen 80;
server_name example.com;
root /var/www/example.com;
gzip_static on;
location / {
try_files $uri $uri/ /index.html;
}
# Attempt to load static files, if not found route to @rootfiles
location ~ (.+)/.(html|json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ {
try_files $uri @rootfiles;
}
# Check for app route "directories" in the request uri and strip "directories"
# from request, loading paths relative to root.
location @rootfiles {
rewrite ^/(?:foo/bar/baz|foo/bar|foo|tacos)/(.*) /$1 redirect;
}
}
Mientras que la respuesta de @Adam-Waite funciona para la raíz y las rutas en el nivel raíz, usar si dentro del contexto de ubicación se considera un antipatrón, a menudo visto al convertir las directivas de estilo de Apache. Ver: http://wiki.nginx.org/IfIsEvil .
Las otras respuestas no cubren rutas con profundidad de directorio para mi caso de uso en una aplicación similar de React que usa react-router y HTML5 pushState habilitado. Cuando se carga o se actualiza una ruta dentro de un "directorio" como example.com/foo/bar/baz/213123
mi archivo index.html hará referencia al archivo js en una ruta relativa y se resolverá en example.com/foo/bar/baz/js/app.js
lugar de example.com/js/app.js
.
Para casos con profundidad de directorio más allá del primer nivel como /foo/bar/baz
, tenga en cuenta el orden de los directorios declarados en la directiva @rootfiles: las rutas más largas posibles deben ir primero, seguidas por la siguiente ruta menos profunda /foo/bar
y finalmente /foo
.
Dado que puede haber solicitud de solicitud jajaja, los siguientes juicios para este caso,
server {
listen 80;
server_name example.com;
root /var/www/example.com;
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+/..+$ {
try_files $uri =404;
}
# Any route that doesn''t have a file extension (e.g. /devices)
location / {
try_files $uri /index.html;
}
# The location block above provides the shortest prefix, of length one,
# and so only if all other location blocks fail to provide a match,
# this block will be used.
# Ajax api starts with /v1/ will be proxied
location /v1/ {
proxy_pass http://proxy;
}
}
Esto es lo que hice con mi aplicación. Cada ruta que termine con un ''/'' (excepto la raíz propia) servirá index.html
:
location ~ ^/.+/$ {
rewrite .* /index.html last;
}
También puede prefijar su ruta:
Backbone.history.start({pushState: true, root: "/prefix/"})
y entonces :
location ~ ^/prefix/ {
rewrite .* /index.html last;
}
O define una regla para cada caso.
Lo logré así:
#set root and index
root /var/www/conferences/video/;
index index.html;
#route all requests that don''t serve a file through index.html
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.html break;
}
}
Terminé yendo con esta solución:
server {
listen 80;
server_name example.com;
root /var/www/example.com;
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+/..+$ {
try_files $uri =404;
}
# Any route that doesn''t have a file extension (e.g. /devices)
location / {
try_files $uri /index.html;
}
}
De esta forma, al menos recibo los errores 404 adecuados si no se encuentra un archivo.