【小哥哥, 跨域要不要了解下】CORS 基础篇

系列文章:

前一篇文章中, 我们一起学习了第一种跨域处理方案 JSONP. 这种方法相对比较原始, 优点是兼容性好, 就连现代前端没怎么听说过的 IE 6 上跑起来都是妥妥的. 然鹅, 它也就这一点优点了. 其缺点有: 只支持 GET 请求, 配置繁琐(前后端都需要调整代码), 在 window 上注册各种回调函数, 开发体验差....

CORS

由于 JSONP 的方案存在诸多缺点且老旧, 这里我们一起学习一种比较现代的跨域问题解决方案---CORS

兼容性

从 mdn 官网粘来的兼容性列表如下:

ie 10 都可以跑, 足以满足现代前端开发者的需求了.

概念 ?

概念性的东西在这儿 MDN 偶尔需要梯子, 自备哈.

搭建跨域的环境

我们先创建一个跨域的环境, 代码基于我们 jsonp 时候的示例项目 cross-domain, 首先, 在 fe 和 be 目录下创建 cors 目录. 其次, 分别添加 index.htmlindex.js. 修改以后的项目目录如下图.

编写前端代码 fe/cors/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>CORS 实现跨域</title>
</head>
<body>
    <h3>CORS 实现跨域</h3>

    <script>
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'http://localhost:8888')
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4 && xhr.status === 200) {
                console.log(xhr.responseText)
            }
        }
        xhr.send()
    </script>
</body>
</html>
复制代码

一个灰常简单的 ajax 请求, 有木有.

后端代码 be/cors/index.js

const http = require('http');

const PORT = 8888;

// 创建一个 http 服务
const server = http.createServer((request, response) => {
  response.end("{name: 'quanquan', friend: 'guiling'}");
});

// 启动服务, 监听端口
server.listen(PORT, () => {
  console.log('服务启动成功, 正在监听: ', PORT);
});
复制代码

此时的项目代码

找点苗头

代码环境准备完成后

  • 首先启动后端代码 node ./be/cors/index.js
  • 其次启动前端 web 容器 live-server ./fe/cors
  • 打开浏览器, 访问 http://localhost:8080/
  • 打开控制台, 切换到 Console tab
  • 刷新浏览器

我们细细分析这个熟悉的报错, 前一段告诉我们我们的请求被 block 了. 后边居然直接告诉我们解决方案了, 方案了 'Access-Control-Allow-Origin' header is present on the requested resource., 这么明显的暗示, 难道我们就不试试???

响应头添加 Access-Control-Allow-Origin

针对浏览器的报错, 我们分析出他是要我们在响应头上添加Access-Control-Allow-Origin这个字段, 那么我们修改我们的后端代码.

const http = require('http');

const PORT = 8888;

// 创建一个 http 服务
const server = http.createServer((request, response) => {
  response.setHeader('Access-Control-Allow-Origin', '*');
  response.end("{name: 'quanquan', friend: 'guiling'}");
});

// 启动服务, 监听端口
server.listen(PORT, () => {
  console.log('服务启动成功, 正在监听: ', PORT);
});
复制代码

改动后的代码.

巨大的 PS: 修改过后端代码以后, 一定要 重启 node 服务

浏览器刷新一下, 我了个乖乖. 好了 ?

开心过后, 我们想一下, jsonp 的缺点是只能支持 GET 请求, 作为现代的跨域请求方式. cors 能不能支持其他的请求方式呢?

其他请求方式的支持

作为现代的跨域问题解决方案, 应该是能解决多种请求方式的. 光说不练假把式. 咱们试试 ?

改动前端代码

// 改动前
xhr.open('GET', 'http://localhost:8888')
// 改动后
xhr.open('POST', 'http://localhost:8888')
复制代码

修改后代码来浏览器上看一下?

木有任何问题, 返回的数据顺利的打印. 没有任何的报错.

趁着兴头试试PUT请求

再次改动前端代码

// 改动前
xhr.open('POST', 'http://localhost:8888')
// 改动后
xhr.open('PUT', 'http://localhost:8888')
复制代码

修改后代码来浏览器上看一下?

哎呀我滴妈? 很眼熟的错误, 但是不要认错人哈, 这次的报错和之前的报错长的很像, 但是关键词不一样了. 根据之前的经验, 后端添加 Access-Control-Allow-Methods 响应头应该好使.

后端代码

const http = require('http');

const PORT = 8888;

// 创建一个 http 服务
const server = http.createServer((request, response) => {
  response.setHeader('Access-Control-Allow-Origin', '*');
  response.setHeader('Access-Control-Allow-Methods', 'PUT');
  response.end("{name: 'quanquan', friend: 'guiling'}");
});

// 启动服务, 监听端口
server.listen(PORT, () => {
  console.log('服务启动成功, 正在监听: ', PORT);
});
复制代码

修改后代码来浏览器上看一下?

成功了 ?

其他的 http 方法和 PUT 方法处理的方式是一样的. 举一反三即可.

后端说, 你的请求要加一个 token 呀

既然是现代的开发, 那么会话的管理一般是会用 jwt(后续可能会写相关的文章), jwt 一个闪耀的标志就是请求头添加了 jwt token. 明人不说暗话.

修改前端代码:

// 添加了一行
xhr.setRequestHeader('token', 'quanquanbunengshuo')
复制代码

修改后代码来浏览器上看一下?

相信大家已经摸清了我的套路, 闲话不扯.

后端代码

// 添加了一行
response.setHeader('Access-Control-Allow-Headers', 'token');
复制代码

修改后代码来浏览器上看一下?

目前为止, 跨域请求成功了, 请求方式兼容了, 自定义请求头好使了. 是不是大吉大利, 可以吃鸡了呢?

致, 被打入冷宫的 Network tab

我们自始至终都在查看浏览器的 Console tab, 作为一个通信性质的文章, 不看一下 Network 明显有点说不过去辣.

既然存在, 那肯定是要看看的, 我们把 tab 切换到 Network.

哎呦喂? 两个请求, 一个 OPTIONS 一个 PUT, 这是什么鬼?

下集预告: 刚刚看到了 Network 就出现了血案. 当然如果仅仅是停留在会用 CORS 实现跨域上, 到目前为止已经没有什么问题了, 用来面试也是杠杠滴. 下一步, 我们一起探讨 CORS 条件下, 预检请求Cookie 携带那些事儿. 周五码字感觉好累...... 约小姐姐去辣 ?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值