首页 > 编程语言 >【nodejs基础】Expres编写接口详解05

【nodejs基础】Expres编写接口详解05

时间:2023-05-13 23:11:49浏览次数:36  
标签:const 请求 05 res nodejs 接口 Expres GET 客户端

一、使用 Express 写接口

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

接口的跨域问题
刚才编写的 GET 和 POST接口,存在一个很严重的问题:不支持跨域请求,解决接口跨域问题的方案主要有两种

CORS(主流解决方案,推荐)
JSONP(有缺陷:只支持 GET 请求) 

使用 CORS 中间件解决跨域问题
CORS(Cross-Origin Resource Sharing,跨域资源共享)是 Express 的一个第三方中间件,由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源。可以很方便地解决跨域问题。使用步骤分为如下 3 步

运行 npm install cors 安装中间件
使用 const cors = require(‘cors’) 导入中间件
在路由之前调用 app.use(cors()) 配置中间件

注意点:

CORS 在服务器端进行配置,客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
CORS 在浏览器中有兼容性,只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(如:IE10+、Chrome4+、FireFox3.5+)
响应头:

响应头部可以携带一个Access-Control-Allow-Origin字段,语法如下:

**Access-Control-Allow-Origin: 或 ***
Origin指定了允许访问该资源的外域 URL,可以控制哪些网页可以请求该服务器,而*表示所有网页均可

res.setHeader('Access-Control-Allow-Origin', 'http....')

Access-Control-Allow-Headers :
默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头

Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded)

如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 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-Alow-Methods来指明实际请求所允许使用的 HTTP 方法

res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE')

res.setHeader('Access-Control-Allow-Methods', '*') // 支持所有请求

 

CROS请求分类
客户端在请求 CORS 接口时,根据请求方式和请求头的不同,可以将 CORS 的请求分为两大类:

简单请求

同时满足以下两大条件的请求,就属于简单请求
请求方式:GET、POST、HEAD 三者之一
HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求
ⅰ请求方式为 GET、POST、HEAD 之外的请求 Method 类型
ⅱ请求头中包含自定义头部字段
ⅲ向服务器发送了 application/json 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,这一次的 OPTION 请求称为预检请求。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。
简单请求的特点:客户端与服务器之间只会发生一次请求
预检请求的特点:客户端与服务器之间会发生两次请求,OPTION 预检请求成功之后,才会发起真正的请求

// apiRouter.js

const express = require('express')
const router = express.Router()

// GET 接口
router.get('/get', (req, res) => {
// 通过 req.query 获取客户端发送到服务器的数据
const query = req.query
res.send({
status: 0, // 0 表示处理成功,1 表示处理失败
msg: 'GET 请求成功!', // 状态的描述
data: query, // 需要响应给客户端的数据
})
})

// POST 接口
router.post('/post', (req, res) => {
// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据
// 意在路由模块之前配置中间件url-encoded
const body = req.body
res.send({
status: 0,
msg: 'POST 请求成功!',
data: body,
})
})

// DELETE 接口
router.delete('/delete', (req, res) => {
res.send({
status: 0,
msg: 'DELETE请求成功',
})
})

module.exports = router

 

JSONP 接口(有缺陷只支持GET)
概念:浏览器端通过
实现 JSONP 接口的步骤:

获取客户端发送过来的回调函数的名字
得到要通过 JSONP 形式发送给客户端的数据
根据前两步得到的数据,拼接出一个函数调用的字符串
把上一步拼接得到的字符串,响应给客户端的

const express = require('express')

const app = express()

// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get('/api/jsonp', (req, res) => {
// 定义 JSONP 接口具体的实现过程
const funcName = req.query.callback // 1. 得到函数的名称
const data = { name: 'zs', age: 22 } // 2. 定义要发送到客户端的数据对象
const scriptStr = `${funcName}(${JSON.stringify(data)})` // 3. 拼接出一个函数的调用
res.send(scriptStr) // 4. 把拼接的字符串,响应给客户端
})

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())

// 导入路由模块
const router = require('./16.apiRouter')
// 把路由模块,注册到 app 上
app.use('/api', router)

app.listen(80, () => {console.log('express server running at http://127.0.0.1')})


测试模块:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://cdn.staticfile.org/jquery/3.4.1/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/api/get',
data: { name: 'cess', age: 18 },
success: function (res) {
console.log(res)
},
})
})
// 2. 测试POST接口
$('#btnPOST').on('click', function () {
$.ajax({
type: 'POST',
url: 'http://127.0.0.1/api/post',
data: { bookname: '开端', author: '祈祷君' },
success: function (res) {
console.log(res)
},
})
})

// 3. 为删除按钮绑定点击事件处理函数
$('#btnDelete').on('click', function () {
$.ajax({
type: 'DELETE',
url: 'http://127.0.0.1/api/delete',
success: function (res) {
console.log(res)
},
})
})

// 4. 为 JSONP 按钮绑定点击事件处理函数
$('#btnJSONP').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/jsonp',
dataType: 'jsonp',
success: function (res) {
console.log(res)
},
})
})
})
</script>
</body>
</html>

标签:const,请求,05,res,nodejs,接口,Expres,GET,客户端
From: https://www.cnblogs.com/xfbk/p/17398474.html

相关文章

  • 【愚公系列】2023年05月 .NET CORE工具案例-Workflow-Core轻量级工作流引擎(随机流程)
    (文章目录)前言1.什么是工作流工作流是OA系统比较重要的功能之一,主要在于企业流程协同审批,有效进行流程管理。流程管理起源于生产组织和办公自动化领域,是针对日常工作中具有固定程序的活动提出的一个概念。目的是通过将工作分解成定义良好的任务、角色,按照一定的规则和过程来......
  • 2023-05 多校联合训练 ZJNU站 热身赛
    猫猫接币币给定两个容量分别为a和b的盒子,已知第i秒天上会掉下i个金币,你会从第1秒开始接金币,每秒钟你可以选择任意一个盒子接金币,但是不能不选,你必须使得两个盒子刚好装满,请问是否存在某个时刻,使得恰好装满两个盒子,输出一个仅由A和B组成的字符串,第\(i\)位的字符即表示第\(i\)......
  • 每日总结2023-05-13
    今天对多线程进行探索: 使用步骤:具体使用: //步骤1:创建线程类(继承自Thread类)classMyThreadextendsThread{//步骤2:复写run(),内容=定义线程行为@Overridepublicvoidrun(){...//定义的线程行为}}//步骤3:创建线程对象,即......
  • MPU6050一些问题与解决方案
    第一次参加电赛,调mpu6050调得想死,记录一些问题等待日后查询。 一.输出一直是0.可能1:没有初始化成功,见二。可能2:输出时用的是整型格式而不是浮点数格式。。。可能3:AD0引脚接了高电平(或者低电平),就是地址不对。二.初始化不能成功。我是和......
  • Hugging News #0512:
    每一周,我们的同事都会向社区的成员们发布一些关于HuggingFace相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「HuggingNews」,本期HuggingNews有哪些有趣的消息,快来看看吧!开源更新Transformers现已支持Meta的S......
  • 2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你
    2023-05-12:存在一个由n个节点组成的无向连通图,图中的节点按从0到n-1编号,给你一个数组graph表示这个图,其中,graph[i]是一个列表,由所有与节点i直接相连的节点组成。返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重......
  • 每日总结2023-05-12
    今天完成了dialog的简易模式:privatevoidshowQieDialog(){AlertDialog.Builderbuilder=newAlertDialog.Builder(this);builder.setTitle("切换账号提示").setMessage("请确认切换账号").setPositiveButton("......
  • 20223.05.12 - 可选链操作符的Ployfill
    可选链操作符是ES2020的新特性,如果要在webpack版本低于5.20的vue2项目中使用它,需要对babel进行配置。首先,需要安装@babel/plugin-proposal-optional-chaining插件:npminstall--save-dev@babel/plugin-proposal-optional-chaining然后,在.babelrc或babel.config.js文件......
  • 230512 // 数论
    夺,夺少?哦,85pts,小让一手。A.征兵http://222.180.160.110:1024/contest/3574/problem/1GM说,怕久了不打最小生成树我们给忘了。笑话,就算退役十年我也不一定能忘了Kruskal,就算在役十年我也不一定能记住Prim。就一板板题,没什么好说的。#defineintlonglongnamespaceXSC......
  • 基于Expression Lambda表达式树的通用复杂动态查询构楗器——《摘要篇》
    基于表达式树的通用查询构造器常见的使用LinqExpression的做法这种代码众多,随便一搜就是, 但几乎都是单个条件的,单层级的,只能简单组装,组装成如:Field_A=1andField_B=2OrField_C=3--或者Field_A=1and(Field_B=2OrField_C=3) 是否可以灵活的查询条件组合&独立......