最近打算将原来放在别人服务器上的Live2D Api切换到自己的服务器上;配置环境和修改相关配置文件都很简单,但是在API更换之后刷新网页发现曾经正常显示的内容消失了,F12的控制台输出了一个错误:
Access to font at ‘http://test.api.com’ from origin ‘http://test.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
通过阅读可以发现是需要在Header中配置跨域选项才能跨域访问导致的。这个问题出现是因为服务器默认是不允许跨域的——CROS规定的:
跨域资源共享(CORS)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
跨域资源共享 (Cross-origin resource sharing)
这个协议还规定了除了以下三类以外的所有MIME类型都需要预检请求:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
所以像前文所述的application/json请求就会在正式通信之前先发出一个预检请求,这个预检请求会检查服务器是否配置了Access-Control-Request-Headers: Content-Type,如果没有配置就会跳出前文描述的问题。
如果你在网上搜索的话,多半会遇到这个答案:
1 2 3 4 5 |
location / { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; } |
但是这个答案对于有些服务器(比如我的)来说是无法工作的,有些服务器配置比较复杂或者location和默认配置并不相同,这就需要你针对自己的服务器进行修改,例如我的服务器所有api都在同一个位置配置,也就是说同一个服务器返回所有结果都是可以跨域的,我可以直接在server层级添加这些内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen 443 ssl http2; …… add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested- With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; …… } |
这样就完成了配置,按住ctrl+F5刷新网页,就能看到API已经正常工作了,我们的看板娘又回来了。