DRF接口返回HTTP文件链接引发HTTPS混合内容错误的解决方案咨询
DRF API返回HTTP文件链接导致HTTPS页面混合内容错误
已使用DRF搭建API应用,站点已安装SSL证书,但前端HTTPS页面(https://www.example.com)加载文件时出现错误:页面加载了不安全的HTTP资源(http://api.example.com/……)。返回的JSON示例中,媒体文件链接均以HTTP开头:
{ "id": 50, "name": "Образец заполнения книги учета доходов", "category": "Бухгалтерия и налоги", "count_download": 0, "type_doc": "xls", "screenshot": "http://api.example.com/media/screenshot/%.png", "add_time": "2023-03-27", "pdffile": "http://api.example.com/media/pdf_docs/%.pdf" }
环境使用容器化Nginx,配置如下:
server { server_name api.example.com; listen 80; root /var/html/; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name api.example.com; ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; root /var/html/; server_tokens off; client_max_body_size 10m; location ~ /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_pass http://backend:8000; } location /media/ { autoindex on; } location /docs/ { root /usr/share/nginx/html; try_files $uri $uri/redoc.html; } location /static/rest_framework/ { autoindex on; } location /static/admin/ { autoindex on; } location /admin/ { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_pass http://backend:8000/admin/; } } server { listen 80; server_name example.com www.example.com; root /var/html/; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; root /var/html/; location ~ /.well-known/acme-challenge/ { root /var/www/certbot; } location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri /index.html; } }
解决方法
1. 配置Django识别HTTPS代理
Django默认无法感知反向代理后的HTTPS请求,需在settings.py中添加以下配置:
# 信任Nginx传递的HTTPS协议头 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 允许的主机列表(根据实际域名调整) ALLOWED_HOSTS = ['api.example.com', 'example.com', 'www.example.com'] # 使用代理传递的主机和端口信息 USE_X_FORWARDED_HOST = True USE_X_FORWARDED_PORT = True
配置后,Django会基于代理头生成HTTPS格式的媒体文件链接。
2. 完善Nginx代理头配置
在api.example.com的443 server块中,为代理请求添加X-Forwarded-Proto头,将当前请求的协议(HTTPS)传递给后端Django:
修改location /和location /admin/部分:
location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; # 添加协议头 proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://backend:8000; } location /admin/ { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; # 添加协议头 proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://backend:8000/admin/; }
3. 强制媒体URL使用HTTPS(备选方案)
如果上述配置不生效,可直接在settings.py中硬编码媒体URL的HTTPS前缀:
MEDIA_URL = 'https://api.example.com/media/'
注意:此方法适合域名固定的场景,域名变动时需同步修改。
4. 检查Nginx媒体文件服务配置
当前Nginx的location /media/仅开启了autoindex,需确保媒体文件能被正确访问:
- 如果媒体文件由Django后端管理,将
location /media/改为代理到后端:
location /media/ { proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://backend:8000/media/; }
- 如果媒体文件直接挂载在Nginx容器中,指定文件路径:
location /media/ { root /path/to/your/media/directory; autoindex on; }
内容的提问来源于stack exchange,提问作者Саша Асеев
相关产品推荐
相关产品推荐

