切换到HTTPS后FastAPI应用无法找到CSS文件的问题
问题:HTTPS下静态文件返回301 Moved Permanently错误
环境与配置
- 部署环境:Amazon Linux EC2实例,使用Docker + Nginx
- 前端文件路径:
/app/app/static/、/app/app/templates/ - FastAPI静态文件挂载代码:
current_directory = os.path.dirname(os.path.abspath(__file__)) templates_directory = os.path.join(current_directory, "templates") static_directory = os.path.join(current_directory, "static") app = FastAPI(openapi_url="/openapi.json") app.mount("/templates", StaticFiles(directory=templates_directory), name="templates") app.mount("/static", StaticFiles(directory=static_directory), name="static")
- HTML引用静态资源:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="/static/style.css"> </head>
问题现象
HTTP访问时index.html加载正常,但切换到HTTPS后,style.css文件返回301: Moved Permanently错误。已确认Docker容器内该文件存在且内容正常。
当前Nginx配置
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; types_hash_max_size 4096; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; server { listen 80; server_name mywebsite.com www.mywebsite.com; # Redirect all HTTP requests to HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot location / { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Add the static location block here for both HTTP and HTTPS location /static/ { alias /app/app/static/; try_files $uri $uri/ =404; } } # This server block is automatically added by Certbot for redirection server { listen 80; server_name mywebsite.com www.mywebsite.com; if ($host = mywebsite.com) { return 301 https://$host$request_uri; } # managed by Certbot return 404; # managed by Certbot } }
已排查操作
- 验证文件权限正常
- 尝试重命名、移动文件排查目录权限问题
- 测试Nginx配置中路径带尾斜杠/不带尾斜杠的情况
解决方案分析
问题核心是Nginx静态资源配置与FastAPI挂载路径冲突,叠加重定向逻辑干扰:
1. 冲突原因
你同时在Nginx配置了location /static/(带尾斜杠)直接读取本地文件,又在FastAPI中挂载了/static路径。当HTTPS请求/static/style.css时,Nginx的带尾斜杠规则无法匹配该路径,请求会落到location /被代理到FastAPI;而FastAPI的StaticFiles组件可能因X-Forwarded-Proto处理逻辑,返回HTTP版本的重定向,最终触发301错误。
2. 修复方案
方案一:统一由Nginx处理静态资源
修改Nginx的静态资源匹配规则(去掉尾斜杠),确保覆盖所有/static开头的请求:
location /static { alias /app/app/static; try_files $uri $uri/ =404; }
同时可注释FastAPI中app.mount("/static", ...)的代码,彻底避免路径冲突。
方案二:统一由FastAPI处理静态资源
删除Nginx中的location /static/配置块,让所有静态请求通过location /代理到FastAPI。需确保FastAPI正确识别HTTPS协议,避免生成HTTP重定向:
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware app.add_middleware(HTTPSRedirectMiddleware)
该中间件会强制所有请求跳转至HTTPS,适配当前Nginx的重定向逻辑。
清理重复重定向配置
当前Nginx存在两个监听80的server块,保留一个即可避免逻辑冲突:
server { listen 80; server_name mywebsite.com www.mywebsite.com; return 301 https://$host$request_uri; }
3. 验证步骤
- 执行
nginx -t验证Nginx配置语法正确 - 重启Nginx:
sudo systemctl restart nginx - 重启FastAPI容器
- 测试HTTPS下静态资源加载情况
内容的提问来源于stack exchange,提问作者Wrong-oo
相关产品推荐
相关产品推荐

