最近在开发测试工具平台以支持对于外部 Http 服务的接入,后端使用的框架是 Django,前端使用的框架是 React,前后端分离且域名不一致的情况下难免遇到了 “跨域” 问题,下面的文章就是记录这次问题发现和解决的全过程(最终的结果有点啼笑皆非😂
阶段一问题:
前端发现所有的 post 请求,发起后变成了 get 请求,报错 403
排查解决:
1、post 请求变成 get 请求,第一反应就是怀疑是跨域请求的问题导致的,再加上自己即没有在服务层面解决跨域问题,有没有在 Ngnix 中进行处理跨域问题,OK,那就当做跨域问题去解决

2、跨域解决:
安装 django-cors-headers
pip3 install django-cors-headers
配置 settings.py 文件

INSTALLED_APPS = [
 ...
 'corsheaders',
 ...
 ] 

MIDDLEWARE_CLASSES = (
 ...
 'corsheaders.middleware.CorsMiddleware',
 'django.middleware.common.CommonMiddleware', # 注意顺序
 ...
)
#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
 '*'
)

CORS_ALLOW_METHODS = (
 'DELETE',
 'GET',
 'OPTIONS',
 'PATCH',
 'POST',
 'PUT',
 'VIEW',
)

CORS_ALLOW_HEADERS = (
 'XMLHttpRequest',
 'X_FILENAME',
 'accept-encoding',
 'authorization',
 'content-type',
 'dnt',
 'origin',
 'user-agent',
 'x-csrftoken',
 'x-requested-with',
 'Pragma',
)

然后启动服务,报错了 “ERRORS: ?: (corsheaders.E013) Origin '' in CORS_ORIGIN_WHITELIST is missing scheme or netloc HINT”
行吧,那就将
```CORS_ORIGIN_WHITELIST = ('
') ```此行给注释掉
重启服务,正常运行,以为成功解决了

阶段二问题
运行服务倒是不报错了,部署到测试环境,发现全部接口请求都 404,以前 Ok 的 GET 请求也是 404 Network Error
[311978940bfd4c59940b4167d3ca11f2__9f06bd7fb3d6419d8392cd9cebe5a199.png

继续排查解决:
1、从报错开始
报错:provisional headers are shown
打开控制台 Console 也有报错:
1bd402b39bc34e2eb823fcda8a8fda7e__38ac6cd724054b2dba685107e85e7e52.png
The 'Access-Control-Allow-Origin' header contains multiple values 'http://fe-test.yuceyi.com, http://fe-test.yuceyi.com'
包含了两个值,还是一样的,抓个包看一下,果然有两个 Access-Control-Allow-Origin
先看下第一个报错

84961dbe25474be6b93a0382836d06be__a32ea6fe3d0d491cb7c02b0a5251e5ce.png
挨个尝试了下,发现无效,然后怀疑是前端没有加 Content-Type 的请求头,让前端加上请求头后,发现依然没有解决问题
很是疑惑,接着查看服务器的请求日志发现,根本没有收到请求,此时已经开始怀疑是 Ngnix 配置的问题

2、
查看服务器上的 Nginx 配置文件,果不其然 cors 文件用以支持跨域,在 nginx.conf 中已经引入了该配置
1017efe981844b1798767c0afeb7bf5c__d9c17d53084f44b091144f42fbb98977_meitu_1.jpg
当时为了快速将服务部署到机器上,copy 了一部分测试环境的 Nginx 配置,后面就忘记了,导致 Nginx 已经实现了跨域,自己又在代码层次实现了一遍,下面的图片,也是对该问题的解答
12faeca1fa914d6788c6ddd10d8e3b89__a3b92419307a44c282362464f3f064e8.png

3、
OK,全部搞定,将代码里面关于跨域的代码注释掉,重新发布,发现还是不行
继续找解决方案:django 跨域请求时,为何将 post 请求转成了 get 请求?

各种寻找后,看到一个极老的帖子,也是同样的问题,其中有留言,说是因为静态资源文件的 url 和后端服务 url 重名了,比如后端服务的 url 是 /api/v1/take_case, 前端静态资源文件夹路径是/api/v1/take_case/ 这样就会出现上面的问题,在后端 url 中加上一个 / ,post 请求时也使用相应的 url 即可.
感觉已经找到了元凶,查看接口请求
85d2b87cbaa44b59912a3b7b562f117b__79bb08c5dbd34876a23b2604998db166.png
果然,我在 django 的 urls 配置和给到前端的接口文档中,该接口是 /http_tools/project/create/
但是前端给到我的接口却是 /http_tools/project/create 坑啊~~~~

最终解决:
让前端在接口最后加上一个 / 后解决问题
所以各位日常工作中一定一定要注意看接口文档啊。。。。 😂


↙↙↙阅读原文可查看相关链接,并与作者交流