Переписывание nginx для pushState-URL - PullRequest
21 голосов
/ 08 февраля 2012

Я пытаюсь заставить nginx работать с моей pushState обработкой URI, которой backbone.js управляет для меня в приложении Javascript.

Прямо сейчас доступ к URI с одного уровня, например. example.com/users работает хорошо, но не двухуровневый или более глубокий URI, такой как example.com/users/all, который упоминается в Магистральной документации :

Например, если у вас есть маршрут / documents / 100, ваш веб-сервер должен быть в состоянии обслуживать эту страницу, если браузер посещает этот URL непосредственно

Итак, будучи далеко не знакомым с параметрами перезаписи nginx, я все еще уверен, что могу сделать что-то вроде rewrite ^ /index.html;, чтобы перенаправить все на мой index.html, но потерять все возможные статические файлы (изображения, javascript и css). ) хранится на том же сервере, к которому мне нужно иметь доступ.

Итак, что я должен сделать вместо показанной ниже текущей конфигурации, чтобы это работало?

server {
    listen   80;
    server_name  example.com;

    location / {
        root   /var/www/example.com;
        try_files $uri /index.html;
    }

}

Ответы [ 5 ]

32 голосов
/ 05 марта 2015

Я закончил с этим решением:

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;
    }

}

Таким образом, по крайней мере, я получаю правильные ошибки 404, если файл не найден.

19 голосов
/ 08 февраля 2012

Вот что я сделал с моим приложением. Каждый маршрут, заканчивающийся символом «/» (кроме самого корня), будет обслуживать index.html:

  location ~ ^/.+/$ {
    rewrite .* /index.html last;
  }

Вы также можете указать префикс вашего маршрута:

Backbone.history.start({pushState: true, root: "/prefix/"})

и затем:

  location ~ ^/prefix/ {
    rewrite .* /index.html last;
  }

Или определите правило для каждого случая.

15 голосов
/ 06 августа 2013

Мне удалось это так:

#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;
   }
}
7 голосов
/ 28 мая 2015

С путями приложения на стороне клиента:

/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123

Использование:

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;
    }
}

Хотя @ ответ Адама-Уэйта работает для корня и путей на корневом уровне, использование if в контексте местоположения считается антипаттерном, часто встречающимся при преобразовании директив стиля Apache. Смотри: http://wiki.nginx.org/IfIsEvil.

Другие ответы не охватывают маршруты с глубиной каталогов для моего варианта использования в аналогичном приложении React, использующем реагирующий маршрутизатор и HTML5 pushState. Когда маршрут загружается или обновляется в «каталоге», таком как example.com/foo/bar/baz/213123, мой файл index.html будет ссылаться на файл js по относительному пути и будет преобразован в example.com/foo/bar/baz/js/app.js вместо example.com/js/app.js.

Для случаев с глубиной каталогов за пределами первого уровня, например /foo/bar/baz, обратите внимание на порядок каталогов, объявленных в директиве @rootfiles: сначала должны идти самые длинные пути, после чего следует следующий более мелкий путь /foo/bar и наконец /foo.

0 голосов
/ 04 мая 2016

Так как может быть запрос API ajax, для этого случая подходят следующие,

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;
    }
}
...