koa2 + VueCLI 4.0 + axios 跨域问题

最近在学习nodeJS 的内容,用 koa2 搭建了一个项目。在进行前后端串接的时候遇到了跨越的问题。

跨域的解决有两个方向:

  • 其一,前端设置api代理

    // vue.config.js  
    devServer: {
        proxy: {
          '/api': {
            target: '',
            changeOrigin: true, // 允许websockets跨域
            ws: true,
            pathRewrite: {
              '^/api': ''
            }
          }
        } // 代理转发配置,用于调试环境
      }
    

    关于 vue.config.js 更多配置可查看:关于 Vue CLI 4.0 的 vue.config.js 基本配置范例(jquery、图片压缩、CSS modules)

  • 其二,后端设置允许跨域。(本文所用的就是这个)

    关于后端的跨域配置基本有两种。

    1. 使用原生的 koa2 代码配置;

      app.use(async (ctx, next) => {
          ctx.set('Access-Control-Allow-Origin', '*');
          ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
          ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
          if (ctx.method == 'OPTIONS') {
              ctx.body = 200;
          } else {
              await next();
          }
      })
      
      
    2. 使用中间件 koa2-cors (推荐)

      app.use(
          cors({
              origin: function (ctx) { //设置允许来自指定域名请求
                  // if (ctx.url === '/test') {
                  //     return '*'; // 允许来自所有域名请求
                  // }
                  return ctx.header.origin; //只允许http://localhost:8080这个域名的请求
              },
              maxAge: 5, //指定本次预检请求的有效期,单位为秒。
              credentials: true, //是否允许发送Cookie
              allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法
              allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段
              exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段
          })
      );
      

但是呢!依照各位大佬的方法,在koa2的app.js后面添加相应的配置。然而这配置就是一直不生效。
配置如下:

// app.js (app.js 是 koa2-generator 生成的)
const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')

const index = require('./routes/index')
const users = require('./routes/users')
const person = require('./routes/person')
const cors = require('koa2-cors')

// error handler
onerror(app)

// middlewares
app.use(bodyparser({
    enableTypes: ['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
    extension: 'ejs'
}))

// logger
app.use(async (ctx, next) => {
    const start = new Date()
    await next();
    const ms = new Date() - start
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

// routes 路由配置
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())
app.use(person.routes(), person.allowedMethods())

// error-handling
app.on('error', (err, ctx) => {
    console.error('server error', err, ctx)
});

// 配置跨域
app.use(
    cors({
        origin: function (ctx) { //设置允许来自指定域名请求
            // if (ctx.url === '/test') {
            //     return '*'; // 允许来自所有域名请求
            // }
            return ctx.header.origin; //只允许http://localhost:8080这个域名的请求
        },
        maxAge: 5, //指定本次预检请求的有效期,单位为秒。
        credentials: true, //是否允许发送Cookie
        allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法
        allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段
        exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段
    })
);

module.exports = app

经过多次测试之后,我悲催的发现:根本不是跨域配置出错的问题,而是跨域配置代码放置的问题。我将配置代码移到routes配置前面就可以。
仔细一想,跨域是为routes定义的api而配置的。确实应该放在前面。因为 js 代码是从上到下执行的。当代码运行道app,jsroute入口配置时,自然会跳转到对应的route文件。如果把跨域的配置代码放到route入口配置后面,肯定是不生效的。所以,必须要把跨域配置的代码段移动到route入口配置的前面。

修正后的 代码如下:

const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')

const index = require('./routes/index')
const users = require('./routes/users')
const person = require('./routes/person')
const cors = require('koa2-cors')

// error handler
onerror(app)

// middlewares
app.use(bodyparser({
    enableTypes: ['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
    extension: 'ejs'
}))

// 配置跨域
app.use(
    cors({
        origin: function (ctx) { //设置允许来自指定域名请求
            // if (ctx.url === '/test') {
            //     return '*'; // 允许来自所有域名请求
            // }
            return ctx.header.origin; //只允许http://localhost:8080这个域名的请求
        },
        maxAge: 5, //指定本次预检请求的有效期,单位为秒。
        credentials: true, //是否允许发送Cookie
        allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法
        allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段
        exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段
    })
);

// logger
app.use(async (ctx, next) => {
    const start = new Date()
    await next();
    const ms = new Date() - start
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

// routes 路由配置
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())
app.use(person.routes(), person.allowedMethods())

// error-handling
app.on('error', (err, ctx) => {
    console.error('server error', err, ctx)
});



module.exports = app

你可能感兴趣的:(杂记)