egg框架使用(2)跨域配置

622 阅读3分钟

CORS配置

egg框架提供了 egg-cors 插件来实现CORS跨域请求,先配置插件,配置完毕后就可以使用了。前端使用的axios框架会将请求的数据处理这样请求的字符串数据会处理为对象,后端的egg框架在发送数据前也会将数据从对象处理为字符串才发送。

插件配置步骤:

//1.下载
npm i egg-cors

//2.开启插件,就是把插件引入到项目中
// config/plugin.js文件
  cors:{
    enable: true,
    package: 'egg-cors',
  }
//3.配置插件的功能,配置插件的功能必须写在声明的config对象下方,是const声明的在声明前操作会报错  
// config/config.default.js文件
  config.cors = {
      //允许跨域的网址,*表示所有网址都可以跨域请求文件资源,也可以指定域名
        origin: '*',
        allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
  }
    
//默认origin只支持一个域名或者*表示全部,如果想支持具体的多个指定域名可以如下设置:
    config.cors = {
        // origin: ['http://localhost'],
        origin:function(ctx) { //设置允许来自指定域名请求
            console.log(ctx);
            const whiteList = ['http://www.baidu.com','http://www.hqyj.com']; 
            let url = ctx.request.header.origin;
            if(whiteList.includes(url)){
                return url;
            }
            return 'http://localhost' //默认允许本地请求可跨域
        },
        allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
    };

使用插件进行跨域请求

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.get("/aotu",controller.home.aotu);
  //*星号路由,表示客户端随便输入什么pathname的网址都会执行controller文件夹下得home.js文件中得all函数
  router.get("/*",controller.home.all);
};
'use strict';

const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'hi, egg';
  }
  async aotu() {
    this.ctx.body = 'anything is possible,你try try';
  }
  async all() {
    this.ctx.body = 'hi,卤蛋';
  }
}

module.exports = HomeController;
<body>
    <button onclick="fn()">跨域请求数据</button>
    <!-- 引入axios框架,做AJAX请求 -->
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.js" type="application/javascript"></script>
    <script>
        function fn(){
            axios("http://192.168.0.109:7001/aotu")
            .then((resquest)=>{
                console.log(resquest);
            });
        };
    </script>
</body>

image.png

JSONP配置

实现jsonp接口步骤

方式1:在配置文件中统一配置

//如果前端的URL中query参数中有cb=函数名参数(jsonp接口参数),将会返回JSONP格式的数据,否则返回JSON格式的数据。

//1.配置:
// config/config.default.js文件
config.jsonp = {
  callback: 'cb', // 识别 query 中的 `cb` 参数
  limit: 100, // 函数名最长为 100 个字符
};

//2.写接口
app/router.js
module.exports = app => {
  const jsonp = app.jsonp();
  app.router.get('/api/posts', jsonp, app.controller.posts.list);
};

方式2:在路由文件中配置,直接在jsonp方法中直接配置,

/// app/router.js文件
module.exports = app => {
  const jsonp = app.jsonp({
  callback: 'cb',
  limit: 100,
});
  app.router.get('/api/posts', jsonp, app.controller.posts.list);
};

使用方法

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  //形参解构赋值,形参app是一个对象,有router, controller这些成员
  const { router, controller} = app;
  router.get('/', controller.home.index);
  router.get("/aotu",controller.home.aotu);
  router.get("/data",app.jsonp({
    callback:"cb"
  }),controller.home.data);
  //*星号路由,表示客户端随便输入什么pathname的网址都会执行controller文件夹下得home.js文件中得all函数
  router.get("/*",controller.home.all);
};

'use strict';

const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'hi, egg';
  }
  async aotu() {
    this.ctx.body = 'anything is possible,你try try';
  }
  async all() {
    this.ctx.body = 'hi,卤蛋';
  }
  async data() {
    this.ctx.body = {info:"我是jsonp接口",code:666};
  }
}

module.exports = HomeController;
<body>
    <button onclick="fn()">跨域请求数据</button>
    <button id="btn" onclick="fg()">跨域请求jsonp数据</button>
    <!-- 引入axios框架,做AJAX请求 -->
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.js" type="application/javascript"></script>
    <script>
        function fn(){
            axios("http://192.168.0.109:7001/aotu")
            .then((resquest)=>{
                console.log(resquest);
            });
        };
        function fg(){
            let fm="fm"+new Date().getTime();
            window[fm]=function(jsdata){
            console.log(jsdata);
        };
            let script=document.createElement("script");
            script.src=`http://192.168.0.109:7001/data?cb=${fm}`
            document.body.appendChild(script);
        }
    </script>
</body>

image.png

Proxy代理配置

egg中的网络请求技术:this.ctx.curl(url, option),请求数据后返回的是Promise对象,取值时需要用await。

option常用配置:

method:'GET/POST'

data:{name:"xxx"}//数据会自动字符串化

//home.js文件,写在controller文件夹下的js文件
async sina(){
    let data1=await this.ctx.curl("http://www.baidu.com",{method:"GET",data:{pwd:123}})
    this.ctx.body=data1
}

使用方法

async sina() {
    let url="https://weibo.com";
    let resquest=await this.ctx.curl(url);
    this.ctx.body = resquest;
  }
router.get("/sina",controller.home.sina);
<button class="proxy" onclick="fh()">go to sina</button>
    <!-- 引入axios框架,做AJAX请求 -->
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.js" type="application/javascript"></script>
    <script>
        function fh(){
            axios("/sina")
            .then((resquest)=>{
                console.log(resquest);
            });
        };
    </script>

image.png