跨域问题解决方案
所谓跨域请求失败, 就是跨域访问其他域名下的资源, 包括在2级域名在内. 这是一种浏览器行为, 服务器并没有什么关于限制. 如果用api 实际上是可以访问到资源的, 只是浏览器的一种自发保护行为.
跨域问题有俩种解决方案 1. CORS 2. JSONP
服务端需要在资源把下面这一坨加到response的header里, 好像不需要这么多, 我反正都加上就好了, * 可以改为指定的地址.
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers Access-Control-Allow-Headers,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,imei,Access-Control-Allow-Origin,appKey;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Credentials true;
add_header Content-Type application/x-www-form-urlencoded;
location ^~/api/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers Access-Control-Allow-Headers,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,imei,Access-Control-Allow-Origin,appKey;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Credentials true;
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_pass http://gaga-api;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Connection "";
default_type application/octet-stream;
}
而JSONP呢, 是一种老旧的办法, 适用于IE8以下的浏览器, 已经绝迹了
拿tornado举例 解决JSONP 需要在请求中读取额外的参数'callback' 然后再 更改返回的json ,加入一些特别的参数, 这样对正常的API请求就有影响了, 所以JSONP 没什么乱用,不要用 才对.
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed
如果错误是这样的, 说明nginx跟tornado里都写了一次header里的A-C-A-O 重复了
------------------------ok 以上是入门级操作------------------------------
在浏览器行为中 对于跨域还有一种情况, 如果遇到的请求是get post header
称之为简单请求
的,那么在CORS时 就用上面这种方法就可以了, 如果是put delete
这种称之为复杂请求
再遇到CORS问题时,
浏览器会安全起见会发送一个pre-flight
OPTIONS
请求, 期待返回状态吗2XX
,
如果server端没有实现OPTIONS方法 则会报错 OPTIONS 405 method not allowed错误, 然后再跟一个跨域的报错.
遇到这种情况 要么我们避免使用复杂请求,改用get post, 要么就实现一个options方法 直接返回2xx状态就可以了.