Fastify 系列教程三 (验证、序列化和生命周期)
Fastify 系列教程:
- Fastify 系列教程一 (路由和日志)
- Fastify 系列教程二 (中间件、钩子函数和装饰器)
- Fastify 系列教程三 (验证、序列化和生命周期)
- Fastify 系列教程四 (请求对象、响应对象和插件)
验证
Fastify 可以验证请求信息,只有符合验证规则的请求才会被处理。
JSON Schema
什么是 JSON Schema ,通俗来讲,JSON Schema 就是“描述 JSON 数据格式的一段 JSON”。
首先,JSON Schema 也是一个 JSON 字符串,下面来看一个简单的 JSON Schema:
{"$schema": "http://json-schema.org/draft-04/schema#","title": "Product","description": "A product from Acme's catalog","type": "object","properties": {"id": {"description": "The unique identifier for a product","type": "integer"},"name": {"description": "Name of the product","type": "string"},"price": {"type": "number","minimum": 0,"exclusiveMinimum": true}},"required": ["id", "name", "price"]
}
上面这段规则描述了这样一个JSON:
1、type
表示该 JSON 的类型是一个 "object"。
type 的参数可以是:number
, integer
(整型), string
, boolean
, array
, object
或者 null
。也可以是一个包含上述类型的数组。
schema:
{ "type": "number" }
valid:
1
,1.5
invalid:
"abc"
,"1"
,[]
,{}
,null
,true
schema:
{ "type": "integer" }
valid:
1
,2
invalid:
"abc"
,"1"
,1.5
,[]
,{}
,null
,true
schema:
{ "type": ["number", "string"] }
valid:
1
,1.5
,"abc"
,"1"
invalid:
[]
,{}
,null
,true
2、properties
定义了 JSON 的字段规则。
3、requirede
定义了必须存在的属性列表。
我们来看一下可以用于这一模式中的各种重要关键字:
关键词 | 描述 |
---|---|
$schema | $schema 关键字状态,表示这个模式与 v4 规范草案书写一致。 |
title | 用它给我们的模式提供了标题。 |
description | 关于模式的描述。 |
type | type 关键字在我们的 JSON 数据上定义了第一个约束:必须是一个 JSON 对象。 |
properties | 定义各种键和他们的值类型,以及用于 JSON 文件中的最小值和最大值。 |
required | 存放必要属性列表。 |
minimum | 给值设置的约束条件,表示可以接受的最小值。 |
exclusiveMinimum | 如果存在 "exclusiveMinimum" 并且具有布尔值 true,如果它严格意义上大于 "minimum" 的值则实例有效。 |
maximum | 给值设置的约束条件,表示可以接受的最大值。 |
exclusiveMaximum | 如果存在 "exclusiveMinimum" 并且具有布尔值 true,如果它严格意义上小于 "maximum" 的值则实例有效。 |
multipleOf | 如果通过这个关键字的值分割实例的结果是一个数字则表示紧靠 "multipleOf" 的数字实例是有效的。 |
maxLength | 字符串实例字符的最大长度数值。 |
minLength | 字符串实例字符的最小长度数值。 |
pattern | 如果正则表达式匹配实例成功则字符串实例被认为是有效的。 |
通过上面的配置,我们就可以验证某个 JSON 是否符合要求了:
validate(JSONSchema, myJson)
有同学肯定会问,这个验证函数 validate
从哪来?github 上有各种第三方验证器:
语言 | 程序库 |
---|---|
C | WJElement (LGPLv3) |
Java | json-schema-validator (LGPLv3) |
.NET | Json.NET (MIT) |
ActionScript 3 | Frigga (MIT) |
Haskell | aeson-schema (MIT) |
Python | Jsonschema |
Ruby | autoparse (ASL 2.0); ruby-jsonschema (MIT) |
PHP | php-json-schema (MIT). json-schema (Berkeley) |
JavaScript | Orderly (BSD); JSV; json-schema; Matic (MIT); Dojo; Persevere (modified BSD or AFL 2.0); schema.js. |
而 Fastify 所使用的 ajv 也是一个 JSON Schema 验证器,号称:
The fastest JSON Schema validator for Node.js and browser with draft 6 support.
有了上面的介绍,我们就来看一下 Fastify 是怎么验证请求信息的吧:
非常简单,只需要添加需要验证的字段即可。
body
:验证请求体,必须是 POST 或者 PUT 请求。querystring
: 验证查询字符串。可以是一个完成的 JSON Schema 对象(符合{type: "object", properties: {...}}
的格式)或者没有type
和properties
属性,而只有查询字符串列表。(查看下面的例子)params
: 验证路由参数。headers
: 验证请求头。
示例:
fastify.post('/add', {schema: {body: {type: 'object',properties: {name: {type: 'string'},id: {type: 'number'}},required: ['name', 'id']}}
}, function(request, reply){reply.send('validate successful')
})
当发送一个body为
{"name": "lavyun","id": "hello"
}
的 post
请求时,会得到错误:
{"error": "Bad Request","message": "[{\"keyword\":\"type\",\"dataPath\":\".id\",\"schemaPath\":\"#/properties/id/type\",\"params\":{\"type\":\"number\"},\"message\":\"should be number\"}]","statusCode": 400
}
因为 id 不符合 number
类型,把 id 改成 1
就可以了。
注意:Fastify 配置了 avj 默认会自动把不符合类型的值强制转换成规则中定义的类型,如果仍然不符合类型,则返回错误:
例如
{"name": null,"id": "2"
}
也会验证通过,因为被强转成:
"name": "null","id": 2
如果不想被强制转换,可以通过配置 avj 关闭该功能:
const fastify = require('fastify')({ajv: {coerceTypes: false}
})
Schema Compiler
schemaCompiler
是一个指定 schema 编译器的方法。(用来验证 body, params, headers, querystring)。默认的 schemaCompiler
返回一个实现 ajv
接口的编译器。
如果你想更改默认的 ajv
实例,可以传入 ajv
配置项, 查看 Ajv documentation 了解更多。
或许想直接更换验证的库,比如使用 Joi:
const Joi = require('joi')fastify.post('/the/url', {schema: {body: Joi.object().keys({hello: Joi.string().required()}).required()},schemaCompiler: schema => data => Joi.validate(data, schema)
})
序列化
通常,我们会通过 JSON 将数据发送给客户端, Fastify 提供了一个强大的工具: fast-json-stringify,这是一个比原生 JSON.stringify()
还快的 JSON 格式化器,其原理就是通过配合 JSON Schema,快速定位字段的类型,省去了原生 JSON.stringify()
内部判断字段类型的步骤,实现了 two times faster than JSON.stringify().
的效果。
在路由选项中传入了 output schema,fastify 就会使用它。
const schema = {response: {200: {type: 'object',properties: {value: { type: 'string' },otherValue: { type: 'boolean' }}}}
}
response schema 是基于状态码的,如果想应用相同的 schema 给多个同级状态码, 可以使用 2xx
。
const schema = {response: {'2xx': {type: 'object',properties: {value: { type: 'string' },otherValue: { type: 'boolean' }}},201: {type: 'object',properties: {value: { type: 'string' }}}}
}
patternProperties
fast-json-stringify
支持属性匹配,符合属性正则的字段都会被验证:
const stringify = fastJson({title: 'Example Schema',type: 'object',properties: {nickname: {type: 'string'}},patternProperties: {'num': {type: 'number'},'.*foo$': {type: 'string'}}
})const obj = {nickname: 'nick',matchfoo: 42,otherfoo: 'str'matchnum: 3
}console.log(stringify(obj)) // '{"matchfoo":"42","otherfoo":"str","matchnum":3,"nickname":"nick"}'
更多 fast-json-stringify
的使用可以查看文档
生命周期
Fastify 严格遵循内部生命周期的架构。在每个部分的右侧分支上都有生命周期的下一个阶段,左侧的分支上有相应的错误状态码,如果父代引发错误,则会生成相应的错误状态码(注意,所有错误都由Fastify自动处理)。
Fastify 生命周期图示:
Incoming Request (请求到达)│└─▶ Instance Logger (实例化 Logger)│└─▶ Routing (路由匹配)│404 ◀─┴─▶ onRequest Hook (onRequest钩子)│4**/5** ◀─┴─▶ run Middlewares (执行中间件)│4**/5** ◀─┴─▶ Parsing (解析请求对象)│415 ◀─┴─▶ Validation (验证)│400 ◀─┴─▶ preHandler Hook (preHandler钩子)│4**/5** ◀─┴─▶ beforeHandler│4**/5** ◀─┴─▶ User Handler│└─▶ Reply (响应)│ ││ └─▶ Outgoing Response (发出响应)│└─▶ onResponse Hook (onResponese钩子
Fastify 的更多使用将在接下来的博客中说明。
参考文档:
JSON 模式 / http://wiki.jikexueyuan.com/project/json/schema.html
Tips:访问 https://lavyun.gitbooks.io/fastify/content/ 查看我翻译的 Fastify 中文文档。
访问lavyun.cn 查看我的个人博客
转载于:https://www.cnblogs.com/smartXiang/p/7749737.html
Fastify 系列教程三 (验证、序列化和生命周期)相关推荐
- Vue.js 系列教程 3:Vue-cli,生命周期钩子
原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...
- 树莓派4B系列教程三 :优化配置
树莓派4B系列教程三 :优化配置 写在前面 树莓派4B内存增加 CPU温度控制 显存优化 Chromuim缓存转移 优化自启程序 Chromium插件安装 离线安装插件时遇到的问题 结语 写在前面 不 ...
- 汇川技术小型PLC梯形图编程系列教程(三):PLC系统程序与用户程序介绍
原文链接:汇川技术小型PLC梯形图编程系列教程(三):PLC系统程序与用户程序介绍 PLC的定义 可编程逻辑控制器是种专门为在工业环境下应用而设计的数字运算操作电子系统.它采用一种可编程的存储器,在其 ...
- Java 多线程(三) 线程的生命周期及优先级
Java 多线程(三) 线程的生命周期及优先级 线程的生命周期 线程的生命周期:一个线程从创建到消亡的过程. 如下图,表示线程生命周期中的各个状态: 线程的生命周期可以分为四个状态: 1.创建状态: ...
- Spring框架:三种Spring Bean生命周期技术
当使用术语"生命周期"时,Spring的家伙指的是您的bean的构造和破坏,通常这与Spring Context的构造和破坏有关. 在某些情况下,Bean生命周期的管理不是一件容易 ...
- 深度:为中老年人打造三十年用户生命周期价值平台,快乐50在老年文娱教育领域“快与慢”的3年实践经验
AgeClub一直在重点研究中老年文娱教育市场的发展趋势,我们在线下已经看到越来越多具备商业变现能力接地气的创新模式正在孕育中. 中老年文娱教育市场也正在从以前边缘状态进入一个新发展阶段,越来越多的资 ...
- C#微信公众号开发系列教程三(消息体签名及加解密)
http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...
- ROS系列教程三:roslaunch文件及参数服务器
一.标签简介 1.<launch> ... </launch> : 根标签,一般写在整个launch文件的头尾,斜杠/代表结束: 2.<node> :启动节点,如果 ...
- ClickHouse系列教程三:MergeTree引擎分析
ClickHouse系列教程: ClickHouse系列教程 Clickhouse之MergeTree引擎分析 CRUD Clickhouse支持查询(select)和增加(insert),但是不直接 ...
最新文章
- Ubuntu 14.04 64bit安装IPython
- 推荐GitHub 上六大爆款AI学习项目,Star超过5.6w
- 常见的BIOS硬盘故障现象及急救措施
- Eclipse之如何快速查看抽象函数实现
- ubuntu异常关机,断电重启后进入紧急模式,挂载磁盘SSD失败了怎么办?(Failed mount on XXX)
- 阿里资深技术专家的10年感悟
- 【数字逻辑设计】Logisim构建三种多路选择器
- python:栈的理解与应用,让你快速入门Python
- 计算机科学与技术大学生职业规划,计算机科学与技术大学生职业生涯规划ppt
- AssertJ断言系列一
- JQ focus blur focusin focuseout
- 创业的两种方式,你适合哪一种?
- 1w存银行一年多少利息_一百万存银行一年利息多少?提前取出利息怎么算?
- bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑(倍增floyd)
- C++小游戏——打方块
- tuxedo客户端调用java_tuxedo调用客户端_tuxedo调用java socket_调用tuxedo
- Oracle数据库锁表查询与解锁处理详解
- 定语从句中的关系代词
- 经常见到的几个菜谱名字
- 后端返给前端的数据格式
热门文章
- 零点起飞学php下载,零点起飞学PHP(附光盘)/零点起飞学编程
- how to install tensorflow-gpu==1.12.0
- 【java】Applet显示阶乘结果
- cartographer源码编译测试之开发环境搭建全在这里了
- python saltstack_通过Python利用saltstack进行生成服务器资产清单
- hibernate oracle 读写分离_ASP.NET CORE 国产最火前后端完全分离框架BCVP
- acrobat xi pro 简体中文语言支持包_恐龙模拟新作《Paleo Pines》Steam明年发售 支持简中...
- arcgis构建金字塔失败什么原因_天猫入驻为什么失败?知舟集团给出失败原因和解决办法...
- android 图片上传java,php服务器
- laravel nginx配置_nginx高可用