API

查看源码

查看 代码示例

编写 API 接口 JSON 描述文件,将其放置在应用 apis 目录中,运行 yao start 命令启动服务时,引擎将按接口描述的定义,生成 RESTFul API 接口。 Yao 当前支持 RESTFul API 描述 MQTT、Socket、WEB Socket API ; 用于数据归集对接、即时通信、IoT 等类型的项目。

命名规范

业务接口描述文件是以 小写英文字母 + .协议名称 + .json 扩展名命名的 JSON 文本文件, <name>.<protocol>.json;

文件夹 (相对业务接口根目录)文件名接口名称API 类型
/name.http.yaonamehttp RESTFul API
/groupname.http.yaogroup.namehttp RESTFul API
/group1/group2name.http.yaogroup1.group2.namehttp RESTFul API
/name.mqtt.yaonamemqtt MQTT API
/groupname.mqtt.yaogroup.namemqtt MQTT API
/group1/group2name.mqtt.yaogroup1.group2.namemqtt MQTT API
/name.sock.yaonamesock Socket API
/groupname.sock.yaogroup.namesock Socket API
/group1/group2name.sock.yaogroup1.group2.namesock Socket API
/name.ws.yaonamews WEB Socket API
/groupname.ws.yaogroup.namews WEB Socket API
/group1/group2name.ws.yaogroup1.group2.namews WEB Socket API

各协议规范文档

协议名称文档地址
httpRESTFul API
mqttMQTT API 尚未实现
sockSocket API (内测中)
wsWEB Socket API (内测中)

一个 http 协议的接口(API)文档,可以定义一组 API,可以在每个 API 中绑定一个处理器(process), 系统自动调用处理器,返回处理器调用结果;

字段类型说明必填项
nameStringAPI 呈现名称,用于开发平台呈现
versionString版本号,用于依赖关系校验和开发平台呈现
descriptionStringAPI 介绍,用于开发平台呈现
groupStringAPI 分组名称,访问时作为 API 路由前缀目录。 /api/<group>/<path>
guardStringAPI 全局中间件,多个用 "," 分割。除特别声明,组内所有 API 都将使用全局中间件
pathsArray\<Object Path>API 列表。具体查看 Object Path 数据结构

Object Path 数据结构

API 将通过路由 /api/<group>/<path>访问, 请求成功响应 out 中定义的状态码、Content-Type 和处理器(process)返回值, 请求失败响应异常状态码和 JSON 格式的错误消息 查看异常规范

字段类型说明必填项
pathStringAPI 路由名称。完整路由地址为 /api/<group>/<path> ,变量使用 : 声明,如 /api/user/find/:id, 可以使用 $param.id 访问路由请求参数
methodString请求类型。许可值 GETPOSTPUTDELETEHEADOPTIONSAny. 其中 Any 将响应任何类型的请求
guardStringAPI 中间件. 如不设置,默认使用全局中间件。如不希望使用全局中间件,可将数值设置为 -
processString调用处理器 process
inArray\<String>请求参数表,将作为 process 的输入参数(args)。可以引用传入参数,可以为空数组 查看输入参数
outObject Out请求响应结果定义。 具体查看 Object Out 数据结构
errObject Out自定义调用失败时的响应结果。 尚未实现

Object Out 数据结构

字段类型说明必填项
statusinteger请求响应状态码
typeString请求响应 Content Type
headersArray\<String>请求响应 Headers 尚未实现

输入参数

in 中定义的参数表,将作为处理器的输入参数。支持使用 :param:payload$param.字段名称 等变量,绑定请求参数。

数值

数值说明
"'字符串'"字符串格式数值, 单引号使用 \ 转义
"数字"数字格式数值

变量

变量类型说明
":body"stringRequest Body
":fullpath"string路由完整路径
":payload"[key:String]:Any如果 Request Content-Type 为 application/json ,视为 Reqest Body 为 JSON。返回解码后的 Key-Value Object
":query"[key:String]:AnyURL-encoded Query String 解析后的数值
":form"[key:String]:AnyPOST form
":query-param"Object QueryParam解析 URL-encoded Query String,返回 QueryParam 查看数据结构(../../model#3-查询参数-queryparam)
"$form.字段名称"StringPOST form 字段数值
"$param.字段名称"String路由变量数值
"$query.字段名称"StringURL-encoded Query String 字段数值
"$payload.字段名称"Anypayload 字段数值,支持多级访问。如 $payload.user.name , $payload.manus.0.name
"$session.字段名称"AnySession 会话字段数,支持多级访问。如 $session.user.name , $session.manus.0.name 值
"$file.字段名称"Object File上传临时文件结构

Object File 数据结构

字段类型说明
nameString文件名
tempfileString临时文件地址
sizeInteger文件大小
header[key:String]:Array\<String>MIME-style header mapping
URL Query String 与 QueryParam 对照表
Query StringQueryParam说明
select=field1,field2{"select":["field1","field2"]}选择字段
with=rel1,rel2{"withs":{"rel1":{}, "rel2":{}}}关联关系
rel1.select=field1,field2{"withs":{"rel1":{"select":["field1", "field2"]}}}关联模型选择字段. 规范为 关联关系.select
where.status.eq=enabled{"wheres":[{"column":"status", "op":"eq", "method":"where", "value":"enabled"}]}Where 查询条件,文档. 规范为 where.字段名称.匹配关系
where.mother.friends.status.eq=enabled{"wheres":[{"rel":"user_mother_friends","column":"status", "op":"eq", "method":"where", "value":"enabled"}]}指定关联模型字段 规范为 where.关系名称.关联模型名称.字段名称.匹配关系
group.types.where.type.eq=admin&group.types.orwhere.type.eq=staff{"wheres":[{"wheres":[{"column":"type", "op":"eq", "method":"where", "value":"admin"}]},{"column":"type", "op":"eq", "method":"orwhere", "value":"staff"}]}]}Where 分组查询,一般用于 orwhere. 规范为 group.分组名称.where.字段名称.匹配关系
order=id.desc,name{"orders":[{"column":"id","option":"desc"}, {"column":"name"}]}排序条件. 规范为 字段名称.排序方式 多个用","分割

异常规范

{
"code": 500,
"message": "ID=12的数据不存在",
"context": {
"field": "id"
}
}
字段类型说明
codeInteger错误码
messageString错误描述
contextAny异常上下文信息

HTTP Response 状态码

返回状态与错误码一致,如 HTTP Response 状态码为 400~599 则视为程序处理异常。

错误码定义

错误码含义,基本与 HTTP 协议状态码含义一致,便于 RESTFul API 编写、统一异常处理和工程师理解错误码含义。

错误码适用场景
400~499因输入数据错误,导致程序运行失败
500~599因服务端资源不足或程序错误异常,导致程序运行失败
400因输入数据不符合要求, 导致程序运行失败。应在上下文数据中描述具体不符合要求的数据字段。
401因尚未登录, 导致程序运行失败。
403因访问权限不足, 导致程序运行失败。应在上下文数据中描述具体权限要求信息。
404因查询资源不存在, 导致程序运行失败。应在上下文数据中描述资源名称和数据 ID。
413因输入数据越界,导致程序运行失败。
500因服务端异常,导致程序运行失败。应在上下文数据中描述具体错误数据。例如: 因磁盘空间不足等原因导致的,文件写入失败.
503服务器暂时无法访问,导致程序运行失败。比如: MySQL server has gone away!
504因连接超时,导致程序运行失败。比如: MySQL server connect timeout!

使用guard

在请求 api 中使用 gurad,类似于使用中间件过滤请求,拦截一些不满足条件的请求,在定义 api 的时候指定 guard 字段所使用的处理器即可

使用系统自带的 guard bearer-jwt

指定整个分组 api 都要验证登录

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"guard": "bearer-jwt",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

单独指定一个接口需要验证登录

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"guard": "bearer-jwt",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

示例:

编写一个接口描述文件 apis/select.http.yao,指定接口路径、请求方式以及绑定的处理器,放置在应用的 apis 目录中。

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"guard": "-",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

新建flows/category.flow.yao文件:

{
"label": "类目树",
"version": "1.0.0",
"description": "类目树",
"nodes": [
{
"name": "类目",
"engine": "xiang",
"query": {
"select": ["id", "name", "name as label", "id as value", "parent_id"],
"wheres": [{ ":deleted_at": "删除", "=": null }],
"from": "category",
"limit": 1000
}
},
{
"name": "类目树",
"process": "xiang.helper.ArrayTree",
"args": ["{{$res.类目}}", { "parent": "parent_id" }]
}
],
"output": "{{$res.类目树}}"
}

调用 127.0.0.1/api/select/category

API

查看源码

查看 代码示例

编写 API 接口 JSON 描述文件,将其放置在应用 apis 目录中,运行 yao start 命令启动服务时,引擎将按接口描述的定义,生成 RESTFul API 接口。 Yao 当前支持 RESTFul API 描述 MQTT、Socket、WEB Socket API ; 用于数据归集对接、即时通信、IoT 等类型的项目。

命名规范

业务接口描述文件是以 小写英文字母 + .协议名称 + .json 扩展名命名的 JSON 文本文件, <name>.<protocol>.json;

文件夹 (相对业务接口根目录)文件名接口名称API 类型
/name.http.yaonamehttp RESTFul API
/groupname.http.yaogroup.namehttp RESTFul API
/group1/group2name.http.yaogroup1.group2.namehttp RESTFul API
/name.mqtt.yaonamemqtt MQTT API
/groupname.mqtt.yaogroup.namemqtt MQTT API
/group1/group2name.mqtt.yaogroup1.group2.namemqtt MQTT API
/name.sock.yaonamesock Socket API
/groupname.sock.yaogroup.namesock Socket API
/group1/group2name.sock.yaogroup1.group2.namesock Socket API
/name.ws.yaonamews WEB Socket API
/groupname.ws.yaogroup.namews WEB Socket API
/group1/group2name.ws.yaogroup1.group2.namews WEB Socket API

各协议规范文档

协议名称文档地址
httpRESTFul API
mqttMQTT API 尚未实现
sockSocket API (内测中)
wsWEB Socket API (内测中)

一个 http 协议的接口(API)文档,可以定义一组 API,可以在每个 API 中绑定一个处理器(process), 系统自动调用处理器,返回处理器调用结果;

字段类型说明必填项
nameStringAPI 呈现名称,用于开发平台呈现
versionString版本号,用于依赖关系校验和开发平台呈现
descriptionStringAPI 介绍,用于开发平台呈现
groupStringAPI 分组名称,访问时作为 API 路由前缀目录。 /api/<group>/<path>
guardStringAPI 全局中间件,多个用 "," 分割。除特别声明,组内所有 API 都将使用全局中间件
pathsArray\<Object Path>API 列表。具体查看 Object Path 数据结构

Object Path 数据结构

API 将通过路由 /api/<group>/<path>访问, 请求成功响应 out 中定义的状态码、Content-Type 和处理器(process)返回值, 请求失败响应异常状态码和 JSON 格式的错误消息 查看异常规范

字段类型说明必填项
pathStringAPI 路由名称。完整路由地址为 /api/<group>/<path> ,变量使用 : 声明,如 /api/user/find/:id, 可以使用 $param.id 访问路由请求参数
methodString请求类型。许可值 GETPOSTPUTDELETEHEADOPTIONSAny. 其中 Any 将响应任何类型的请求
guardStringAPI 中间件. 如不设置,默认使用全局中间件。如不希望使用全局中间件,可将数值设置为 -
processString调用处理器 process
inArray\<String>请求参数表,将作为 process 的输入参数(args)。可以引用传入参数,可以为空数组 查看输入参数
outObject Out请求响应结果定义。 具体查看 Object Out 数据结构
errObject Out自定义调用失败时的响应结果。 尚未实现

Object Out 数据结构

字段类型说明必填项
statusinteger请求响应状态码
typeString请求响应 Content Type
headersArray\<String>请求响应 Headers 尚未实现

输入参数

in 中定义的参数表,将作为处理器的输入参数。支持使用 :param:payload$param.字段名称 等变量,绑定请求参数。

数值

数值说明
"'字符串'"字符串格式数值, 单引号使用 \ 转义
"数字"数字格式数值

变量

变量类型说明
":body"stringRequest Body
":fullpath"string路由完整路径
":payload"[key:String]:Any如果 Request Content-Type 为 application/json ,视为 Reqest Body 为 JSON。返回解码后的 Key-Value Object
":query"[key:String]:AnyURL-encoded Query String 解析后的数值
":form"[key:String]:AnyPOST form
":query-param"Object QueryParam解析 URL-encoded Query String,返回 QueryParam 查看数据结构(../../model#3-查询参数-queryparam)
"$form.字段名称"StringPOST form 字段数值
"$param.字段名称"String路由变量数值
"$query.字段名称"StringURL-encoded Query String 字段数值
"$payload.字段名称"Anypayload 字段数值,支持多级访问。如 $payload.user.name , $payload.manus.0.name
"$session.字段名称"AnySession 会话字段数,支持多级访问。如 $session.user.name , $session.manus.0.name 值
"$file.字段名称"Object File上传临时文件结构

Object File 数据结构

字段类型说明
nameString文件名
tempfileString临时文件地址
sizeInteger文件大小
header[key:String]:Array\<String>MIME-style header mapping
URL Query String 与 QueryParam 对照表
Query StringQueryParam说明
select=field1,field2{"select":["field1","field2"]}选择字段
with=rel1,rel2{"withs":{"rel1":{}, "rel2":{}}}关联关系
rel1.select=field1,field2{"withs":{"rel1":{"select":["field1", "field2"]}}}关联模型选择字段. 规范为 关联关系.select
where.status.eq=enabled{"wheres":[{"column":"status", "op":"eq", "method":"where", "value":"enabled"}]}Where 查询条件,文档. 规范为 where.字段名称.匹配关系
where.mother.friends.status.eq=enabled{"wheres":[{"rel":"user_mother_friends","column":"status", "op":"eq", "method":"where", "value":"enabled"}]}指定关联模型字段 规范为 where.关系名称.关联模型名称.字段名称.匹配关系
group.types.where.type.eq=admin&group.types.orwhere.type.eq=staff{"wheres":[{"wheres":[{"column":"type", "op":"eq", "method":"where", "value":"admin"}]},{"column":"type", "op":"eq", "method":"orwhere", "value":"staff"}]}]}Where 分组查询,一般用于 orwhere. 规范为 group.分组名称.where.字段名称.匹配关系
order=id.desc,name{"orders":[{"column":"id","option":"desc"}, {"column":"name"}]}排序条件. 规范为 字段名称.排序方式 多个用","分割

异常规范

{
"code": 500,
"message": "ID=12的数据不存在",
"context": {
"field": "id"
}
}
字段类型说明
codeInteger错误码
messageString错误描述
contextAny异常上下文信息

HTTP Response 状态码

返回状态与错误码一致,如 HTTP Response 状态码为 400~599 则视为程序处理异常。

错误码定义

错误码含义,基本与 HTTP 协议状态码含义一致,便于 RESTFul API 编写、统一异常处理和工程师理解错误码含义。

错误码适用场景
400~499因输入数据错误,导致程序运行失败
500~599因服务端资源不足或程序错误异常,导致程序运行失败
400因输入数据不符合要求, 导致程序运行失败。应在上下文数据中描述具体不符合要求的数据字段。
401因尚未登录, 导致程序运行失败。
403因访问权限不足, 导致程序运行失败。应在上下文数据中描述具体权限要求信息。
404因查询资源不存在, 导致程序运行失败。应在上下文数据中描述资源名称和数据 ID。
413因输入数据越界,导致程序运行失败。
500因服务端异常,导致程序运行失败。应在上下文数据中描述具体错误数据。例如: 因磁盘空间不足等原因导致的,文件写入失败.
503服务器暂时无法访问,导致程序运行失败。比如: MySQL server has gone away!
504因连接超时,导致程序运行失败。比如: MySQL server connect timeout!

使用guard

在请求 api 中使用 gurad,类似于使用中间件过滤请求,拦截一些不满足条件的请求,在定义 api 的时候指定 guard 字段所使用的处理器即可

使用系统自带的 guard bearer-jwt

指定整个分组 api 都要验证登录

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"guard": "bearer-jwt",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

单独指定一个接口需要验证登录

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"guard": "bearer-jwt",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

示例:

编写一个接口描述文件 apis/select.http.yao,指定接口路径、请求方式以及绑定的处理器,放置在应用的 apis 目录中。

{
"name": "下拉搜索",
"version": "1.0.0",
"description": "下拉搜索",
"guard": "-",
"group": "select",
"paths": [
{
"path": "/category",
"method": "GET",
"process": "flows.category",
"in": [],
"out": {
"status": 200,
"type": "application/json"
}
}
]
}

新建flows/category.flow.yao文件:

{
"label": "类目树",
"version": "1.0.0",
"description": "类目树",
"nodes": [
{
"name": "类目",
"engine": "xiang",
"query": {
"select": ["id", "name", "name as label", "id as value", "parent_id"],
"wheres": [{ ":deleted_at": "删除", "=": null }],
"from": "category",
"limit": 1000
}
},
{
"name": "类目树",
"process": "xiang.helper.ArrayTree",
"args": ["{{$res.类目}}", { "parent": "parent_id" }]
}
],
"output": "{{$res.类目树}}"
}

调用 127.0.0.1/api/select/category