跨域[2]--jsonp、webpack、koa2-cors解决跨域 |8月更文挑战

437 阅读2分钟

跨域--jsonp、webpack、koa2-cors解决跨域

书接上一章:跨域--通过代码一步一步了解其本质 。上一章我们简单在本地搭建了前后端分离项目,从代码的层面的理解跨域。这一章是我们的实践篇,完整代码在我的git上,阅读readme获取正确姿势。本章内容如下:

  • jsonp原理分析
  • koa项目引入koa-cors解决跨域问题
  • webpack项目开发时候解决问题

jsonp

jsonp主要目的是让网页从其他域名获取数据,就是跨域资源获取。其主要是利用script不适用同源策略,通过src能够请求其他域名的数据。

代码实现

客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script type="text/javascript">
    function callback(result) {
      console.log(result)
    }
  </script>
  <script type="text/javascript" src="http://127.0.0.1:3000/jsonp?callback=callback">
  </script>
</body>
</html>

服务端代码

router.get('/jsonp', async (ctx) => {
  // 获取回调函数名字
  let callbackName = ctx.query.callback || 'callback'
  // 返回数据定义
  let returnData = {
    success: true,
    data: {
      text: 'this is a jsonp api',
      time: new Date().getTime(),
    }
  }
  // 返回js代码(即:执行回到函数)
  let jsonpStr = `${callbackName}(${JSON.stringify(returnData)})`
  // 设置Content-Type
  ctx.type = 'text/javascript'
  ctx.body = jsonpStr
})

image

原理分析

image

  1. 客户端第一个script定义回调函数
  2. 第二个script发送请求,带上回调函数名字
  3. 服务端拼装执行回调的js代码
  4. 客户端获取到后台的js代码并执行
  5. 获取到数据

ps:jsonp只使用与get请求

koa-cors

通常跨域是由后端处理。每种语言都要相应的第三方包,进行处理。对于koa2项目引入koa2-cors即可解决问题

// 解决跨域问题
app.use(cors({
    exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
    maxAge: 5,
    // 允许接收cookie
    credentials: true,
    allowMethods: ['GET', 'POST', 'DELETE', 'PUT'],
    allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))

webpack-dev proxy 配置解决跨域

此种方式只使用与开发模式,在webpack.config.js或者vue-config.js中配置如下

devServer: {
    // 启用热更新
    hot: true,
    port: 3000,
    contentBase: path.resolve(__dirname, '../dist'),
    compress: true,
    // 代理配置
    proxy: {
        '/api': {
            target: 'http://10.10.0.135:8899',
            changeOrigin : true, // 域名
            secure: false, // 是否支持https
            pathRewrite: {'^/api': ''} // 重写url
        },
    }
}

注意理解路径重写(pathRewrite)

  1. 以上诉代码为例。在没有路径重写的情况之下:/api/xx 代理为 http://127.0.0.1:3000/api/xx

  2. 在有路径重写的情况下:/api/xx 代理为 http://127.0.0.1:3000/xx