鍍金池/ 問答/HTML/ koa2怎么處理OPTIONS請(qǐng)求

koa2怎么處理OPTIONS請(qǐng)求

自己練習(xí)用koa2去寫接口的時(shí)候,遇到了ajax請(qǐng)求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')
    }
})

然后會(huì)發(fā)生一次OPTIONS的請(qǐng)求,但是一直接受不到,koa2的代碼如下

const fn_usrs = async (ctx, next) => {
  let cb = ctx.request.query.callback;
  if (cb) { //ajax jsonp的請(qǐng)求方式
    ctx.response.body = cb + '(' + JSON.stringify(jsonData) + ')';
  }else{ //
    // ctx.set("Access-Control-Allow-Origin", "*") //ajax json的形式允許都跨域進(jìn)入
    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, 也沒有走這個(gè)'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');


// 部署靜態(tài)資源
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'
}))
// 集中處理錯(cuò)誤
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處理錯(cuò)誤')
    ctx.response.status = err.statusCode || err.status || 500;
    ctx.response.body = {
      message: err.message
    };
  }
};
// 如果錯(cuò)誤被catch. 就不會(huì)出發(fā)onerror時(shí)間,需要調(diào)用 ctx.app.emit('error', err, ctx);
// app.on('error', function(err) {
//   console.log('logging error ', err.message);
// });
app.use(handler)


app.use(bodyParser()); //合適的位置 解析post請(qǐng)求的
app.use(controller()) // 服務(wù)的位置 ----也是寫路由的位置

app.listen(3000, () => {
  console.log('app started at port 3000...');
});

controller 文件的內(nèi)容如下

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();
};

調(diào)用的時(shí)候直接打印了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,
};
這個(gè)是路由的地址,接口的地址,我本地的服務(wù),

解決的方法就是在集中處理錯(cuò)誤的地方統(tǒng)一設(shè)置
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");
這些東西,可以挑著用,看項(xiàng)目的需要。其次還有就是OPTIONS確實(shí)是router內(nèi)容自己處理,我們不需要處理,只需要告訴OPTIONS請(qǐng)求返回200就行,上面的函數(shù)也就變成了下面這個(gè)樣子

// 集中處理錯(cuò)誤
const handler = async (ctx, next) => {
  // log request URL:
  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");
  if (ctx.request.method == "OPTIONS") {
    ctx.response.status = 200
  }
  console.log(`Process ${ctx.request.method} ${ctx.request.url}`);
  try {
    await next();
    console.log('handler通過')
  } catch (err) {
    console.log('handler處理錯(cuò)誤')
    ctx.response.status = err.statusCode || err.status || 500;
    ctx.response.body = {
      message: err.message
    };
  }
};
2018年1月30日 04:26
編輯回答
糖豆豆

OPtion請(qǐng)求是預(yù)請(qǐng)求, 你接受預(yù)請(qǐng)求干嘛?偽命題吧?

2017年10月14日 01:28
編輯回答
忠妾

首先你的頭加了 Authorization ,就不是簡單請(qǐng)求;
最好的方法,就是接口和頁面同域。

2018年9月21日 00:47