Nginx子域名配置异常:swagger.example.com无法加载API定义
Nginx子域名配置问题:Swagger页面加载API定义失败
问题描述
预期部署三个域名:
- example.com
- swagger.example.com
- api.example.com
后端基于FastAPI开发,希望将localhost:8000/docs映射到swagger.example.com,但访问该域名时始终提示Failed to load API definition。奇怪的是,未在Nginx中配置的api.example.com/docs却能正常访问。
当前Nginx配置如下:
user nginx; worker_processes 4; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { server { listen 80; listen [::]:80; server_name .example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name triptip.pro; server_tokens off; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://example_service:8000; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name swagger.example.com; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://example_service:8000/docs; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; } } }
问题根源
FastAPI的Swagger UI依赖加载openapi.json等核心文件,这些文件的请求路径是基于当前域名的根路径生成的。你当前把swagger.example.com的根路径直接代理到http://example_service:8000/docs,导致Swagger UI尝试从swagger.example.com/openapi.json获取API定义,但这个路径在Nginx中没有对应代理规则,返回404错误,最终触发加载失败提示。
而api.example.com/docs能正常访问,是因为它走了.example.com的泛域名HTTPS重定向后,实际访问的是后端完整路径,Swagger UI可以正确加载同域名下的/openapi.json。
修复方案
方案一:保留后端路径结构(推荐)
修改swagger.example.com的server块,不要直接代理根路径到/docs,而是代理整个后端服务,同时添加根路径到/docs的重定向:
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name swagger.example.com; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 根路径重定向到/docs location = / { return 302 /docs; } # 代理所有其他路径到后端服务 location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://example_service:8000; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; } }
方案二:指定FastAPI根路径
如果希望swagger.example.com仅提供Swagger相关页面,可以在FastAPI启动时设置root_path,并调整Nginx配置:
- 启动FastAPI时添加参数:
from fastapi import FastAPI app = FastAPI(root_path="/swagger")
- 修改Nginx的
swagger.example.com配置:
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name swagger.example.com; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://example_service:8000/swagger/docs; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; # 重写响应中的路径,让Swagger能正确找到openapi.json sub_filter '"/openapi.json"' '"/swagger/openapi.json"'; sub_filter_once off; } location /swagger { proxy_pass http://example_service:8000/swagger; proxy_set_header Host $http_host; } }
额外注意事项
- 检查SSL证书是否包含
swagger.example.com,如果当前api.example.com的证书未覆盖该子域名,需要重新申请包含所有所需子域名的证书。 - 补充
api.example.com的独立server块配置(当前配置中未明确设置,它依赖泛域名规则,若需单独定制行为需添加对应server块)。
内容的提问来源于stack exchange,提问作者cosmosfactory
相关产品推荐
相关产品推荐

