欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

推薦一個(gè)基于Node.js的表單驗(yàn)證庫

 更新時(shí)間:2019年02月15日 10:08:59   作者:瘋狂的技術(shù)宅  
這篇文章主要介紹了推薦一個(gè)基于Node.js的表單驗(yàn)證庫,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

API 在執(zhí)行過程中的一個(gè)基本任務(wù)是數(shù)據(jù)驗(yàn)證。 在本文中,我想向你展示如何為你的數(shù)據(jù)添加防彈驗(yàn)證,同時(shí)返回風(fēng)格良好的格式。

在 Node.js 中進(jìn)行自定義數(shù)據(jù)驗(yàn)證既不容易也不快。 為了覆蓋所有類型的數(shù)據(jù),需要寫許多函數(shù)。 雖然我已經(jīng)嘗試了一些 Node.js 的表單庫 —— Express 和 Koa ——他們從未滿足我的項(xiàng)目需求。 這些擴(kuò)展庫要么不兼容復(fù)雜的數(shù)據(jù)結(jié)構(gòu),要么在異步驗(yàn)證出現(xiàn)問題。

使用 Datalize 在 Node.js 中進(jìn)行表單驗(yàn)證

這就是為什么我最終決定編寫自己的小巧而強(qiáng)大的表單驗(yàn)證庫的原因,它被稱為 datalize。 它是可擴(kuò)展的,因此你可以在任何項(xiàng)目中使用它,并根據(jù)你的要求進(jìn)行自定義。 它能夠驗(yàn)證請求的正文、查詢或參數(shù),還支持async 過濾器和復(fù)雜的JSON結(jié)構(gòu),如 數(shù)組 或 嵌套對象。

Github:https://github.com/flowstudio/datalize

配置

Datalize可以通過npm安裝:

npm install --save datalize

要解析請求的正文,你應(yīng)該使用其他的庫。 如果你還沒有用過,我建議使用 koa-body for Koa 或 body-parser for Express。

你可以將本教程用于已配置好的HTTP API服務(wù)器,也可以使用以下簡單的Koa HTTP服務(wù)器代碼。

const Koa = require('koa');
const bodyParser = require('koa-body');

const app = new Koa();
const router = new (require('koa-router'))();

// helper for returning errors in routes
app.context.error = function(code, obj) {
this.status = code;
this.body = obj;
};

// add koa-body middleware to parse JSON and form-data body
app.use(bodyParser({
enableTypes: ['json', 'form'],
multipart: true,
formidable: {
maxFileSize: 32 * 1024 * 1024,
}
}));

// Routes...

// connect defined routes as middleware to Koa
app.use(router.routes());
// our app will listen on port 3000
app.listen(3000);

console.log('🌍 API listening on 3000');

但是,這不是生產(chǎn)環(huán)境下的設(shè)置(你還應(yīng)該使用logging,強(qiáng)制 授權(quán)錯(cuò)誤處理等),不過這幾行代碼用于向你正常展示后面的例子足夠了。

注意:所有代碼示例都基于 Koa,但數(shù)據(jù)驗(yàn)證代碼也同樣適用于 Express。 datalize 庫還有一個(gè)實(shí)現(xiàn) Express 表單驗(yàn)證的例子。

一個(gè)基本的Node.js表單驗(yàn)證案例

假設(shè)你的 API 中有一個(gè) Koa 或 Express Web 寫的服務(wù)和一個(gè)端點(diǎn),用于在數(shù)據(jù)庫中創(chuàng)建包含多個(gè)字段的用戶數(shù)據(jù)。其中某些字段是必需的,有些字段只能具有特定值,或者必須格式化為正確的類型。

你可以像這樣寫一個(gè)簡單的邏輯:

/**
 * @api {post} / Create a user
 * ...
 */
router.post('/', (ctx) => {
  const data = ctx.request.body;
  const errors = {};
  
  if (!String(data.name).trim()) {
    errors.name = ['Name is required'];
  }
  
  if (!(/^[\-0-9a-zA-Z\.\+_]+@[\-0-9a-zA-Z\.\+_]+\.[a-zA-Z]{2,}$/).test(String(data.email))) {
    errors.email = ['Email is not valid.'];
  }
  
  if (Object.keys(errors).length) {
    return ctx.error(400, {errors});
  }
  
  const user = await User.create({
      name: data.name,
      email: data.email,
  });
  
  ctx.body = user.toJSON();
});

下面讓我們重寫這段代碼并使用 datalize 驗(yàn)證這個(gè)請求:

const datalize = require('datalize');
const field = datalize.field;

/**
 * @api {post} / Create a user
 * ...
 */
router.post('/', datalize([
  field('name').trim().required(),
  field('email').required().email(),
]), (ctx) => {
  if (!ctx.form.isValid) {
    return ctx.error(400, {errors: ctx.form.errors});
  }
  
  const user = await User.create(ctx.form);
  
  ctx.body = user.toJSON();
});

短小精悍并易于閱讀。 使用 datalize,你可以指定字段列表,并為它們鏈接盡可能多的規(guī)則(用于判斷輸入是否有效并拋出錯(cuò)誤的函數(shù))或過濾器(用于格式化輸入的函數(shù))。

規(guī)則和過濾器的執(zhí)行順序與它們定義的順序相同,所以如果你想要先切分含有空格的字符串,然后再檢查它是否有值,則必須在 .trim() 之前定義 .required()。

然后,Datalize 將只使用你指定的字段創(chuàng)建一個(gè)對象(在更廣泛的上下文對象中以 .form 形式提供),因此你不必再次列出它們。 .form.isValid 屬性會(huì)告訴你驗(yàn)證是否成功。

自動(dòng)錯(cuò)誤處理

如果我們不想檢查表單是否對每個(gè)請求都有效,可以添加一個(gè)全局中間件,如果數(shù)據(jù)未通過驗(yàn)證,則取消請求。

為此,我們只需將這段代碼添加到我們創(chuàng)建的 Koa / Express 應(yīng)用實(shí)例的 bootstrap 文件中。

const datalize = require('datalize');

// set datalize to throw an error if validation fails
datalize.set('autoValidate', true);

// only Koa
// add to very beginning of Koa middleware chain
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    if (err instanceof datalize.Error) {
      ctx.status = 400;
      ctx.body = err.toJSON();
    } else {
      ctx.status = 500;
      ctx.body = 'Internal server error';
    }
  }
});


// only Express
// add to very end of Express middleware chain
app.use(function(err, req, res, next) {
  if (err instanceof datalize.Error) {
    res.status(400).send(err.toJSON());
  } else {
    res.send(500).send('Internal server error');
  }
});

而且我們不必檢查數(shù)據(jù)是否有效,因?yàn)?datalize 將幫我們做到這些。 如果數(shù)據(jù)無效,它將返回帶有無效字段列表的格式化錯(cuò)誤消息。

查詢驗(yàn)證

是的,你甚至可以非常輕松地驗(yàn)證查詢參數(shù)——它不僅僅用于POST請求。 我們也可以只使用.query()輔助方法,唯一的區(qū)別是數(shù)據(jù)存儲(chǔ)在 .data 對象而不是 .form 中。

const datalize = require('datalize');
const field = datalize.field;

/**
 * @api {get} / List users
 * ...
 */
router.post('/', datalize.query([
  field('keywords').trim(),
  field('page').default(1).number(),
  field('perPage').required().select([10, 30, 50]),
]), (ctx) => {
  const limit = ctx.data.perPage;
  const where = {
  };
  
  if (ctx.data.keywords) {
    where.name = {[Op.like]: ctx.data.keywords + '%'};
  }
  
  const users = await User.findAll({
    where,
    limit,
    offset: (ctx.data.page - 1) * limit,
  });
  
  ctx.body = users;
});

還有一個(gè)輔助方法用于參數(shù)驗(yàn)證:.params()。 通過在路由的 .post() 方法中傳遞兩個(gè) datalize 中間件,可以同時(shí)對查詢和表單數(shù)據(jù)進(jìn)行驗(yàn)證。

更多過濾器,數(shù)組和嵌套對象

到目前為止,我們在 Node.js 表單驗(yàn)證中使用了非常簡單的數(shù)據(jù)。 現(xiàn)在讓我們嘗試一些更復(fù)雜的字段,如數(shù)組,嵌套對象等:

const datalize = require('datalize');
const field = datalize.field;
const DOMAIN_ERROR = "Email's domain does not have a valid MX (mail) entry in its DNS record";

/**
 * @api {post} / Create a user
 * ...
 */
router.post('/', datalize([
  field('name').trim().required(),
  field('email').required().email().custom((value) => {
    return new Promise((resolve, reject) => {
      dns.resolve(value.split('@')[1], 'MX', function(err, addresses) {
        if (err || !addresses || !addresses.length) {
          return reject(new Error(DOMAIN_ERROR));
        }
        
        resolve();
      });
    });
  }),
  field('type').required().select(['admin', 'user']),
  field('languages').array().container([
    field('id').required().id(),
    field('level').required().select(['beginner', 'intermediate', 'advanced'])
  ]),
  field('groups').array().id(),
]), async (ctx) => {
  const {languages, groups} = ctx.form;
  delete ctx.form.languages;
  delete ctx.form.groups;
  
  const user = await User.create(ctx.form);
  
  await UserGroup.bulkCreate(groups.map(groupId => ({
    groupId,
    userId: user.id,
  })));
  
  await UserLanguage.bulkCreate(languages.map(item => ({
    languageId: item.id,
    userId: user.id,
    level: item.level,
  ));
});

如果我們需要驗(yàn)證的數(shù)據(jù)沒有內(nèi)置規(guī)則,我們可以用 .custom() 方法創(chuàng)建一個(gè)自定義數(shù)據(jù)驗(yàn)證規(guī)則(很不錯(cuò)的名字,對嗎?)并在那里編寫必要的邏輯。 對于嵌套對象,有 .container() 方法,你可以在其中用和 datalize() 函數(shù)相同的方式指定字段列表。 你可以將容器嵌套在容器中,或使用 .array() 過濾器對其進(jìn)行補(bǔ)充,這些過濾器會(huì)將值轉(zhuǎn)換為數(shù)組。 如果在沒有容器的情況下使用 .array() 過濾器,則指定的規(guī)則或過濾器將被用于數(shù)組中的每個(gè)值。

所以 .array().select(['read', 'write']) 將檢查數(shù)組中的每個(gè)值是 'read' 還是 'write' ,如果有任何一個(gè)值不是其中之一,則返回所有錯(cuò)誤的索引列表。 很酷,對吧?

PUT/PATCH

在使用 PUT/PATCH (或 POST)更新數(shù)據(jù)時(shí),你不必重寫所有邏輯、規(guī)則和過濾器。 只需添加一個(gè)額外的過濾器,如 .optional() 或 .patch() ,如果未在請求中定義,它將從上下文對象中刪除任何字段。 ( .optional() 將使它始終是可選的,而 .patch() 只有在 HTTP 請求的方法是 PATCH 時(shí)才會(huì)使它成為可選項(xiàng)。)你可以添這個(gè)額外的過濾器,以便它可以在數(shù)據(jù)庫中創(chuàng)建和更新數(shù)據(jù)。

const datalize = require('datalize');
const field = datalize.field;

const userValidator = datalize([
  field('name').patch().trim().required(),
  field('email').patch().required().email(),
  field('type').patch().required().select(['admin', 'user']),
]);

const userEditMiddleware = async (ctx, next) => {
  const user = await User.findByPk(ctx.params.id);
  
  // cancel request here if user was not found
  if (!user) {
    throw new Error('User was not found.');
  }
  
  // store user instance in the request so we can use it later
  ctx.user = user;
  
  return next();
};

/**
 * @api {post} / Create a user
 * ...
 */
router.post('/', userValidator, async (ctx) => {
  const user = await User.create(ctx.form);
  
  ctx.body = user.toJSON();
});

/**
 * @api {put} / Update a user
 * ...
 */
router.put('/:id', userEditMiddleware, userValidator, async (ctx) => {
  await ctx.user.update(ctx.form);
  
  ctx.body = ctx.user.toJSON();
});

/**
 * @api {patch} / Patch a user
 * ...
 */
router.patch('/:id', userEditMiddleware, userValidator, async (ctx) => {
  if (!Object.keys(ctx.form).length) {
    return ctx.error(400, {message: 'Nothing to update.'});
  }
  
  await ctx.user.update(ctx.form);
  
  ctx.body = ctx.user.toJSON();
});

使用兩個(gè)簡單的中間件,我們可以為所有 POST/PUT/PATCH 方法編寫大多數(shù)邏輯。 userEditMiddleware() 函數(shù)驗(yàn)證我們要編輯的記錄是否存在,否則便拋出錯(cuò)誤。 然后 userValidator() 對所有端點(diǎn)進(jìn)行驗(yàn)證。 最后 .patch() 過濾器將刪除 .form 對象中的任何字段(如果其未定義)或者假如請求的方法是 PATCH 的話。

Node.js表單驗(yàn)證附加功能

在自定義過濾器中,你可以獲取其他字段的值并根據(jù)該值執(zhí)行驗(yàn)證。 還可以從上下文對象中獲取任何數(shù)據(jù),例如請求或用戶信息,因?yàn)樗鼈兌际窃谧远x函數(shù)的回調(diào)參數(shù)中提供的。

該庫涵蓋了一組基本規(guī)則和過濾器,不過你可以注冊能與任何字段一起使用的自定義全局過濾器,所以你不必一遍又一遍地寫相同的代碼:

const datalize = require('datalize');
const Field = datalize.Field;

Field.prototype.date = function(format = 'YYYY-MM-DD') {
 return this.add(function(value) {
  const date = value ? moment(value, format) : null;

  if (!date || !date.isValid()) {
   throw new Error('%s is not a valid date.');
  }

  return date.format(format);
 });
};

Field.prototype.dateTime = function(format = 'YYYY-MM-DD HH:mm') {
 return this.date(format);
};

有了這兩個(gè)自定義過濾器,你就可以用 .date() 或 .dateTime() 過濾器鏈接字段對日期輸入進(jìn)行驗(yàn)證。

文件也可以使用 datalize 進(jìn)行驗(yàn)證:只有 .file(), .mime(), 和 .size() 等文件才有特殊的過濾器,所以你不必單獨(dú)處理文件。

立即開始編寫更好的API

對于小型和大型API,我已經(jīng)在好幾個(gè)生產(chǎn)項(xiàng)目中用 datalize 進(jìn)行 Node.js 表單驗(yàn)證。 這有助于我按時(shí)提供優(yōu)秀項(xiàng)目、減輕開發(fā)壓力,同時(shí)使其更具可讀性和可維護(hù)性。 在一個(gè)項(xiàng)目中,我甚至用它來通過對 Socket.IO 進(jìn)行簡單封裝,來驗(yàn)證 WebSocket 消息的數(shù)據(jù),其用法與在 Koa 中的定義路由幾乎完全相同,所以這很好用。 如果很多人有興趣的話,我也可以為此編寫一個(gè)教程。

我希望本教程能夠幫助你在 Node.js 中構(gòu)建更好的API,并使用經(jīng)過完美驗(yàn)證的數(shù)據(jù),而不會(huì)出現(xiàn)安全問題或內(nèi)部服務(wù)器錯(cuò)誤。 最重要的是,我希望它能為你節(jié)省大量時(shí)間,否則你將不得不用 JavaScript 投入大量時(shí)間來編寫額外的函數(shù)進(jìn)行表單驗(yàn)證。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Node.js dgram模塊實(shí)現(xiàn)UDP通信示例代碼

    Node.js dgram模塊實(shí)現(xiàn)UDP通信示例代碼

    這篇文章主要介紹了Node.js dgram模塊實(shí)現(xiàn)UDP通信示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Node.js?源碼閱讀深入理解cjs模塊系統(tǒng)

    Node.js?源碼閱讀深入理解cjs模塊系統(tǒng)

    這篇文章主要為大家介紹了Node.js?源碼閱讀深入理解cjs模塊系統(tǒng),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Node.js服務(wù)端實(shí)戰(zhàn)之服務(wù)啟動(dòng)過程詳解

    Node.js服務(wù)端實(shí)戰(zhàn)之服務(wù)啟動(dòng)過程詳解

    這篇文章主要為大家介紹了Node.js服務(wù)端實(shí)戰(zhàn)之服務(wù)啟動(dòng)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 從零學(xué)習(xí)node.js之express入門(六)

    從零學(xué)習(xí)node.js之express入門(六)

    相信大家都知道Express是一個(gè)簡潔而靈活的 node.js Web應(yīng)用框架, 提供了一系列強(qiáng)大特性幫助你創(chuàng)建各種 Web 應(yīng)用,和豐富的 HTTP 工具。下面這篇文章主要介紹了node.js中express的入門知識,需要的朋友可以參考下。
    2017-02-02
  • Node.js實(shí)現(xiàn)前端后端數(shù)據(jù)傳輸加密解密

    Node.js實(shí)現(xiàn)前端后端數(shù)據(jù)傳輸加密解密

    這篇文章主要介紹了Node.js實(shí)現(xiàn)前端后端數(shù)據(jù)傳輸加密解密,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能

    node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能

    本文主要介紹了node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 使用Node.js寫一個(gè)代碼生成器的方法步驟

    使用Node.js寫一個(gè)代碼生成器的方法步驟

    這篇文章主要介紹了使用 Node.js 寫一個(gè)代碼生成器,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • node解析修改nginx配置文件操作實(shí)例分析

    node解析修改nginx配置文件操作實(shí)例分析

    這篇文章主要介紹了node解析修改nginx配置文件操作,結(jié)合實(shí)例形式分析了node.js使用nginx-conf解析修改nginx配置文件的相關(guān)操作技巧,需要的朋友可以參考下
    2019-11-11
  • require加載器實(shí)現(xiàn)原理的深入理解

    require加載器實(shí)現(xiàn)原理的深入理解

    這篇文章主要給大家介紹了關(guān)于require加載器實(shí)現(xiàn)原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Node.js使用SQLite數(shù)據(jù)庫方法大全

    Node.js使用SQLite數(shù)據(jù)庫方法大全

    Node.js是一種流行的JavaScript運(yùn)行時(shí),提供了許多有用的模塊和庫來構(gòu)建Web應(yīng)用程序,而SQLite是一種嵌入式關(guān)系型數(shù)據(jù)庫,它可以運(yùn)行在各種操作系統(tǒng)上,包括Windows、Linux和Mac OS X等,在Node.js中,可以通過安裝sqlite3模塊來訪問SQLite數(shù)據(jù)庫
    2023-10-10

最新評論