动态API
该平台的 API 使用 Database Mirroring 来动态生成 REST 端点和基于连接数据库架构的 GraphQL 模式。由于这些终结点根据特定架构和配置的权限返回数据,因此 API 的输入/输出对于单个安装有很大差异。
REST vs. GraphQL
REST 和 GraphQL 端点之间的可用功能没有区别。
两者中可用的功能都映射到同一组核心服务,这意味着您不会因选择其中一个而失去任何性能或功能。你选择哪一个最终取决于你。
认证
默认情况下,系统中的所有数据对于未经身份验证的用户都是禁止的。若要访问受保护的数据,必须 在每个请求中包含访问令牌,或 为公共角色配置权限。
相关参考资料:
关系数据
Directus 仅检索项目中明确请求的字段。关系数据可以通过使用 REST 中的 字段
参数 或 GraphQL 中的常规嵌套查询来检索。例如,这允许您检索文章数据中包含的文章作者,或获取应用程序分析数据的相关日志入口点。
创建/更新/删除
与获取类似,关系内容也可以进行深度修改。
多对一
多对一关系的关系管理相当简单。您可以简单地将所需的更改作为对象提交到集合中的关系键下。例如,如果您想在页面上创建新的特色文章,您可以提交:
{
"featured_article": {
"title": "This is my new article!"
}
}
这将在相关集合中创建一个新记录,并将其主键保存在此项目的“featured_article”字段中。要更新现有项目,只需提供更新的主键,Directus 会将其视为更新而不是创建:
{
"featured_article": {
"id": 15,
"title": "This is an updated title for my article!"
}
}
看到多对一关系将外键存储在字段本身上,可以通过使字段无效来删除该项目:
{
"featured_article": null
}
一对多(或多对多)
一对多,因此多对多和多对任意关系可以通过以下两种方式之一进行更新:
基本的
API 将返回一对多字段作为嵌套键或项的数组(基于 字段
参数)。您可以使用相同的结构来选择相关项目是什么:
{
"children": [2, 7, 149]
}
您还可以提供对象而不是主键,以便创建动态嵌套的新项,或者提供包含主键的对象以更新现有项:
{
"children": [
2, // assign existing item 2 to be a child of the current item
{
"name": "A new nested item"
},
{
"id": 149,
"name": "Assign and update existing item 149"
}
]
}
要从此关系中删除项目,只需从数组中省略它们:
{
"children": [2, 149]
}
这种更新一对多的方法对于较小的关系数据集非常有用。 “详细的” 或者,您可以提供一个详细说明更改的对象,如下所示:
{
"children": {
"create": [{ "name": "A new nested item" }],
"update": [{ "id": 149, "name": "A new nested item" }],
"delete": [7]
}
}
如果您需要更严格地控制分阶段更改,或者当您使用大型关系数据集时,这非常有用。
多对任意(联合类型)
多对任意字段的工作方式与“常规”多对多字段非常相似,不同之处在于相关字段可以从任何相关集合中提取字段,例如:
{
"sections": [
{
"collection": "headings",
"item": {
/* headings fields */
}
},
{
"collection": "paragraphs",
"item": {
/* paragraphs fields */
}
}
]
}
REST API
要限定每个集合类型返回的字段,您可以在 fields 参数中使用 <field>:<scope>
语法,如下所示:
GET /items/pages
?fields[]=sections.item:headings.id
&fields[]=sections.item:headings.title
&fields[]=sections.item:paragraphs.body
&fields[]=sections.item:paragraphs.background_color
GraphQL
在 GraphQL 中,您可以使用联合类型上的嵌套片段来选择字段:
query {
pages {
sections {
item {
... on headings {
id
title
}
... on paragraphs {
body
background_color
}
}
}
}
}
Updating
在多对任意关系中更新记录与其他关系类型相同。
SEARCH HTTP 方法
当使用 REST API 通过(非常)高级过滤器读取多个项目时,您可能会遇到 URL 无法容纳足够数据以包含完整查询结构的问题。在这些情况下,您可以使用 SEARCH HTTP 方法作为 GET 的替代方法,您可以将查询放入请求正文中,如下所示:
之前:
GET /items/articles?filter[title][_eq]=Hello World
现在:
SEARCH /items/articles
{
"query": {
"filter": {
"title": {
"_eq": "Hello World"
}
}
}
}
关于是否将正文放在GET请求中,使用POST创建搜索查询或完全依赖其他方法,有很多讨论。截至目前,我们已经选择了与IETF的 HTTP SEARCH Method 规范保持一致。虽然我们认识到这仍然是一个规范草案,但SEARCH方法之前已经在WebDAV世界中广泛使用(spec),并且与其他可用选项相比,它感觉像是“最干净”和最正确的处理这一过程。与其他任何事情一样,如果您有任何想法,意见或疑虑,我们很乐意听到您的想法。
相关阅读:
- HTTP SEARCH Method (IETF, 2021)
- Defining a new HTTP method: HTTP SEARCH (Tim Perry, 2021)
- HTTP GET with request body (StackOverflow, 2009 and ongoing)
- Elastic Search GET body usage (elastic, n.d.)
- Dropbox starts using POST, and why this is poor API design. (Evert Pot, 2015)
GraphQL 中的系统数据
由于 GraphQL 本身的限制,不可能从常规数据访问中正确确定范围/命名空间系统功能的范围。为了防止用户创建的数据和系统数据之间的任何命名冲突,我们将两者的访问范围分别限定为用户和系统数据的单独端点:/graphql
和/graphql/system
。两个终结点共享相同的基础架构,因此无论嵌套关系是否在用户和系统数据之间“交叉”,嵌套关系都将按预期工作这两个终结点的唯一区别是可用的根查询和突变字段。
错误代码
以下是Directus中使用的全局错误代码及其含义。
错误代码 | HTTP状态 | 描述 |
---|---|---|
FAILED_VALIDATION | 400 | 此特定项目的验证失败 |
FORBIDDEN | 403 | 不允许您执行当前操作 |
INVALID_TOKEN | 403 | 提供的令牌无效 |
TOKEN_EXPIRED | 401 | 提供的令牌有效但已过期 |
INVALID_CREDENTIALS | 401 | 用户名/密码或访问令牌错误 |
INVALID_IP | 401 | 您的 IP 地址未列入此用户的允许列表 |
INVALID_OTP | 401 | 提供了错误的 OTP |
INVALID_PAYLOAD | 400 | 提供的有效载荷无效 |
INVALID_QUERY | 400 | 请求的查询参数不能使用 |
UNSUPPORTED_MEDIA_TYPE | 415 | 不支持提供的有效负载格式或“Content-Type”标头 |
REQUESTS_EXCEEDED | 429 | 达到速率限制 |
ROUTE_NOT_FOUND | 404 | 端点不存在 |
SERVICE_UNAVAILABLE | 503 | 无法使用外部服务 |
UNPROCESSABLE_ENTITY | 422 | 你试图做一些非法的事情 |
安全
为防止泄露哪些项目存在,对不存在项目的所有操作都将返回FORBIDDEN
错误。