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

news2024/9/23 20:22:09

         在前面的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方法;

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/137816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL高级 SQL优化【order bygroup by优化】

目录 1&#xff1a;SQL优化 1.1&#xff1a;order by优化 A. 数据准备 B. 执行排序SQL C. 创建索引 D. 创建索引后&#xff0c;根据age, phone进行升序排序 E. 创建索引后&#xff0c;根据age, phone进行降序排序 F. 根据phone&#xff0c;age进行升序排序&#xff…

STM32MP157驱动开发——Linux 网络设备驱动

STM32MP157驱动开发——Linux 网络设备驱动一、简介STM32MP1 GMAC 接口简介YT8511C 详解二、驱动开发1.网络外设的设备树2.设备驱动三、测试网速测试参考文章&#xff1a;【正点原子】I.MX6U嵌入式Linux驱动开发——Linux 网络驱动 一、简介 网络驱动是 linux 驱动三巨头之一&…

[C语言]三种方法实现n的k次方(递归/调用math库函数/实现pow函数)[含递归图解说明]

目录 1.调用math库函数中的pow函数实现n的k次方 2.创造pow函数实现n的k次方 3.递归实现n的k次方&#xff08;含图解&#xff09; 1.调用math库函数中的pow函数实现n的k次方 pow函数的功能&#xff1a;计算n的k次幂 pow格式&#xff1a;pow(n,k) #include <stdio.h>#in…

@NotEmpty、@NotBlank、@NotNull 区别和使用

这种注解通常使用场景在前端发送过来的数据&#xff0c;先进行校验处理&#xff0c;在进行逻辑判断的&#xff0c;所以在进行校验处理的时候&#xff0c;我们通常会使用这三种注解来进行判断传过来的值 1NotNull 适用于基本数据类型(Integer&#xff0c;Long&#xff0c;Doubl…

回收租赁商城系统功能拆解01讲-产品架构

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

【谷粒商城基础篇】基础环境搭建

谷粒商城笔记合集 分布式基础篇分布式高级篇高可用集群篇简介&环境搭建项目简介与分布式概念&#xff08;第一、二章&#xff09;基础环境搭建&#xff08;第三章&#xff09;整合SpringCloud整合SpringCloud、SpringCloud alibaba&#xff08;第四、五章&#xff09;前端知…

关于yum源的总结

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录1 相关概念1.1 rpm与yum1.2 yum源与repo文件2 yum源的种类2.1 官方源2.…

【HTML】耗时一下午,整理出了一个精美的响应式登陆注册表单(附源码)

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

【OpenDDS开发指南V3.20】第八章:opendds_idl

opendds_idl是构建opendds和opendds应用程序过程中使用的代码生成器之一。 它可以用多种不同的方式定制如何从IDL文件生成源代码。 有关默认使用模式的概述,请参见第2.1.2节。 OpenDDS IDL编译器是使用位于$DDS_ROOT/bin/(PATH上)的OpenDDS_IDL可执行文件调用的。 它解析…

SpringBoot+RabbitMQ(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-messaging-rabbitmq.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建应用程序&#xff0c;S…

inventor(2):设置单位,显示完整工具区/功能区,创建分割面

好久没用inventor了&#xff0c;记录一些重新学习的基本操作 文章目录1. inventor设置单位为cm2. inventor显示完整工具区/功能区3. inventor创建分割面1. inventor设置单位为cm inventor默认单位为in(英尺)&#xff0c;国内常用习惯为cm 一次点击&#xff1a;工具–选项–文档…

这篇文章会让你熟悉文件的各种操作,让你对文件的认识更加深入【c语言】

文章目录为什么使用文件什么是文件文件名文件的打开和关闭文件指针文件的顺序读写fgetcfputcfgetsfprintffscanffwritefread对比一组函数sprintfsscanf文件的随机读写fseekftellrewind文本文件和二进制文件文件读取结束的判定文件缓冲区为什么使用文件 把数据存放在磁盘文件、存…

2022 SuperMap开发者大会全议程公布,16个专场快来pick

2022年10月12日-14日&#xff0c;2022 SuperMap开发者大会(2022 SuperMap Developer Conference,简称“SDC 2022”)将在线举办。3天时间&#xff0c;16场专题论坛&#xff0c;聚焦GIS前沿技术和热点应用领域开发&#xff0c;分享50场开发实战报告&#xff0c;面向不同应用场景&…

基于小程序语法的跨端开发平台大盘点

2022年12月18日&#xff0c;微信推出了“Donut”开发平台&#xff0c;目前已经开始限时免费公测。这款跨端开发平台与Flutter、React Native、Taro等跨端框架最大的不同是&#xff1a;跨端的能力是基于小程序原生语法进行转译。这背后不得不让人联想到此次开发平台的推出&#…

P1046 [NOIP2005 普及组] 陶陶摘苹果————C++

文章目录题目[NOIP2005 普及组] 陶陶摘苹果题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示解题思路Code运行结果题目 [NOIP2005 普及组] 陶陶摘苹果 题目描述 陶陶家的院子里有一棵苹果树&#xff0c;每到秋天树上就会结出 101010 个苹果。苹果成熟的时候&…

实验十一、多级放大电路的参数设置

一、题目 利用 Multism 为图1所示电路选择电路参数&#xff0c;使之正常工作&#xff0c;并测试 QQQ 点、电压放大倍数和输入电阻。 图1多级放大电路图1\,多级放大电路图1多级放大电路 二、仿真电路 在Multism环境下搭建图1所示电路&#xff0c;选择电路参数&#xff0c;如图…

【谷粒商城基础篇】商品服务开发:基础概念、三级分类

谷粒商城笔记合集 分布式基础篇分布式高级篇高可用集群篇简介&环境搭建项目简介与分布式概念&#xff08;第一、二章&#xff09;基础环境搭建&#xff08;第三章&#xff09;整合SpringCloud整合SpringCloud、SpringCloud alibaba&#xff08;第四、五章&#xff09;前端知…

再快一点?动态内容如何加速

未来已来&#xff0c;只是不均衡地分布在当下 大家好&#xff0c;我是菜农&#xff0c;欢迎来到我的频道。 近年来 Web 3 的概念在程序员的小圈子也几乎是人尽皆知了。功能再强&#xff0c;噱头再足&#xff0c;但是如果访问速度没有跟上&#xff0c;一起都是浮云。哪怕拿现在…

封装和解封装、跨层封装

封装和解封装 我们一般把数据从应用层开始到数据链路层的加工过程称为封装&#xff0c;反过程称为解封装 封装 — 将每一层最重要的数据添加到原始数据当中&#xff0c;来实现这一层的功能。 应用层 — 应用需要进行封装&#xff0c;但是&#xff0c;封装方式取决于不同的应用…

hiveSql 京东面试题-有效值问题

hiveSql 京东面试题-有效值问题需求准备数据分析实现最后需求 有入库成本表&#xff0c;一个商品每次入库就会产生一条数据&#xff0c;里面包含商品id&#xff0c;入库时间time&#xff0c;以及入库采购的成本。但由于某些某些原因&#xff0c;导致表中某些数据的成本是有丢失…