You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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配置:

  1. 启动FastAPI时添加参数:
from fastapi import FastAPI

app = FastAPI(root_path="/swagger")
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:43:15