自己练习用koa2去写接口的时候,遇到了ajax请求GET接口,例如如下
$.ajax({
type: "GET",
url:'http://localhost:3000/user_new',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=utf-8',
'Authorization': 'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTJjYjA5MjFjMjM0NDgzODhjMDQ1Mzg2N2QzZDI0NzUiLCJjb21wYW55X2lkIjoiNzM2ZDc5YjQ1NTkzNDU2NWE4ODljYjJmOTBhOTNlNzIiLCJzdGFmZl9pZCI6IjhlODM2MjFmZjQ3YTRhZGY4NjU4NGNhNWYxNDRmYzc0IiwidGVuYW50X2lkIjoiMTliMDQyMGM3ODViNGNlN2IxODNmMTFjMjY0M2I4YmUifQ.D7Mrba-lB94iSWr2pHAtS4KUkC_g06lJVHutj0MIu1Q'
},
success: function (data, textStatus) {
console.log('123123')
},
error: function (a,b,c) {
console.log('2222222')
}
})
然后会发生一次OPTIONS的请求,但是一直接受不到,koa2的代码如下
const fn_usrs = async (ctx, next) => {
let cb = ctx.request.query.callback;
if (cb) { //ajax jsonp的请求方式
ctx.response.body = cb + '(' + JSON.stringify(jsonData) + ')';
}else{ //
// ctx.set("Access-Control-Allow-Origin", "*") //ajax json的形式允许都跨域进入
ctx.response.body = '{}'; //proxy 代理的方式
}
}
const fn_usrs_option = async(ctx, next) => {
// ctx.set("Access-Control-Allow-Origin", "*");
if (ctx.request.method == "OPTIONS") {
ctx.response.status = 200
}
ctx.response.status = 200
}
module.exports = {
'GET /user_new': fn_usrs_new,
'OPTIONS /user_new': fn_usrs_option,
};
可是浏览器却一直显示的是404 找不到,也没有走'OPTIONS /user_new': fn_usrs_option,
也没有走这个'GET /user_new': fn_usrs_new,
koa2代码的index.js如下
const Koa = require('koa');
const app = new Koa();
const path = require('path');
const static = require('koa-static');
const bodyParser = require('koa-bodyparser');
const router = require('koa-router')();
const controller = require('./server/index.js');
// 部署静态资源
const staticPath = './static';
app.use(static(
path.join( __dirname, staticPath)
))
// ejs 模版引擎
const views = require('koa-views')
app.use(views(path.join(__dirname, './view'), {
extension: 'ejs'
}))
// 集中处理错误
const handler = async (ctx, next) => {
// log request URL:
// ctx.set("Access-Control-Allow-Origin", "*");
// ctx.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
console.log(`Process ${ctx.request.method} ${ctx.request.url}`);
try {
await next();
console.log('handler通过')
} catch (err) {
console.log('handler处理错误')
ctx.response.status = err.statusCode || err.status || 500;
ctx.response.body = {
message: err.message
};
}
};
// 如果错误被catch. 就不会出发onerror时间,需要调用 ctx.app.emit('error', err, ctx);
// app.on('error', function(err) {
// console.log('logging error ', err.message);
// });
app.use(handler)
app.use(bodyParser()); //合适的位置 解析post请求的
app.use(controller()) // 服务的位置 ----也是写路由的位置
app.listen(3000, () => {
console.log('app started at port 3000...');
});
controller 文件的内容如下
const fs = require('fs');
function addMapping(router, mapping) {
for (var url in mapping) {
if (url.startsWith('GET ')) {
var path = url.substring(4);
router.get(path, mapping[url]);
// console.log(`register URL mapping: GET ${path}`);
} else if (url.startsWith('OPTIONS ')) {
var path = url.substring(8);
router.get(path, mapping[url]);
} else if (url.startsWith('POST ')) {
var path = url.substring(5);
router.post(path, mapping[url]);
// console.log(`register URL mapping: POST ${path}`);
} else if (url.startsWith('PUT ')) {
var path = url.substring(4);
router.put(path, mapping[url]);
// console.log(`register URL mapping: PUT ${path}`);
} else if (url.startsWith('DELETE ')) {
var path = url.substring(7);
router.del(path, mapping[url]);
// console.log(`register URL mapping: DELETE ${path}`);
} else {
console.log(`invalid URL: ${url}`);
}
}
}
function addControllers(router, dir) {
const files = fs.readdirSync(__dirname + '/' + dir).filter((f) => {
return f !== 'index.js';
})
files.forEach((f) => {
// console.log(`process controller: ${f}...`);
let mapping = require(__dirname + '/' + f);
addMapping(router, mapping);
});
}
module.exports = function(dir) {
let controllers_dir = dir || '/',
router = require('koa-router')();
addControllers(router, controllers_dir);
return router.routes();
};
调用的时候直接打印了process和handler通过。不知道为什么?找了很多原因也没有找到
module.exports = {
'GET /user_new': fn_usrs_new,
'OPTIONS /user_new': fn_usrs_option,
'GET /users': fn_usrs,
'POST /users': add_usrs,
'DELETE /users/:id': del_usrs,
};
这个是路由的地址,接口的地址,我本地的服务,
解决的方法就是在集中处理错误的地方统一设置
ctx.set("Access-Control-Allow-Origin", "*");
ctx.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
ctx.set("Access-Control-Max-Age", "3600");
ctx.set("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type,Accept");
ctx.set("Access-Control-Allow-Credentials", "true");
这些东西,可以挑着用,看项目的需要。其次还有就是OPTIONS确实是router内容自己处理,我们不需要处理,只需要告诉OPTIONS请求返回200就行,上面的函数也就变成了下面这个样子