首先通读下 MDN 关于 CORS 的 定义,了解跨域的含义及简单请求和复杂请求等的定义。文中的内容不赘述,如今说解决方案。
经过定义咱们能够,简单请求与复杂请求的差异是复杂请求会自动发出一个 OPTIONS
的预检请求,当请求获得确认后,才开始真正发送请求。webpack
综上,咱们要解决两个问题:web
解决的方式有多种,既能够在Web Server解决,也能够在源码层解决。由于问题比较广泛,故咱们选择在Web Server解决,下面咱们以 Nginx 为例,说明解决方案。api
假设访问的地址为 /example
, Nginx 配置以下:跨域
location /example { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080/; }
为了解决跨域问题,添加以下内容:缓存
location /example { + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Max-Age 1728000; + add_header Access-Control-Allow-Methods GET,POST,OPTIONS; + add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + add_header Content-Type' 'text/plain; charset=utf-8'; + add_header Content-Length 0 ; + return 204; + } proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080/; }
if ($request_method = 'OPTIONS') {...}
当请求方法为 OPTIONS 时:webpack-dev-server
Access-Control-Allow-Origin
为 *
(可根据业务须要更改)Access-Control-Max-Age
,当下次请求时,无需再发送 OPTIONS 请求text/plain; charset=utf-8
, 返回状态码为 204
的首部至此,完成 OPTIONS 请求的正确响应。spa
添加以下内容:3d
location /example { if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin *; add_header Access-Control-Max-Age 1728000; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header Content-Type' 'text/plain; charset=utf-8'; add_header Content-Length 0 ; return 204; } + if ($http_origin ~* (https?://(.+\.)?(example\.com$))) { + add_header Access-Control-Allow-Origin $http_origin; + add_header Access-Control-Allow-Credentials true; + add_header Access-Control-Allow-Methods GET,POST,OPTIONS; + add_header Access-Control-Expose-Headers Content-Length,Content-Range; + } proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080/; }
if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {...}
, 当 origin 为合法域名(可根据业务调整或去除合法域名验证)时:代理
Access-Control-Allow-Origin
为 $http_origin
(可根据业务须要更改)Access-Control-Allow-Credentials
为 true
,容许接收客户端 Cookie
(可根据业务须要更改。 但要注意,当设置为true
时,Access-Control-Allow-Origin
不容许设置为 *
)至此,完成跨域请求正确响应。code
以上,是对跨域请求在Web Server的解决方案,主要是经过响应 OPTIONS
方法和添加容许源来解决。
固然,若是本地开发中,能够在利用 webpack-dev-server
的 proxy 选项来快速解决跨域问题:
示例以下:
// webpack.congf.js module.exports = { //... devServer: { proxy: { '/api': { target: 'http://localhost:3000', pathRewrite: {'^/api' : ''} } } } }
当访问地址如 /api/foo?q=bar
时,则经过代理访问的实际地址是: http://localhost:3000/foo?q=bar
CORS跨域请求并不魔幻,理解 CORS 的含义,根据规则去找方法就迎刃而解了。但愿能帮助到你们。
以上。