解法参考
前言
先说我的情况。前段H5使用react开发,后端koa2。前端页面本地使用3000端口,Koa2使用3001端口。毫无疑问,联调就涉及跨域。
因为后端代码在我这里,所以我选择后端配置的办法(这样一次配置,多个页面都能跨域联调)。
解法
解法参考
为防止页面失效。我复制一份儿放这儿。
关于后端的跨域配置基本有两种。
- 使用自己写中间件方法:
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();
}
})
- 使用中间件 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中间件的执行顺序是按代码顺序生效的。也就说,
!!!!这段允许跨域的代码必须配置在路由生效之前!!!
比如这样:
/**
*开发阶段的临时配置
*/
let devConfig = (app)=>{
if (process.env.NODE_ENV === 'production'){
console.log(process.env.NODE_ENV);
return;
}
//开发环境下,允许跨域请求。
//注意:跨域请求开启必须放在route配置之前!!!
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'] //设置获取其他自定义字段
}));
}
然后devConfig
调用处必须在路由设置前面。比如这样:
const app = new Koa();
//开发环境下需要增加的一些配置
devConfig(app);
//网站图标
app.use(favicon(__dirname + '/statics/img/favicon.ico'));
//配置日志记录
app.use(Logger());
//配置路由规则
Router.getInstance(app).initRouteRules();
//配置静态资源服务
initStatics(app)
//配置渲染引擎
initRenderEngine(app);
//开始监听
app.listen(3001)
```
这样前端页面不需要做任何跨域修改,就能直接请求到数据了。