2012-02-07 16 views
21

Próbuję uzyskać nginx do pracy z obsługą opartego na identyfikatorze URI pushState, którą zarządza dla mnie backbone.js w aplikacji JavaScript.Przepisanie pliku nginx dla adresu użytkownika PushState-URL:

Teraz dostęp do identyfikatorów URI z jednym poziomem, np. example.com/users działa dobrze, ale nie dwupoziomowy lub głębiej URI, takich jak example.com/users/all, który jest wymieniony w Backbone documentation:

Na przykład, jeśli masz trasę/Dokumenty/100, serwer WWW moszczu być w stanie obsłużyć tę stronę, jeśli przeglądarka odwiedza że URL bezpośrednio

Więc, będąc daleko od zapoznania się z opcjami przepisywania nginx jest, wciąż jestem pewien, że mogę zrobić coś takiego rewrite^/index.html; przekierować wszystko, aby mój index.html , ale loosi ng out na ewentualnych statycznych plikach (obrazy, javascript & css) przechowywanych na tym samym serwerze, który muszę mieć możliwość dostępu.

Co powinienem zrobić zamiast pokazanej poniżej, bieżącej konfiguracji, aby to zadziałało?

server { 
    listen 80; 
    server_name example.com; 

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

} 

Odpowiedz

19

Oto, co zrobiłem w mojej aplikacji. Każda trasa kończy się znakiem '/' (z wyjątkiem siebie korzeń it) będzie służyć index.html:

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

Można również poprzedzić swoją trasę:

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

, a następnie:

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

Lub zdefiniuj regułę dla każdego przypadku.

+3

Twoja pierwsza sugestia wydaje się wymagać ukośnik ... przepisać działa, gdy idę do „/ search /”, ale nie "/ search" – andrhamm

+1

jak byś go rozwiązał, gdybyś nie miał końcowego ukośnika? –

+0

Być może wyrażenie regularne, które akceptuje wszystko poza index.html? –

14

I udało się to tak:

#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; 
    } 
} 
+1

Mam 500 używając tego. –

+0

ta konfiguracja działa dla mnie! – llazzaro

30

skończyło się dzieje z tego rozwiązania:

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

} 

ten sposób, przynajmniej ja nadal uzyskania odpowiedniego 404 błędy, jeśli plik nie został znaleziony .

+2

Dzięki, to zadziałało dla mnie. Posiadanie faktycznego 404 jest ważne - jeśli zażądano pliku JS, który nie istnieje i zamiast niego zwrócony zostanie HTML, przeglądarka spróbuje przeanalizować go jako JS i wygeneruje wszystkie rodzaje błędów JS. To mogłoby trochę zepsuć SPA. – ccnokes

+1

To powinno być wyżej. Proste, eleganckie i 404 pliki są ważne – Igonato

7

Z ścieżek aplikacji po stronie klienta:

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

Zastosowanie:

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

Podczas @Adam-Waite's answer prace dla korzenia i ścieżki na poziomie głównym, przy użyciu jeśli w kontekście lokalizacji jest uważany za antywzorzec projektowy , często widziana podczas konwersji dyrektyw w stylu Apache. Patrz: http://wiki.nginx.org/IfIsEvil.

Pozostałe odpowiedzi nie obejmują tras z głębokością katalogu dla mojego przypadku użycia w podobnej aplikacji React z użyciem routera reagującego i włączonego HTML5 pushState. Kiedy trasa jest ładowana lub odświeżana w "katalogu", takim jak example.com/foo/bar/baz/213123, mój plik index.html będzie odwoływał się do pliku js na ścieżce względnej i zostanie rozstrzygnięty na example.com/foo/bar/baz/js/app.js zamiast na example.com/js/app.js.

W przypadkach, o głębokości katalogów poza pierwszym poziomie takim jak /foo/bar/baz, zwróć uwagę na kolejność katalogów zadeklarowanych w dyrektywie @rootfiles: najdłuższe możliwe ścieżki trzeba iść najpierw, a następnie kolejnej płytsze ścieżce /foo/bar i wreszcie /foo.

0

Ponieważ nie może być ajax żądanie api następujące garnitury dla tej sprawy,

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