收款定制开发【node进阶】深度解析express框架---编写接口|解决跨域问题

✅ 作者简介:收款定制开发一名普通本科大三的学生,收款定制开发致力于提高前端开发能力
✨ 个人主页:
🔥 系列专栏 :
⭐️ 个人社区 :
🍀 学习格言: ☀️ 收款定制开发打不倒你的会使你更强!☀️


🔥前言

收款定制开发我们在做的时候,收款定制开发我们经常调用后端所给收款定制开发我们的接口,收款定制开发从而获取接口中的信息,收款定制开发这一篇文章将带领大家做收款定制开发自己的后端,收款定制开发给大家讲解怎么去运用node收款定制开发给自己写接口,收款定制开发同时帮助大家解决经常遇到的跨域问题

📃目录

学前先知:req.body | req.query | req.params

想要从web收款定制开发的后台中获取接口的数据,收款定制开发传参是必不可少的,收款定制开发后台想要接收前台传来收款定制开发的数据需要借助一些内置的方法:

req.body

在express框架中,用req.body接收post收款定制开发客户端的数据,收款定制开发该属性主要用于post()收款定制开发方法时传递参数使用,收款定制开发用法最广泛,收款定制开发在你想使用这个方法的收款定制开发时候必须要导入第三方中间件body-parser.

演示代码:

const express = require('express')const app = express()const body_parser = require('body-parser')app.use(body_parser.urlencoded({extended : false}))app.post('/user',(req,res)=>{    console.log(req.body);   //[Object: null prototype] { name: 'james', age: '37', gender: '男' }    res.send('ok')})app.listen(80,()=>{    console.log('http://127.0.0.1');})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里使用了postman测试工具,打印出来的req.body为前台传给后台的参数,后台告诉了前台接收到了参数,打印了ok


req.query

req.query用来获取get方法传递的参数,在这里就无需载入中间件了。

演示代码:

const express = require('express');const app = express();// 测试地址:http://127.0.0.1/user/?name=jamesapp.get('/user', function(req, res){   	let param = req.query.name;     	console.log(param) //james	res.send('ok');});app.listen(80,()=>{    console.log('http://127.0.0.1');})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在postman中测试地址为http://127.0.0.1?name=james,通过req.query取到了一个对象{name : 'james'},随后拿到name属性即可


req.params

有时候我们遇到的地址栏可能会是这种形式:http://127.0.0.1/user/1,这时候就需要我们的req.params去接收前台传来的参数

演示代码:

const express = require('express')const app = express()app.get('/user/:id', function(req, res){   	let param = req.params.id;  //1   	console.log(param)	res.send('ok');});app.listen(80,()=>{    console.log('http://127.0.0.1');})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在postman中自创地址http://127.0.0.1/user/1,通过req.query获取到一个对象{id:1},随后取出对象中的属性即可


使用express编写接口

  • 创建基本的服务器

    const express = require('express')//创建express实例const app = express()//在这里写下你的业务代码...//调用app.listen 方法,指定端口号并启动web服务器app.listen('80',()=>{    console.log('http://127.0.0.1');})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 创建api路由模块

    const express = require('express')const apiRouter = express.Router()//在这里写下你所创建的路由...//将apiRouter导出为一个模块module.exports = apiRouter
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 将模块导入创建基本服务的文件中

    const express = require('express')const app = express()const apiRouter = require('./16.apiRouter')app.use('/api',apiRouter)app.listen('80',()=>{    console.log('http://127.0.0.1');})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 编写get接口

    apiRouter.get('/get',(req,res)=>{    // 通过 req.query 获取客户端通过查询字符串,发送到服务器的数据    const query = req.query    // 调用 res.send() 方法,向客户端响应处理的结果    res.send({        status : 0, // 0 表示处理成功,1 表示处理失败        msg : 'GET请求成功!',  // 状态的描述        data : query // 需要响应给客户端的数据    })})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 编写post接口

    apiRouter.post('/post',(req,res)=>{    // 通过 req.body 获取请求体中包含的 url-encoded 格式的数据    const body = req.body    // 调用 res.send() 方法,向客户端响应结果    res.send({        status : 0,         msg : 'post请求成功!',        data : body    })})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意:如果要获取 URL-encoded 格式的请求体数据,须配置中间件:app.use(express.urlencoded({ extended: false }))

  • 编写delete接口

    // 定义 DELETE 接口apiRouter.delete('/delete', (req, res) => {    res.send({      status: 0,      msg: 'DELETE请求成功',    })  })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

什么是跨域

我们刚才编写的接口,存在一个很严重的问题:不支持跨域请求。那么什么是跨域(CORS)呢?
当一个请求url的协议域名端口号三者之间任意一个与当前页面url不同即为跨域.
举个例子:我当前的url为:http://127.0.0.1/user,但是我想访问url为https://127.0.0.1/admin中的数据,我能访问的到吗?显然是不可能的,这就产生了跨域问题!

为什么会产生跨域问题

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互
所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)


的两种方案

1. CORS 解决跨域

什么是 CORS

CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源
浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制。

上图中,如果我们网页对服务器发送了跨域请求,服务器受到请求后返回书记,但是在返回的时候,浏览器的同源策略安全机制拦截了响应的数据,这就导致了跨域。

上图中,使用cors后,配置了响应头Access-Control-Allow-*,这样的话解除了浏览器对响应的拦截,也就是解除了跨域。

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


使用 cors 中间件解决跨域问题

cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。
使用步骤分为如下 3 步:

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

代码示例:

const express = require('express')const app = express()app.use(express.urlencoded({extended : false}))//一定要在路由之前,配置cors 这个中间件,从而解决接口跨域问题const cors = require('cors')app.use(cors())//将上方的apiRouter模块导入进来const apiRouter = require('./16.apiRouter')//访问加上前缀app.use('/api',apiRouter)app.listen('80',()=>{    console.log('http://127.0.0.1');})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

cors的三个响应头

Access-Control-Allow-Origin

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

Access-Control-Allow-Origin : <origin> | *
  • 1

其中,origin 参数的值指定了允许访问该资源的外域 URL
如果指定了 Access-Control-Allow-Origin 字段的值为通配符 *,表示允许来自任何域的请求。
例如,下面的两个字段值将分别允许来自 http://127.0.0.1/user任何url的请求:

//该设置允许来自`http://127.0.0.1/user`的请求res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1/user')//该设置允许所有的url的请求res.setHeader('Access-Control-Allow-Origin','*')
  • 1
  • 2
  • 3
  • 4
  • 5

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')
  • 1

该设置的目的是:允许客户端额外向服务器发送 Content-Type 请求头和X-Custom-Header 请求头
注意:多个请求头之间使用英文逗号隔开进行分割。


Access-Control-Allow-Methods

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

示例代码如下:

//只允许 POST、GET、DELETE、HEAD 请求方法res.setHeader('Access-Control-Allow-Methods','POST','GET','DELETE','HEAD')//允许所有的HTTP请求方法res.setHeader('Access-Control-Allow-Methods','*')
  • 1
  • 2
  • 3
  • 4

CORS请求的分类

客户端在请求 CORS 接口时,根据请求方式请求头的不同,可以将 CORS 的请求分为两大类,分别是:简单请求预检请求

简单请求

同时满足以下两大条件的请求,就属于简单请求:

  1. 请求方式:GET、POST、HEAD 三者之一
  2. 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)

预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求:

  1. 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  2. 请求头中包含自定义头部字段
  3. 向服务器发送了 application/json 格式的数据

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

简单请求与预检请求的区别

简单请求的特点:客户端与服务器之间只会发生一次请求

预检请求的特点:客户端与服务器之间会发生两次请求OPTION 预检请求成功之后,才会发起真正的请求


2. jsonp解决跨域

jsonp的概念

浏览器端通过 <script> 标签的 src (让src)属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP。

注意:

  1. JSONP 不属于真正的 Ajax 请求,因为它没有使用 XMLHttpRequest 这个对象。
  2. JSONP 仅支持 GET 请求(重点!!!),不支持 POST、PUT、DELETE 等请求。
  3. JSONP 需要前后端共同协调

jsonp的原理

动态创建script标签,src属性指向没有跨域限制(重点!!!),指向一个接口,接口返回的格式一定是 ****() 函数表达式


创建 JSONP 接口的注意事项

如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突,必须在配置 CORS 中间件之前声明 JSONP 的接口。否则 JSONP 接口会被处理成开启了 CORS 的接口。示例代码如下:

// 必须在配置 cors 中间件之前,配置 JSONP 的接口【这个接口不会被处理成cors接口】app.get('/api/jsonp', (req, res) => {...})//一定要在路由之前,配置cors 这个中间件,从而解决接口跨域问题【后续的所有接口,都会被处理为 cors接口】const cors = require('cors')app.use(cors())//在这里开启了一个 cors 的接口app.get('api/get',(req,res)=>{...})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

实现jsonp接口的步骤

  1. 获取客户端发送过来的回调函数的名字
  2. 得到要通过 JSONP 形式发送给客户端的数据
  3. 根据前两步得到的数据,拼接出一个函数调用的字符串
  4. 把上一步拼接得到的字符串,响应给客户端的<script>标签进行解析执行

具体代码如下:

app.get('/api/jsonp', (req, res) => {    // TODO: 定义 JSONP 接口具体的实现过程    // 1. 得到函数的名称    const funcName = req.query.callback        // 2. 定义要发送到客户端的数据对象    const data = { name: 'zs', age: 22 ,req:req.query}    // 3. 拼接出一个函数的调用    const scriptStr = `${funcName}(${JSON.stringify(data)})`        // 4. 把拼接的字符串,响应给客户端    res.send(scriptStr)  })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

随后在网页中发送jsonp请求即可,这里用的是$.ajax():

<button id="btnJSONP">JSONP</button>
  • 1
$('#btnJSONP').on('click', function () {  $.ajax({    type: 'GET',    url: 'http://127.0.0.1/api/jsonp',    dataType: 'jsonp',    success: function (res) {      console.log(res)  //{ name: 'zs', age: 20 }    },  })})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

小结

本篇的内容主要就是针对express的接口编写和解决跨域的,接口的编写非常的容易上手,现阶段并没有到数据库衔接,等后续文章更新数据库之后,就可以真正做一个全栈开发者了,前端中,跨域的问题必须要会,这里提供了最常用的cors解决跨域,jsonp在实际开发中使用较少,还有一种反向代理的方式,如果有机会更新vue的时候会详细讲解反向代理,好了,少年,继续加油吧!😀😀


👑书写不易,希望大家能够给予三连支持,期待我更好的文章哟👑

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发