什么是中间件
在路由相应之前就会执行中间件的内容,例如在中间件中进行赋值,这种就可以在路由执行时使用这个值。
所以中间件就是服务器开启之后和路由响应之前执行的一个函数。这个函数可以操作req与res。使用next()
向下传递到下一个中间件,最后传到路由。
例如开启三个中间件的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| app.use((req, res, next) => { console.log("中间件1"); req.requestTime = Date.now(); next(); }); app.use((req, res, next) => { console.log("中间件2"); next(); });
app.get("/", (req, res) => { console.log(Date.now() - req.requestTime); res.send("Hello World!"); });
|
什么是跨域
浏览器使用ajax
时,如果请求的接口地址和当前打开的页面地址不同源称之为跨域。
协议和地址、端口都一样成为同源。有一个不同则为不同源。
同源与不同源的意义
浏览器安全策略。
设置响应头允许跨域
只需要在响应头处设置Access-Control-Allow-Origin
为*
即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| app.post("/login", (req, res) => { res.setHeader("Access-Control-Allow-Origin", "*"); let { username, password } = req.body; if (username == "admin" && password == "123") { res.send({ code: 200, msg: "登陆成功", }); } else { res.send({ code: 400, msg: "登陆失败", }); } });
|
在中间件设置允许跨域
因为中间件会在执行路由之前会被调用,因此可以将设置响应头在中间件中设置。
1 2 3 4 5
| app.use((req, res, next) => { res.setHeader("Access-Control-Allow-Origin", "*"); next(); });
|
安装cors
模块(npm i cors
)。接下来使用即可。
1 2
| const cors = require("cors"); app.use(cors());
|
jsonp
原理
通过动态创建script
标签,通过script
标签的src
请求没有域限制来获取资源
例如在html页面中,将script
标签地址改为后端接口。
1 2 3 4
| app.get("/all", (req, res) => { console.log(Date.now() - req.requestTime); res.send("console.log('hah')"); });
|
1
| <script src="http://127.0.0.1:3000/all"></script>
|
那么当服务器开启时,我们就会看到返回来的内容会当作JavaScript
代码执行。
因此此方式需要与前端进行配合才可使用。例如前端通过get参数方式将函数名传递给后端。
1 2 3 4 5 6 7 8 9
| <script> function fn() { console.log('这是事先准备好的函数!') } function fn1(backData) { console.log(backData) } </script> <script src="http://127.0.0.1:3000/all?callback=fn"></script>
|
1 2 3 4 5 6 7 8
| app.get("/all", (req, res) => { let fn = req.query.callback; res.send(`fn()`); }); app.get("/all", (req, res) => { let fn = req.query.callback; res.send(`${fn}({'name':'haha','price':100})`); });
|
动态获取数据的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head>
<body> <button id="btn">点我获取</button> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script> function sb(backData) { console.log(backData); } $('#btn').on('click', function () { var script1 = document.createElement('script') $(script1).attr('src', 'http://127.0.0.1:3000/all?callback=sb') $('body').append(script1) }) </script> </body>
</html>
|
1 2 3 4
| app.get("/all", (req, res) => { let fn = req.query.callback; res.send(`${fn}({'name':'haha','price':100})`); });
|
ajax请求使用jsonp
1 2 3 4 5 6 7
| $.ajax({ url: 'http://127.0.0.1:3000/all', dataType: 'jsonp', success: function (backData) { console.log(backData) } })
|
如果访问的接口支持jsonp,那么jQuery会自动创建script标签
请求一言接口示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head>
<body> <button id="btn">点我获取</button> <div></div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script> function sb(backData) { console.log(backData); } $('#btn').on('click', function () { $.ajax({ url: 'https://v1.hitokoto.cn?encode=json', dataType: 'jsonp', success: function (backData) { let data = JSON.parse(backData)
$('div').html(data['hitokoto'] + '---' + data['from'])
} }) }) </script> </body>
</html>
|