部署在Railway的Django+DRF项目Ajax跨域请求失败求助
问题背景
我使用Django、DRF结合jQuery Ajax开发项目,本地运行(localhost或127.0.0.1:8000)时POST/GET请求正常,但部署到Railway后出现CORS错误。已尝试将域名加入settings.py的CORS_ALLOWED_ORIGINS和CORS_ORIGIN_WHITELIST,但问题未解决。相关配置及错误信息如下:
当前配置
# settings.py CORS_ALLOWED_ORIGINS = [ 'http://localhost:3000', 'http://127.0.0.1:3000', 'https://my-domain.com', ] CORS_ORIGIN_WHITELIST = [ 'http://localhost:3000', 'https://my-domain.com', ] ALLOWED_HOSTS = ['*'] CSRF_TRUSTED_ORIGINS = ['https://my-domain.com', 'http://127.0.0.1']
Ajax请求代码
// main.js $.ajax({ url: `https://my-domain.com/api/blogview`, type: "GET", dataType: "json", // 省略其他配置项 });
模拟非本地服务器的错误提示
The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead.
修复方案
1. 统一CORS配置项
CORS_ORIGIN_WHITELIST是django-cors-headers旧版配置项,新版已被CORS_ALLOWED_ORIGINS替代,保留其中一项即可,避免配置冲突。删除CORS_ORIGIN_WHITELIST,仅保留CORS_ALLOWED_ORIGINS。
2. 适配Railway反向代理的HTTPS配置
Railway通过反向代理提供服务,需让Django识别真实请求协议:
# settings.py中添加 CORS_ALLOW_CREDENTIALS = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
3. 完善CSRF信任源配置
确保CSRF_TRUSTED_ORIGINS包含Railway分配的完整HTTPS域名(含自定义域名和Railway默认域名):
CSRF_TRUSTED_ORIGINS = [ 'https://my-domain.com', 'https://your-railway-assigned-domain.up.railway.app' ]
4. 检查django-cors-headers中间件顺序
确保CorsMiddleware在CommonMiddleware之前加载,保证CORS头优先处理:
# settings.py INSTALLED_APPS = [ # 其他应用 'corsheaders', 'rest_framework', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 其他中间件 ]
5. POST请求需传递CSRF令牌
如果涉及POST请求,在Ajax中添加CSRF令牌头部:
$.ajax({ url: `https://my-domain.com/api/blogview`, type: "POST", dataType: "json", headers: { "X-CSRFToken": getCookie("csrftoken") }, // 其他配置 }); // 获取CSRF令牌的辅助函数 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; }
6. 处理Cross-Origin-Opener-Policy错误
本地测试非localhost地址时,需用HTTPS协议(如通过ngrok代理);部署到Railway后默认使用HTTPS,只要完成上述配置即可解决该错误。
内容的提问来源于stack exchange,提问作者Victor Okoye

