2022年了,不会还不会解决跨域吧?

298 阅读2分钟

跨域

跨域问题是我们前端开发中经常会遇到的问题,希望通过这篇博客,小伙伴们就能解决这类问题啦

素材准备以及错误演示

根目录
├── public
│ ├── js
└── axios.js
│   └── index.html # 提前准备好的页面
└── server.js

前端页面

public/index.html

    <!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <p>
    <button id="btn1_get">接口测试1:get请求带参数</button>
  </p>
  <p>
    <button id="btn2_post"> 接口测试2:post-传递普通键值对</button>
  </p>
  <p>
    <button id="btn3_postJSON">接口测试3:post-传递json</button>
  </p>
  <form id="myform">
    <input type="text" name="title">
    <input type="file" name="cover">
  </form>
  <button id="btn4_formdata">接口测试4:post-传递formdata</button>

  <script src="./js/axios.js"></script>
  <script>
    document.getElementById('btn1_get').addEventListener('click', () => {
      axios.get('http://localhost:3000/getapi', { params: { a: 1, b: 2 } })
    })
    var obj = {
      "name": "abc",
      "address": {
        "a": 1,
        "b": 2,
        "info": "c"
      }
    }
    // axios库发送 普通键值对的参数
    document.getElementById('btn2_post').addEventListener('click', () => {
      const params = new URLSearchParams();
      // 属性名,属性值
      params.append('param1', 'value1');
      params.append('param2', 'value2');
      axios.post('http://localhost:3000/post', params, {
        headers: { "content-type": "application/x-www-form-urlencoded" }
      })
    })

    document.getElementById('btn3_postJSON').addEventListener('click', () => {
      axios.post('http://localhost:3000/postJSON', obj)
    })

    document.getElementById('btn4_formdata').addEventListener('click', () => {
      console.log(1)
      var fd = new FormData(document.getElementById('myform'));

      axios.post('http://localhost:3000/publish',
        fd
      )
    })
  </script>
</body>

</html>

后端代码

// 1. 引入包
const multer = require('multer')

// 2. 配置
const upload = multer({ dest: 'uploads/' }) // 上传的文件会保存在这个目录下
// uploads表示一个目录名,你也可以设置成其它的

//1.导入模块
const express = require('express')
//2.创建服务器
let app = express()

//静态资源托管
app.use(express.static('public'))

//键值对的中间键
app.use(express.urlencoded())
app.use(express.json())

//接口1 get
app.get('/getapi', (req, res) => {
  console.log('收到的参数是', req.query)
  res.send({ message: 'ok' })
})

//接口2 post
app.post('/post', (req, res) => {
  console.log('收到的参数是', req.body)
  res.send({ message: 'ok' })
})

//接口3 postJSON
app.post('/postJSON', (req, res) => {
  console.log('收到的参数是', req.body)
  res.send({ message: 'ok' })
})

//接口4 上传文件
app.post('/publish', upload.single('cover'), (req, res) => {
  console.log('收到的参数是', req.body)
  res.send({ message: 'ok' })
})

//3.开启服务器
app.listen(3000, () => {
  console.log('success')
})

此时如果用localhost打开的话,接口都正常使用,但是如果我们使用鼠标双击index.html页面然后测试接口的话,系统就会直接报错,就有了跨域问题 错误提示如下 :

001.png

如何解决跨域问题

一、CORS

CORS是一个W3C标准,全程是"跨域资源共享"(Cross-origin resource sharing).它允许浏览器想跨院服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制.
CORS需要浏览器和服务器同时支持.目前,所有浏览器都支持该功能.IE浏览器不能低于IE10(ie8通过XDomainRequest能支持CORS)。

手写实现

通过在被请求的路由中设置header头,可以实现跨域

//接口 get
app.get('/getapi', (req, res) => {
   //表示允许任何域名来访问
   res.setHeader('Access-Control-Allow-Origin','*')
  res.send({ message: 'ok' })
})

使用cors

  1. 它是一个npm包,要单独下载使用npm包cros
    npm i cros
  2. 当做express中的中间键,注意代码应该放在顶部
    var cors = require('cors')
    app.use(cors())