如何在drf_yasg中切换HTTP/HTTPS协议而非硬编码URL?
当然可行!你不需要硬编码URL字符串,有两种更优雅的方式让drf_yasg自动根据请求协议生成正确的Swagger请求地址,解决混合内容错误:
方法1:配置Django识别ALB的HTTPS转发头
这是最推荐的方案,它能让整个Django应用(包括drf_yasg)自动感知请求是否来自HTTPS。
当你的DRF应用部署在AWS ALB后,ALB会将HTTPS请求转发为HTTP到EC2实例,同时会添加X-Forwarded-Proto头标记原始请求的协议。你只需要在Django的settings.py中添加以下配置:
# settings.py SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
这个配置告诉Django:如果请求包含X-Forwarded-Proto: https头,就认为当前请求是通过HTTPS访问的。这样,drf_yasg会自动使用HTTPS作为Swagger文档中的服务器协议,无需手动指定URL。
注意:AWS ALB默认会自动添加
X-Forwarded-Proto头,一般不需要额外配置监听器。
方法2:动态生成Swagger服务器地址
如果需要更灵活的控制(比如同时支持HTTP和HTTPS测试环境),可以通过servers参数动态生成服务器地址,根据当前请求的协议和主机来设置:
from django.http import HttpRequest from drf_yasg import openapi from drf_yasg.views import get_schema_view def dynamic_servers(request: HttpRequest): # 根据当前请求的协议和主机生成服务器地址 return [openapi.Server(url=f"{request.scheme}://{request.get_host()}")] schema_view = get_schema_view( openapi.Info( title="Server Api Documentation", default_version="v1", description="", ), # 传入动态生成服务器的函数 servers=dynamic_servers, )
这样每次访问Swagger UI时,都会根据当前请求的协议(HTTP/HTTPS)自动生成对应的服务器URL,彻底避免硬编码的问题。
为什么之前会出现混合内容错误?
因为ALB将HTTPS请求转发为HTTP到你的EC2实例,Django默认认为请求是HTTP的,所以drf_yasg生成的Swagger文档中使用了HTTP作为服务器协议,导致页面在HTTPS环境下发起HTTP请求,触发浏览器的混合内容拦截。
内容的提问来源于stack exchange,提问作者Artur Siepietowski

