Express学习(四)

使用Express写接口

创建基本的服务器

创建API路由模块

编写GET接口


编写POST接口

CORS跨域资源共享

  • 什么是CORS
    CORS由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。浏览器的同源安全策略默认会阻止网页"跨域"获取资源。但如果接口服务器配置了CORS相关的HTTP响应头 ,就可以解除浏览器前端的跨域访问限制。
  • 新建一个test.html文件,在文件内输入!,点击!即可快速初始化html文件
  • 使用cors中间件解决跨域问题
  • 使用步骤如下
    • 运行npm install cors安装中间件
    • 使用const cors = require('cors')导入中间件
    • 在路由之前调用app.use(cors())配置中间件
  • 代码如下
  • API.js
javascript 复制代码
//路由模块
const express = require('express')
const router = express.Router()

router.get('/get', (req, res) => {
  //获取到客户端通过查询字符串发送到服务器的数据
  const query = req.query
  //调用res.send()方法把数据响应给客户端
  res.send({
    status: 0,  //状态0表示成功,1表示失败
    msg: 'GET请求成功!',  //状态描述
    data: query    //需要响应给客户端的具体数据
  })
})

router.post('/post', (req, res) => {
  //获取客户端通过请求体发送到服务器的 URL-encoded数据
  //如果要获取URL-encoded格式的请求体数据,必须配置中间件app.use(express.urlencoded({ extended: false}))
  const body = req.body
  //调用res.send()方法把数据响应给客户端
  res.send({
    status: 0,    //状态0表示成功,1表示失败
    msg: 'POST请求成功!',  //状态描述消息
    data: body    //需要响应给客户端的具体数据
  })
})

module.exports = router
  • test.js
javascript 复制代码
//导入express模块
const express = require('express')

//创建express服务器实例
const app = express()

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

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

//导入并注册路由模块
const router = require('./API')
app.use('/api', router)




//调用app.listen方法指定端口号并启动服务器
app.listen(80, () => {
  console.log('Express server running at http://127.0.0.1')
})
  • test.html
html 复制代码
<!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.net/jquery/3.7.1/jquery.min.js"></script>
</head>

<body>

  <!--输入以下内容-->
  <button id="btnGET">GET</button>
  <button id="btnPOST">POST</button>


  <script>
    //测试GET接口
    $('#btnGET').on('click', function () {
      $.ajax({
        type: 'GET',
        url: 'http://127.0.0.1/api/get',
        data: { name: 'zs', age: 20 },
        success: function (res) {
          console.log(res)
        },
      })
    })
    //测试POST接口
    $('#btnPOST').on('click', function () {
      $.ajax({
        type: 'POST',
        url: 'http://127.0.0.1/api/get',
        data: { bookname: '区块链', author: 'thq' },
        success: function (res) {
          console.log(res)
        },
      })
    })
  </script>

</body>

</html>
  • 终端运行test.js文件

  • 然后在网页中打开html文件

  • 点击GET和POST按钮

  • 注意事项

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

CORS响应头部

  • Access-Control-Allow-Origin
    响应头部可以携带一个Access-Control-Allow-Origin字段,如下,下面的字段值将只允许来自http://itcast.cn的请求
javascript 复制代码
res.setHeader('Access-Control-Allow-Origin', 'http://itcast.cn')

下面的字段表示允许来自任何域的请求

javascript 复制代码
res.setHeader('Access-Control-Allow-Origin', '*')
  • Access-Control-Allow-Headers
    默认情况下,CORS仅支持客户端向服务器发送如下的9个请求头:
    Accept、Accept-Language、 Content-Language、 DPR、DownlinkSave-Data Viewport-Width, Width Content-Type (值仅限于 text/plain、 multipart/form-data、application/x-www-form-urlencoded 三者之一)
    如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过Access-Control-Allow-Headers对额外的请求头进行声明,否则请求失败。例如如下允许使用Conten-Type和X-Custom-Header请求头
javascript 复制代码
res.setHeader('Access-Control-Allow-Headers', 'Conten-Type, X-Custom-Header')
  • Access-Control-Allow-Methods
    默认情况下,CORS仅支持客户端发起GET、POST、HEAD请求。
    如果客户端希望通过PUT、DELETE等方式请求服务器的资源,则需要在服务器通过Access-Control-Allow-Methods来指明实际请求所允许使用的HTTP方法。如下,
javascript 复制代码
//只允许POST、GET、DELETE、HEAD请求方法
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
//允许所有的HTTP请求方法
res.setHeader('Access-Control-Allow-Methods', '*')

CORS请求的分类

  • 简单请求
    • 请求方式:GET、POST、HEAD三者之一
    • HTTP 头部信息不超过以下几种字段: 无自定义头部字段、Accept、Accept-LanguageContent-Language、DPR.Downlink、Save-Data、 Viewport-Width、 Width 、Content-Type (只有三个值application/x-www-formurlencoded、multipart/form-data、text/plain)。
  • 预检请求
    在浏览器与服务器正式通信之前,浏览器会发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为预检请求。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。
    • 请求方式:GET、POST、HEAD之外的请求Method类型
    • 请求头中包含自定义头部字段
    • 向服务器发送了application/json格式的数据。
  • 简单请求和预检请求的区别
    • 简单请求的特点:客户端与服务器之间只会发生一次请求
    • 预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后才会发起真正的请求。

示例

  • 修改之前的test.html代码如下
html 复制代码
<!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.net/jquery/3.7.1/jquery.min.js"></script>
</head>

<body>

  <!--输入以下内容-->
  <button id="btnGET">GET</button>
  <button id="btnPOST">POST</button>
  <!--添加一个新的按钮-->
  <button id="btnDelete">DELETE</button>


  <script>
    $(function () {
      //测试GET接口
      $('#btnGET').on('click', function () {
        $.ajax({
          type: 'GET',
          url: 'http://127.0.0.1/api/get',
          data: { name: 'zs', age: 20 },
          success: function (res) {
            console.log(res)
          },
        })
      })
      //测试POST接口
      $('#btnPOST').on('click', function () {
        $.ajax({
          type: 'POST',
          url: 'http://127.0.0.1/api/post',
          data: { bookname: '区块链', author: 'thq' },
          success: function (res) {
            console.log(res)
          },
        })
      })

      //为删除按钮绑定点击事件处理函数
      $('#btnDelete').on('click', function () {
        $.ajax({
          type: 'DELETE',
          url: 'http://127.0.0.1/api/delete',
          data: { bookname: '区块链', author: 'thq' },
          success: function (res) {
            console.log(res)
          },
        })
      })
    })
  </script>

</body>

</html>
  • 然后在API.js文件中添加代码
javascript 复制代码
//路由模块
const express = require('express')
const router = express.Router()

router.get('/get', (req, res) => {
  //获取到客户端通过查询字符串发送到服务器的数据
  const query = req.query
  //调用res.send()方法把数据响应给客户端
  res.send({
    status: 0,  //状态0表示成功,1表示失败
    msg: 'GET请求成功!',  //状态描述
    data: query    //需要响应给客户端的具体数据
  })
})

router.post('/post', (req, res) => {
  //获取客户端通过请求体发送到服务器的 URL-encoded数据
  //如果要获取URL-encoded格式的请求体数据,必须配置中间件app.use(express.urlencoded({ extended: false}))
  const body = req.body
  //调用res.send()方法把数据响应给客户端
  res.send({
    status: 0,    //状态0表示成功,1表示失败
    msg: 'POST请求成功!',  //状态描述消息
    data: body    //需要响应给客户端的具体数据
  })
})

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

module.exports = router

然后我们运行test.js文件启动服务器,然后打开网页,点击DELETE按钮即可看到出现了两次请求

JSONP接口

  • 概念
    浏览器通过 < script >标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP。
  • 特点
    • JSONP不属于真正的Ajax请求,因为它没有使用XMLHttpRequest这个对象。
    • JSONP仅支持GET请求,不支持POST、PUT、DELETE等请求。
  • 创建JSONP接口的注意事项
    如果项目中已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP的接口,否则JSONP接口会被处理成开启了CORS的接口,示例代码如下
javascript 复制代码
//优先创建JSONP接口,这个接口不会被处理成CORS接口
app.get('/api/jsonp', (req, res) => { })

//再配置CORS中间件,后续的所有接口都会被处理成CORS接口
app.use(cors())

//这是一个开启了CORS的接口
app.get('/api/get', (req, res) => { })
  • 实现JSONP接口的步骤
    • 获取客户端发送过来的回调函数的名字
    • 得到要通过JSONP形式发送给客户端的数据
    • 根据前两步得到的数据,拼接出一个函数调用的字符串
    • 把上一步拼接得到的字符串,响应给客户端的
javascript 复制代码
app.get('/api/jsonp', (req, res) => {
//获取客户端发送过来的回调函数的名字
const funcName = req.query.callback
//得到要通过JSONP形式发送给客户端的数据
const data = { name: 'zs', age: 22 }
//根据前两步得到的数据,拼接出一个函数调用的字符串
const scriptStr = `${funcName}(${JSON.stringify(data)})`
//把上一步拼接得到的字符串,响应给客户端的<script>标签进行解析执行
res.send(scriptStr)
})
  • 示例
    在之前的test.js文件中添加代码后如下
javascript 复制代码
//导入express模块
const express = require('express')

//创建express服务器实例
const app = express()

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

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

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

//导入并注册路由模块
const router = require('./API')
app.use('/api', router)




//调用app.listen方法指定端口号并启动服务器
app.listen(80, () => {
  console.log('Express server running at http://127.0.0.1')
})
  • 使用jQuery发起JSONP请求
    调用$.ajax()函数,提供JSONP的配置选项,从而发起JSONP请求。
    在test.html文件中添加代码后如下
html 复制代码
<!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.net/jquery/3.7.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">DELETE</button>


  <script>
    $(function () {
      //测试GET接口
      $('#btnGET').on('click', function () {
        $.ajax({
          type: 'GET',
          url: 'http://127.0.0.1/api/get',
          data: { name: 'zs', age: 20 },
          success: function (res) {
            console.log(res)
          },
        })
      })
      //测试POST接口
      $('#btnPOST').on('click', function () {
        $.ajax({
          type: 'POST',
          url: 'http://127.0.0.1/api/post',
          data: { bookname: '区块链', author: 'thq' },
          success: function (res) {
            console.log(res)
          },
        })
      })

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

      //为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>
  • 然后打开网页,点击JSONP
相关推荐
西岸行者9 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意9 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码9 天前
嵌入式学习路线
学习
毛小茛9 天前
计算机系统概论——校验码
学习
babe小鑫9 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms9 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下9 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。9 天前
2026.2.25监控学习
学习
im_AMBER9 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J9 天前
从“Hello World“ 开始 C++
c语言·c++·学习