目录
5.5.1Access-Control-Allow-Origin
5.5.2Access-Control-Allow-Headers
5.5.3Access-Control-Allow-Methods
1.创建基本的服务器
2.创建API路由模块
3.编写GET接口
4.编写POST接口
5. CORS 跨域资源共享
5.1接口的跨域问题
在线的jquery :可以直接复制地址写在script中
接口是通过http协议向外提供的,网页是通过file协议来访问的,此时就会出现跨域的问题。解决办法:
- CORS(主流的解决方案,推荐使用)
- JSONP(有缺陷的解决方案:只支持GET请求)
5.2使用CORS 中间件解决跨域问题
cors 是Express的一个第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题。使用步骤分为如下3步:
- 运行npm install cors安装中间件
- 使用const cors = require('cors')导入中间件
- 在路由之前调用app.use(cors())配置中间件
5.3什么是CORS
5.4CORS 的注意事项
- CORS主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口。
- CORS在浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。
5.5CORS响应头部
5.5.1Access-Control-Allow-Origin
可以控制允许哪些网页或者网站来请求服务器接口
如果指定了Access-Control-Allow-Origin字段的值为通配符*,表示允许来自任何域的请求,示例代码如下:
5.5.2Access-Control-Allow-Headers
默认情况下,CORS仅支持客户端向服务器发送如下的9个请求头:
5.5.3Access-Control-Allow-Methods
默认情况下,CORS仅支持客户端发起GET、POST、HEAD请求。
5.6CORS请求的分类
客户端在请求CORS 接口时,根据请求方式和请求头的不同,可以将CORS的请求分为两大类,分别是:
简单请求:客户端与服务器之间只会发生一次请求
预检请求:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求
对简单请求和预检请求区别的测试:(谷歌浏览器无法演示,换一个浏览器来演示)
6.JSONP 接口
6.1回顾JSONP的概念与特点
概念:浏览器端通过<script>标签的 src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP。
特点:JSONP不属于真正的Ajax请求,因为它没有使用XMLHttpRequest这个对象。JSONP仅支持GET请求,不支持 POST、PUT、DELETE等请求。
6. 2创建JSONP接口的注意事项
如果项目中已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP 的接口。否则JSONP接口会被处理成开启了CORS的接口。示例代码如下:
6. 3实现JSONP 接口的步骤
- 获取客户端发送过来的回调函数的名字
- 得到要通过JSONP形式发送给客户端的数据
- 根据前两步得到的数据,拼接出一个函数调用的字符串
- 把上一步拼接得到的字符串,响应给客户端的<script>标签进行解析执行
实现JSONP接口的具体代码
6.4在网页中使用jQuery 发起JSONP请求
调用$.ajax()函数,提供JSONP的配置选项,从而发起JSONP请求,示例代码如下:
14测试接口跨域问题.html运行在浏览器,点击JSONP按钮
7.整体代码实现
12使用express写接口.js
// 1导入express const express = require('express') // 1创建服务器实例 const app = express() // 注意:如果要获取URL-encoded格式的请求体数据,必须配置中间件app.use(express.urlencoded([{extended:false})) app.use(express.urlencoded({ extended: false })) // 必须在配置cors中间件之前,配置JSONP的接口 app.get('/api/jsonp', (req, res) => { // TODO:定义JSONP接口具体的实现过程 // .得到函数的名称 const funcName = req.query.callback //2.定义要发送到客户端的数据对象 const data = { name: 'sjf', age: 23 } //3.拼接出一个函数的调用 const scriptStr = `${funcName}(${JSON.stringify(data)})` // 4.把拼接的字符串,响应给客户端 res.send(scriptStr) }) // 一定要在路由之前,配置cors这个中间件,从而解决接口跨域的问题 const cors = require('cors') app.use(cors()) // 2导入路由模块 const router = require('./13apiRouter') // 2把路由模块注册到app上 app.use('/api', router) // 1启动服务器 app.listen(8080, () => { console.log('express server running at http://127.0.0.1:8080') })
13apiRouter.js
const express = require('express') const router = express.Router() // 3在这里挂载对应的路由 // 定义GET接口 router.get('/get', (req, res) => { // 通过req.query获取客户端通过查询字符串发送到服务器的数据 const query = req.query // 调用res.send方法,向客户端响应处理的结果 res.send({ status: 0, //0表示处理成功,1表示处理失败 msg: 'GET请求成功!', //状态的描述 data: query //需要响应给客户端的数据 }) }) // 定义POST接口 router.post('/post', (req, res) => { // 通过req.body获取请求体中包含url-encoded格式的数据 const body = req.body // 调用res.send方法,向客户端响应处理的结果 res.send({ status: 0, //0表示处理成功,1表示处理失败 msg: 'POST请求成功!', //状态的描述 data: body //需要响应给客户端的数据 }) }) // 定义delete接口 router.delete('/delete', (req, res) => { res.send({ status: 0, //0表示处理成功,1表示处理失败 msg: 'DELETE请求成功!', //状态的描述 }) }) module.exports = router
14测试接口跨域问题.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 在线版本的jquery --> <script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.min.js"></script> </head> <body> <button id="btnGET">GET</button> <button id="btnPOST">POST</button> <button id="btnDelete">DELETE</button> <button id="btnJSONP">JSONP</button> <script> $(function() { // 1测试get接口 $('#btnGET').on('click', function() { $.ajax({ type: 'GET', url: 'http://127.0.0.1:8080/api/get', data: { name: 'ch', age: 24 }, success: function(res) { console.log(res) } }) }) // 1测试post接口 $('#btnPOST').on('click', function() { $.ajax({ type: 'POST', url: 'http://127.0.0.1:8080/api/post', data: { name: 'jf', age: 23 }, success: function(res) { console.log(res) } }) }) // 为删除按钮绑定点击事件处理函数 $('#btnDelete').on('click', function() { $.ajax({ type: 'DElETE', url: 'http://127.0.0.1:8080/api/delete', success: function(res) { console.log(res) } }) }) // 1为JSONP按钮绑定带年纪事件处理函数 $('#btnJSONP').on('click', function() { $.ajax({ type: 'GET', url: 'http://127.0.0.1:8080/api/jsonp', dataType: 'jsonp', success: function(res) { console.log(res) }, }) }) }) </script> </body> </html>