“404 Not Found” 和 “403 Forbidden” 在 nginx 里往往是路径拼错或没有 index 文件。这篇在本机起自己的 nginx,把 root 与 alias 的路径拼接规则、结尾斜杠的陷阱、目录请求为什么是 403、权限怎么引起 403,以及 SPA 回退的坑逐个测了,每个都对照 error.log 里 nginx 实际去找的路径。
GET /static/b.txt -> 200 'static/b.txt' GET /static/nope.txt -> 404 '404 Not Found' error.log: open() "<tmp>/data/static/nope.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /static/nope GET /files/a.txt -> 200 'files/a.txt' —— 常见的错:想把 /static/ 指到 data/files,写成 root data/files: GET /static/a.txt -> 404 '404 Not Found' error.log: open() "<tmp>/data/files/static/a.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /static/a
404 时 error.log 写着 nginx 实际找的路径,对照期望的路径就知道哪里拼错。
location /static/ + alias .../files/(两边都有斜杠): GET /static/a.txt -> 200 'files/a.txt' location /static/ + alias .../files(alias 缺斜杠): GET /static/a.txt -> 404 '404 Not Found' error.log: open() "<tmp>/data/filesa.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /static/a.txt HTT location /static + alias .../files/(location 缺斜杠): GET /static/a.txt -> 200 'files/a.txt' GET /staticx.txt -> 404 '404 Not Found' error.log: open() "<tmp>/data/files/x.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /staticx.txt HTT —— 正则 location 里的 alias 要用捕获组: GET /dl/a.txt -> 200 'files/a.txt' GET /dl/nope.txt -> 404 '404 Not Found' error.log: open() "<tmp>/data/files/nope.txt" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /dl/nope.txt
root 接整个 URI,alias 替换匹配部分;结尾斜杠要两边一致。
GET /dir/ -> 403 '403 Forbidden' error.log: directory index of "<tmp>/data/dir/" is forbidden, client: 127.0.0.1, server: , request: "GET /dir/ HTTP/1.1", host: "127.0.0.1:97 GET /dir -> 301 '301 Moved Permanently' Location: http://127.0.0.1:9780/dir/ autoindex on:GET /dir/ -> 200,页面里有 "note.txt":True
没有 index 文件是 403;没有尾斜杠会 301;autoindex 才显示列表。
GET /files/a.txt -> 403 '403 Forbidden' error.log: open() "<tmp>/data/files/a.txt" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET /files/a.txt HTTP/1.1", GET /locked/secret.txt -> 403 '403 Forbidden' error.log: open() "<tmp>/data/locked/secret.txt" failed (13: Permission denied), client: 127.0.0.1, server: , request: "GET /locked/secret.tx GET /locked/secret.txt -> 200 'secret'
worker 用户要有路径上每级目录的 x 权限和文件的 r 权限。
GET /app/deep/route -> 200 '<html>SPA index</html>' GET /assets/app.js -> 200 'console.log(1)' GET /assets/missing.js -> 200 '<html>SPA index</html>' GET /app/deep/route -> 200 '<html>SPA index</html>' GET /assets/app.js -> 200 'console.log(1)' GET /assets/missing.js -> 404 '404 Not Found'
try_files 回退到 index.html 会让缺失的静态资源变成 200 的页面;静态资源目录单独加 =404。