Nginx config for single page app with HTML5 App Cache
Asked Answered
O

1

14

I'm trying to build a single page app that utilizes HTML5 App Cache, which will cache a whole new version of the app for every distinct URL, thus I must redirect everyone to / and have my app route them afterward (this is the solution used on devdocs.io).

Here's my nginx config. I want all requests to send a file if it exists, redirect to my API at /auth and /api, and redirect all other requests to index.html. Why is the following configuration causing my browser to say that there is a redirect loop? If the user hits location block #2 and his route doesn't match a static file, he's sent to location block #3, which will redirect him to "/" which should hit location block #1 and serve index.html, correct? What is causing the redirect loop here? Is there a better way to accomplish this?

root /files/whatever/public;
index index.html;

# If the location is exactly "/", send index.html.
location = / {
    try_files $uri /index.html;
}

location / {
    try_files $uri @redirectToIndex;
}

# Set the cookie of the initialPath and redirect to "/".
location @redirectToIndex {
    add_header Set-Cookie "initialPath=$request_uri; path=/";
    return 302 $scheme://$host/;
}

# Proxy requests to "/auth" and "/api" to the server.
location ~* (^\/auth)|(^\/api) {
    proxy_pass http://application_upstream;
    proxy_redirect off;
}
Orton answered 15/9, 2015 at 19:6 Comment(5)
Do you have root directive and index.html file? Check error.logJenniejennifer
Yes. Question updated to include it.Orton
Nothing in my error log.Orton
Did you check with curl (or wget)? May be your browser cached wrong redirect…Jenniejennifer
curl gives me some nginx HTML <center><h1>302 Found</h1></center><hr><center>nginx/1.8.0</center> and wget says "20 redirections exceeded". No caching issues here.Orton
A
28

That loop message suggests that /files/whatever/public/index.html doesn't exist, so the try_files in location / doesn't find $uri when it's equal to /index.html, so the try_files always internally redirects those requests to the @ location which does the external redirect.

Unless you have a more complicated setup than you've outlined, I don't think you need to do so much. You shouldn't need external redirects (or even internal redirects) or server-side cookie sending for a one-file js app. The regex match for app and api wasn't quite right, either.

root /files/whatever/public;
index index.html;

location / {
    try_files $uri /index.html =404;
}

# Proxy requests to "/auth" and "/api" to the server.
location ~ ^/(auth|api) {
    proxy_pass http://application_upstream;
    proxy_redirect off;
}
Authors answered 18/9, 2015 at 17:34 Comment(2)
Thanks, turned out index.html didn't exist. I'm curious why you say I don't need server-side cookie sending or redirects? HTML5 App Cache will undesirably save a whole new cache for every URL, so the only solution I see is that I need to set the cookie, redirect all requests to /, and then reroute them within the JavaScript on the frontend.Orton
Can you use slugs instead of virtual urls? Instead of http://site/path1/path2/foo, http://site/#path1/path2/foo. That's the only way I can think of to avoid either duplicate html5 app caching or horribly inefficient external redirects.Authors

© 2022 - 2024 — McMap. All rights reserved.