Egg.js 中入參的校驗


日常作業中免不了頻繁處理 GET/POST 的入參,你當然可以每個 action 中都重復地去做這些事情,

  • 從 query 或 body 取出入參,
  • 對可選的入參進行判空,
  • 處理入參的類型轉換,
  • 對入參進行邏輯校驗,數字是否超限,類型是否非法等...

但這些通用的邏輯可通過抽取到插件或服務中,避免代碼冗余和重復勞動。

egg-validation

Egg.js 中可通過 egg-validation 插件來減少這部分的工作量。通過該插件,上面大部分工作可轉成簡單的配置。

安裝插件

$ yarn add egg-validate

配置插件

啟用:

config/plugin.ts

const plugin: EggPlugin = {
    // ...
    validate: {
        enable: true,
        package: 'egg-validate',
    },
    // ...
};

export default plugin;

配置插件:

config/config.default.ts

export default (appInfo: EggAppInfo) => {
  const config = {} as PowerPartial<EggAppConfig>;

// ...
config.validate = {
convert: true,
widelyUndefined:true
};

// ...
};

其配置項為 node-modules/parameter 的所有可用配置項,因為該插件其實就是后者的 Egg.js 封裝。

  • convert 會對入參進行轉換,建議開啟。舉個例子,使用表單中默認的 submit 類型按鈕提交表單時,提交過來的往往是序列化后的字符串,那些期望是數字類型的字段就會始終驗證不過。而開啟此項后,會對入參按希望的類型進行轉換。
  • widelyUndefined 開啟后,會把空字符串,NaN,null 這些轉成 undefined,將這些異常的數據進行了統一,方便后續處理。

使用

插件在 appcontext 上擴展了 validator 對象,通過調用 validator.validate(rules,data) 來進行驗證。

比如接收一個名為 name 的字符串入參:

app/controller/home.ts

const errors = this.app.validator.validate({ name: 'string' }, this.request.body);
if (errors) {
    this.ctx.body = errors;
}

驗證規則

validate 第一個參數為規則,它是個對象。其每個字段對應同名的入參。字段的值可以是簡單的字符串,指定字段的類型,也可以是對象,在這個對象里進行更加詳細的規則指定。

const rules = {
    param1: 'string', // 必填的字符串入參
    param2: 'string?', // 可選的字符串入參
    param3: {
        type: 'int', // 整形入參
        required: false, // 該入參可選
        min: 0, // 該入參的最小值
        max: 10, // 該入參的最大值
    },
};

規則默認入參是必填的,對於可選的入參,可通過在類型后加問號,與 TypeScript 類似,也可以顯式指定 required: false

預設可用的參數類型參見 parameter

針對參數的規則配置,根據參數的類型,有不同的配置頂,比如對於數字類型,可配置其最大最小值;對於枚舉,可定義其候選值,一旦入參不在這些值之內,便驗證不通過。每種類型可用的配置項參見 parameter

自定義驗證規則

如果上面文檔中預設的這些類型無法滿足需求,可通過 validator.addRule(type,checker) 自定義規則來擴充。

其中 type 為新增規則的類型名, checker 為用來校驗的正則或方法。如果是個方法,其入參為規則本身及需要校驗的數據,文檔里沒有體現其入參,可參考源碼

checker.call(self, rule, obj[key], obj);

比如增加一種類型為 jsonString 的驗證規則,限定入參必需為合法的 JSON 數據。

app.ts

export default (app) => {
    app.validator.addRule('jsonString', (_rule, value) => {
        try {
            JSON.parse(value);
        } catch (err) {
            return 'must be json string';
        }
    });
};

示例代碼

一個可本地運行調試,配合了預設的驗證規則及自定義的規則的示例,完整代碼可在 GitHub 找到。

結論

寫了過多的重復的代碼后,比如這種入參的校驗,就應該想想如何優雅地來處理這些重復的工作,無論是自己造輪子,還是找輪子。入參的校驗如此之常見,進而,甚至可以去追求一套前后台通用的校驗邏輯,將瀏覽器端的 JavaScript 與 Node.js 的邏輯進行統一。

相關資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM