egg學習筆記-1

入門筆記

請按照官方文檔初始化一個simple工程項目,按照以下步驟學習便可,若有不懂的請參考官方文檔。node

禁止csrf驗證

根據以下步驟進行控制的建立,在執行Post操做的時候會出現invalid csrf token錯誤。須要禁止此特性。git

建立路由

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const {
    router,
    controller,
  } = app;
  router.get('/', controller.home.index);
  // 新建資源路由
  router.resources('SystemUser', '/system/user', controller.system.user);
};

控制器controller.system.user,對應的是controller目錄下的system目錄裏面的user.js文件github

建立對應的控制器

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

class SystemUserController extends Controller {
  async index() {
    const {
      ctx,
    } = this;
    ctx.body = 'hello ! this is SystemUserController';
  }
}
module.exports = SystemUserController;

訪問地址:localhost:7001/system/usernpm

建立能夠提交數據的控制器方法

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

class SystemUserController extends Controller {
  async index() {
    const {
      ctx,
    } = this;
    ctx.body = 'hello ! this is SystemUserController';
  }

  async create() {
    const ctx = this.ctx;
    const user = ctx.request.body;
    ctx.body = user;
  }
}

module.exports = SystemUserController;

POST方法訪問網址:localhost:7001/system/user 會提示invalid csrf token錯誤。api

關閉csrf驗證

// config\config.default.js
  // 關閉csrf驗證
  config.security = {
    csrf: {
      enable: false,
    },
  };

開啓驗證

在上面的例子中,咱們經過表單提交了任何數據,都會回顯到界面上,若是是數據須要存儲或者作其餘業務處理,則須要對用戶輸入的數據進行驗證。
egg提供了egg-validate插件進行表單驗證數據結構

安裝插件

cnpm install egg-validate --save

配置啓用插件

/** @type Egg.EggPlugin */
module.exports = {
  // had enabled by egg
  // static: {
  //   enable: true,
  // }
  validate: {
    enable: true,
    package: 'egg-validate',
  },

};

使用驗證組件

首先建立一個規則,這裏咱們定義username是字符串並且是必須的,最大長度爲8個字符。
定義password爲字符串且必須,最小長度爲6個字符。
ctx.validate(createRule, ctx.request.body);
經過上述語句進行參數檢查
更多規則請參考:https://github.com/node-modul...app

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

// 定義本接口的請求參數的驗證規則
const createRule = {
  username: {
    type: 'string',
    required: true,
    max: 8,
  },
  password: {
    type: 'string',
    required: true,
    min: 6,
  },
};

class SystemUserController extends Controller {
  async index() {
    const {
      ctx,
    } = this;
    ctx.body = 'hello ! this is SystemUserController';
  }

  async create() {
    const ctx = this.ctx;
    // 驗證輸入參數是否符合預期格式
    ctx.validate(createRule, ctx.request.body);
    const user = ctx.request.body;
    ctx.body = user;
  }
}

module.exports = SystemUserController;

測試

使用POSTMAN提交任意字段,則會提示Validation Failed (code: invalid_param)
如何查看具體錯誤信息呢。下面將定義統一錯誤處理的中間件進行錯誤處理。框架


統一錯誤處理中間件

在項目的app目錄中建立middleware目錄,此目錄中能夠建立中間件。async

建立錯誤處理中間件

'use strict';
module.exports = () => {
  return async function errorHandler(ctx, next) {
    try {
      await next();
    } catch (err) {
      // 控制檯輸出
      console.error('MiddleWare errorHandler', err);
      // 全部的異常都在 app 上觸發一個 error 事件,框架會記錄一條錯誤日誌
      ctx.app.emit('error', err, ctx);
      // status 若是沒有,則統一爲500
      const status = err.status || 500;
      // 若是是500錯誤,且是生產環境,則統一顯示「Internal Server Error」
      const error = status === 500 && ctx.app.config.env === 'prod' ? 'Internal Server Error' : err;
      // 改變上下文狀態代碼
      ctx.status = status;
      // 從 error 對象上讀出各個屬性,設置到響應中
      ctx.body = {
        error,
      };
    }
  };
};

啓用中間件

文件configconfig.default.js中學習

// add your middleware config here
  config.middleware = [];

將其修改成包含你建立的中間件

// add your middleware config here
  // errorHandler 統一錯誤處理
  config.middleware = [ 'errorHandler' ];

  // errorHandler 只在/api上生效
  config.errorHandler = {
    match: '/api',
  };

如上所示,能夠設置錯誤處理中間件在什麼URL上面起做用。這裏咱們使用/api

測試路由

先使用原來的路由訪問:localhost:7001/system/user
錯誤提示依舊
變動路由:打開文件:approuter.js

// router.resources('SystemUser', '/system/user', controller.system.user);
  router.resources('SystemUser', '/api/v1/system/user', controller.system.user);

再次訪問:localhost:7001/api/v1/system/user
提示信息會變成:

{"error":{"message":"Validation Failed","code":"invalid_param","errors":[{"message":"required","field":"username","code":"missing_field"},{"message":"required","field":"password","code":"missing_field"}]}}

格式化接口返回的數據結構

在上面顯示錯誤信息中,能夠看到規範的Json數據,若是開發接口,咱們就須要定義統一的數據結構,以便客戶端進行解析。
在API開發中,能夠定義接口的標準返回格式。經過框架擴展方式定義返回數據格式是一個很是方便的方法。
在app目錄中建立extend目錄,對egg的內置對象Helper進行擴展便可。

建立Helper擴展

文件:app/extend/helper.js

'use strict';

module.exports = {
  /**
   * 調用正常狀況的返回數據封裝
   * @param {Object} ctx - context
   * @param {*} msg  - message
   * @param {*} data - 數據
   */
  success(ctx, msg, data) {
    ctx.body = {
      code: 0,
      msg,
      data,
    };
    ctx.status = 200;
  },

  /**
   * 處理失敗,處理傳入的失敗緣由
   * @param {*} ctx - context
   * @param {Object} res - 返回的狀態數據
   */

  fail(ctx, res) {
    ctx.body = {
      code: res.code,
      msg: res.msg,
      data: res.data,
    };
    ctx.status = 200;
  },
};

改造統一錯誤處理

// 從 error 對象上讀出各個屬性,設置到響應中
// ctx.body = {
//   error,
// };
// 格式化返回錯誤信息
ctx.helper.fail(ctx, {
  code: status,
  msg: error.message,
  data: error.errors,
});

測試

再次訪問:localhost:7001/api/v1/system/user
提示信息會變成:

{
    "code": 422,
    "msg": "Validation Failed",
    "data": [
        {
            "message": "required",
            "field": "username",
            "code": "missing_field"
        },
        {
            "message": "required",
            "field": "password",
            "code": "missing_field"
        }
    ]
}

將控制器user中的返回改成標準格式

async create() {
  const ctx = this.ctx;
  // 驗證輸入參數是否符合預期格式
  ctx.validate(createRule, ctx.request.body);
  const user = ctx.request.body;
  // ctx.body = user;
  this.ctx.helper.success(this.ctx, 'ok', user);
}

提交知足要求的數據,測試正確的返回數據
username testuser
password 1234567890
提交後將返回標準的數據格式

{
    "code": 0,
    "msg": "ok",
    "data": {
        "username": "testuser",
        "password": "1234567890"
    }
}
相關文章
相關標籤/搜索