十二、Express接口编写 —— 跨域问题

         在前面的HTTP模块内容内容当中讲到这个跨域的问题,跨域就涉及到浏览器的同源策略,跨域只出现在浏览器当中,在浏览器当中去执行脚本的时候会进行一个同源检测,只有是同源的脚本才会被浏览器执行,不同源就是跨域,同源就是请求的url协议、域名、端口号要相同,只有相同的才能够互相访问,不同就会出现跨域问题。下面用一个简单的例子图示理解:


后端解决跨域

下面来回顾之前通过后端处理的方式解决跨域的问题;通过后端的设置来解决请求跨域的问题:

Access to XMLHttpRequest at 'http://127.0.0.1:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

         http://127.0.0.1:5500发起请求http://127.0.0.1:3000/中的数据,协议相同,域名相同,端口号不同出现跨域请求的问题,通过后端的设置解决跨域的问题,在后端设置中设置以下属性:

Access-Control-Allow-Origin",'*'
Access-Control-Allow-Headers","X-Requested-With"
Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"

        那么在HTTP模块中已经具体的讲述,就不在赘述了;


cors中间件 解决跨域

        上一篇内容讲到这个中间件,那么这里来用使用cors中间件来解决跨域问题,cors是Express的一个第三方中间件;cors(cross-origin-resource Sharing)意思就是跨域资源共享,是由一系列的HTTP响应头组成,这些HTTP响应头也就决定了浏览器是否要阻止前端的js脚本去跨域请求获取资源,CROS主要是在服务器进行配置的,客户端浏览器无须做任何额外的配置,就可以开启了CROS的接口,但CORS在浏览器中有兼容性,例如IE10+,Chrome4+,FireFox3.5+;下面就来安装和使用这个cors中间件:

1. 安装cors第三方中间件;

npm install cors

2. 导入cors第三方中间件使用;

const express = require('express');
const app = express();
const fs = require('fs');
const cors = require('cors');
app.use(cors());
app.get('/',function(req,res){
    let data = fs.readFileSync(__dirname + '/全国行政区数据.json')
    res.end(data);
})
app.listen('3000',function(){
    console.log('Server Running || 127.0.0.1:3000');
})

3. 测试使用;

通过编写一个index.html页面发起ajax请求:

<!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>全国行政区</title>
</head>
<body>
    <div id='app'>
        <h2>全国行政区</h2>
        <ul class="city">
        </ul>
    </div>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
        $.ajax({
            url:'http://127.0.0.1:3000'
        }).then(res=>{
            const rs = JSON.parse(res); 
            for(const i in rs.result){
                $('.city').append('<li>'+rs.result[i].name+'</li>');
            }         
        })
    </script>
</body>
</html>

         如果不使用的话,将app.use(cors())内容人注视点然后打开浏览器来对比使用cors中间件后HTTP响应头(Response Hearders):

Access-Control-Allow-Orgin

         Access-Control-Allow-Orgin: * 表示允许来自任何域的请求,当然了也可以进行一个IP的限制,限制在某个域名之下才能够访问,有如下形式:

res.setheader("Access-Control-Allow-Orgin":"*");
res.setheader("Access-Control-Allow-Orgin":"http://mp.csdn.net"); 

Access-Control-Allow-Headers

        默认情况下,cors仅支持客户端向浏览器发送这(Accept、Accept-Language、Content-Langage、DPR、Downink、Save-Data、Viewport-Width、Width、Content-Type[value:text/plain、multipart/from-data、application/x-www-form-urlencded])9个请求头,如果客户端向服务器发送了额外的请求消息,则需要在服务器端通过Access-Control-Allow-Headers 对额外的请求进行声明,否则会请求失败;如下需要进行其他请求头设置:

res.setHeader('Access-Control-Allow-Headers','Content-Type,X-Custom-Header')

Access-Control-Allow-Methods

        默认情况下,CORS仅支持客户端发起GET、POST、HEAD请求,如果客户端希望通过PUT、DELETE等方式请求服务器资源,则需要在服务器端,通过Access-Control-Allow-Methods来指明实际请求所允许使用的HTTP方法;

// 只允许post,get,head,delete
res.setHeader('Access-Control-Allow-Methods','POST,GET,HEAD,DELETE');
// 允许所有请求方式
res.setHeader('Access-Control-Allow-Methods','*');

cors请求分类

        cors请求分为两种:简单请求和预检请求

简单请求

         GET / POST / HEAD 这三种任意一种请求方式,同时HTTP头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Langage、DPR、Downink、Save-Data、Viewport-Width、Width、Content-Type[value:text/plain、multipart/from-data、application/x-www-form-urlencded]

预检请求

        请求除了 GET/POST/HEAD 这三种的其他请求METHOD类型,请求头包含自定义头部字段,向服务器发送application/json的数据;

        在浏览器与服务器进行正式通信之前,浏览器会先发送OPTION请求进行预检,以获得服务器是否允许该实际请求,所以这次的OPTION请求称为 "预检请求",服务器成功响应预检请求后,才会发送真实的请求且携带真实数据。

区别:

        在简单请求中,客户端与服务器之间只发生一次请求,而在预检请求中,客户端与服务器之间发生两次请求,OPTION预检请求成功之后才会发起真正的请求;

下面来进行测试:

1. 编写代码

<!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>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
    <button id="get">简单请求</button>
    <button id="del">预检请求</button>
    <script>
        $('#get').on('click',function(){
            $.ajax({
                type:'GET',
                url:'http://127.0.0.1:3000/get',
                success:function(res){
                    console.log(res);
                }
            })
        })

        $('#del').on('click',function(){
            $.ajax({
                type:'DELETE',
                url:'http://127.0.0.1:3000/del',
                success:function(res){
                    console.log(res);
                }
            })
        })
    </script>

</body>
</html>
// Express  -  /routes/index.js
const express = require('express');
const router = express.Router();
router.get('/get',function(req,res){
    res.send('success');
})
router.delete('/del',function(req,res){
    res.send({
        status:0,
        msg:'success'
    })
})
module.exports = router;

        通过执行node命令将服务器启动:

        通过编写request.html模拟客户端来点击按钮发起对应的请求:

(Chrome谷歌浏览器)

(Firefox火狐浏览器) 

        以上就是关于cors中间件的知识和解决跨域问题的全部内容了,下面来讲另外一种跨域方式JSONP. 


JSONP接口 解决跨域

        在前面中讲到了浏览器中的同源策源,需要访问的协议,域名和端口号要一致才能够进行跨域,但在HTML中,用过<script><img><link><video><aduio>这些标签中的一个src属性,通过这个属性可以访问到来自不同域的资源,这种请求方式就是JSONP,请求服务器上的数据,同时服务器返回一个函数的调用;JSONP不属于真正的Ajax请求,因为它没有XmlHttpRequest这个对象,同时JSONP仅支持GET请求,这也是JSONP的一个缺点,不支持其他POST、DELETE、HEAD等请求。

        JSONP接口创建之前如果配置了CORS跨域资源共享,为了防止冲突需要在配置注册使用(app.use())CORS中间件之前声明JSONP的接口,否则JSONP接口会被处理成开启了CORS接口,如下:

const express = require('express');
const app = express();
const cors = require('cors');

app.get('/jsonp',function(req,res){
    // jsonp具体实现
})

// 配置cors中间件
app.use(cors());

// CORS接口
app.get('/get',function(req,res){
    // cors具体实现    
})

下面来编写JSONP的接口

// index.js
const express = require('express');
const app = express();
const cors = require('cors');

app.get('/jsonp',function(req,res){
    const getInfo = req.query.callback;
    // 模拟数据
    const data = { 
        name:'syan123',
        sex:'女',
        age:18
    }
    const cbStr = `${getInfo}(${JSON.stringify(data)})`;
    res.send(cbStr);
})
app.use(cors());
app.listen('3000',function(req,res){
    console.log('Server Running || 127.0.0.1:3000');
})

        通过 jquery 发起 JSONP 请求,当然这个地方讲jsonp的一个内容会有一些片面,那么如果有后续会在js当中去提及到,这里仅仅是将JSONP也是能够实现跨域的一种手段跟大家聊聊;

<!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>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
    <button id="jsonp">jsonp</button>
    <script>
        $('#jsonp').on('click',function(){
            $.ajax({
                type:'get',
                dataType:'jsonp',
                // jsonpCallback:'syan',
                url:'http://127.0.0.1:3000/jsonp',
                success:function(res){
                    console.log(res);
                }
            })
        })
    </script>
</body>
</html>

        通过客户端发送过来的回调函数的名字,可以通过req.query.callback,如果没有写callback方法,jquery会自动封装一个callback方法;

        以上就是本篇关于接口实现跨域的全部内容,感谢大家的支持! 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂学者

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值