#postgresql #json-api #rest #exposing #response #attributes #io

app basiliq

使用JSON:API规范暴露Postgres数据库的REST API服务器

3个版本

0.1.2 2021年5月13日
0.1.1 2021年5月3日
0.1.0 2021年5月2日

#1010数据库接口

MIT/Apache

410KB
7K SLoC

Basiliq

通过REST API暴露Postgres数据库,遵循JSON:API规范。
总的来说,这是一个美味的API。

什么是Basiliq

Basiliq是一个非常原始的REST API,它通过暴露一个标准化的API来与Postgres数据库交互,从而取代了编写CRUD方法的需要。

它遵循JSON:API规范。使用Rust编写,试图在性能和稳定性之间取得平衡。

快速入门

可直接使用的示例

您可以通过Heroku试用已经部署的API。

例如


# For a very simple example
curl 'http://demo.basiliq.io/public__peoples'

# For a more complex example
curl 'http://demo.basiliq.io/public__peoples?include=public__articles,public__comments&fields\[public__comments\]='

本地运行

可以通过Docker安装basiliq。在仓库根目录下有一个示例docker-compose脚本。要启动它

# To start
docker-compose -f docker-compose.example.yml up -d

# At that point the database is empty,
# you can populate it with the following script
curl -L https://gitlab.com/basiliqio/basiliq_db_test_utils/-/jobs/artifacts/main/raw/basiliq_test.dump\?job\=pack_test_migrations | PGHOST=localhost PGUSER=postgres PGPASS=postgres psql

# Then you can restart the basiliq server so it rescans the database
docker-compose -f docker-compose.example.yml restart basiliq

# To stop
docker-compose -f docker-compose.example.yml down

理解API

如何查询

未来,应该有一种方法可以生成OpenApi文档,以便查看API的访问方式。

API响应遵循JSON:API规范

默认情况下,端点以schema__table格式暴露(即对于位于public模式中的peoples表,端点将是public__table)。

通过修改配置,可以更改这些端点的暴露方式。

示例请求

创建请求

注意请求中没有id。

此外,在响应中,未指定的字段设置为它们的默认值

POST /public__peoples HTTP/1.1
Host: demo.basiliq.io
User-Agent: curl/7.76.1
Content-Type:application/vnd.api+json
Accept: application/json, */*
Content-Length: 174

{
    "data": {
        "type": "public__peoples",
        "attributes": {
            "first-name": "Somebody",
            "last-name": "Once_told_me_the_world",
            "gender": "F",
            "twitter": "@allstars"
        }
    }
}

HTTP/1.1 201 Created
Connection: keep-alive
Content-Type: application/vnd.api+json
Content-Length: 224
Date: Sun, 02 May 2021 20:20:52 GMT

{
    "jsonapi": {
        "version": "1.0"
    },
    "data": {
        "type": "public__peoples",
        "id": "d14e1928-9cae-441c-945d-144ebe6c94c8",
        "attributes": {
            "age": null,
            "first-name": "Somebody",
            "gender": "F",
            "last-name": "Once_told_me_the_world",
            "twitter": "@allstars"
        }
    }
}
简单的获取请求
GET /public__peoples HTTP/1.1
Host: demo.basiliq.io
User-Agent: curl/7.76.1
Accept: application/json, */*

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/vnd.api+json
Content-Length: 598
Date: Sun, 02 May 2021 20:13:47 GMT

{
    "jsonapi": {
        "version": "1.0"
    },
    "data": [
        {
            "type": "public__peoples",
            "id": "1649b1e9-8a5f-4f52-b331-c07ce3bccc6f",
            "attributes": {
                "age": 22,
                "first-name": "Francis",
                "gender": "M",
                "last-name": "Le Roy",
                "twitter": null
            }
        },
        {
            "type": "public__peoples",
            "id": "777cc565-c66b-4942-ab44-8fc5f194b804",
            "attributes": {
                "age": 34,
                "first-name": "Somebody",
                "gender": "F",
                "last-name": "Wuhu",
                "twitter": "@randomhandle"
            }
        },
        {
            "type": "public__peoples",
            "id": "961e543a-4b22-4d48-a8e5-c1eafada950f",
            "attributes": {
                "age": null,
                "first-name": "AAAAAAAA",
                "gender": null,
                "last-name": "BBBBBBBBB",
                "twitter": null
            }
        }
    ]
}
包括关系和解析字段的获取请求

您可以在每个主要资源的included键下的relationships键中找到对象的属性。

注意,注释对象只有id,因为通过查询参数fields[public__comments]=未选择它们的任何字段。

GET /public__peoples?include=public__articles,public__comments&fields[public__comments]= HTTP/1.1
Host: demo.basiliq.io:80
User-Agent: curl/7.76.1
Accept: application/json, */*

HTTP/1.1 200 OK
content-type: application/vnd.api+json
content-length: 1879
date: Sun, 02 May 2021 20:08:12 GMT

{
    "jsonapi": {
        "version": "1.0"
    },
    "data": [
        {
            "type": "public__peoples",
            "id": "1649b1e9-8a5f-4f52-b331-c07ce3bccc6f",
            "attributes": {
                "age": 22,
                "first-name": "Francis",
                "gender": "M",
                "last-name": "Le Roy",
                "twitter": null
            },
            "relationships": {
                "public__articles": {
                    "data": [
                        {
                            "type": "public__articles",
                            "id": "fdf715dd-8772-498c-8196-6f4ccb64edef"
                        },
                        {
                            "type": "public__articles",
                            "id": "2dbf5d1a-b029-4456-af6b-339c75b1089c"
                        }
                    ]
                },
                "public__comments": {
                    "data": [
                        {
                            "type": "public__comments",
                            "id": "59f58abd-c9db-4074-9c34-ac33e9c838ce"
                        },
                        {
                            "type": "public__comments",
                            "id": "c2add83b-6f58-45a2-bf62-3ebc05c46192"
                        }
                    ]
                }
            }
        },
        {
            "type": "public__peoples",
            "id": "777cc565-c66b-4942-ab44-8fc5f194b804",
            "attributes": {
                "age": 34,
                "first-name": "Somebody",
                "gender": "F",
                "last-name": "Wuhu",
                "twitter": "@randomhandle"
            },
            "relationships": {
                "public__articles": {
                    "data": {
                        "type": "public__articles",
                        "id": "46c4fe50-8c56-4f26-935e-56ccfa496bb5"
                    }
                },
                "public__comments": {
                    "data": {
                        "type": "public__comments",
                        "id": "6ae9938f-d490-4707-b138-770c2a52465f"
                    }
                }
            }
        },
        {
            "type": "public__peoples",
            "id": "961e543a-4b22-4d48-a8e5-c1eafada950f",
            "attributes": {
                "age": null,
                "first-name": "AAAAAAAA",
                "gender": null,
                "last-name": "BBBBBBBBB",
                "twitter": null
            }
        }
    ],
    "included": [
        {
            "type": "public__articles",
            "id": "2dbf5d1a-b029-4456-af6b-339c75b1089c",
            "attributes": {
                "body": "Yeah I know ! Right ?!",
                "title": "Oh my g**"
            }
        },
        {
            "type": "public__articles",
            "id": "46c4fe50-8c56-4f26-935e-56ccfa496bb5",
            "attributes": {
                "body": "They feast on the blood of the departed draw their powers",
                "title": "Why devs require sacrifices"
            }
        },
        {
            "type": "public__articles",
            "id": "fdf715dd-8772-498c-8196-6f4ccb64edef",
            "attributes": {
                "body": "Yes",
                "title": "How to dead"
            }
        },
        {
            "type": "public__comments",
            "id": "59f58abd-c9db-4074-9c34-ac33e9c838ce"
        },
        {
            "type": "public__comments",
            "id": "6ae9938f-d490-4707-b138-770c2a52465f"
        },
        {
            "type": "public__comments",
            "id": "c2add83b-6f58-45a2-bf62-3ebc05c46192"
        }
    ]
}
更新请求

注意,那些未包含在 PATCH 请求中的属性不会被置为空。

PATCH /public__peoples/777cc565-c66b-4942-ab44-8fc5f194b804 HTTP/1.1
Host: demo.basiliq.io
User-Agent: curl/7.76.1
Content-Type:application/vnd.api+json
Accept: application/json, */*
Content-Length: 204

{
    "data": {
        "type": "public__peoples",
        "id": "777cc565-c66b-4942-ab44-8fc5f194b804",
        "attributes": {
            "first-name": "NotTheOriginalFirstName",
            "last-name": "NotTheOriginalLastName"
        }
    }
}

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/vnd.api+json
Content-Length: 260
Date: Sun, 02 May 2021 20:24:50 GMT

{
    "jsonapi": {
        "version": "1.0"
    },
    "data": {
        "type": "public__peoples",
        "id": "777cc565-c66b-4942-ab44-8fc5f194b804",
        "attributes": {
            "age": 34,
            "first-name": "NotTheOriginalFirstName",
            "gender": "F",
            "last-name": "NotTheOriginalLastName",
            "twitter": "@randomhandle"
        }
    }
}

删除请求
DELETE /public__peoples/777cc565-c66b-4942-ab44-8fc5f194b804 HTTP/1.1
Host: demo.basiliq.io
User-Agent: curl/7.76.1
Accept: application/json, */*

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/vnd.api+json
Content-Length: 41
Date: Sun, 02 May 2021 20:25:54 GMT

{
    "jsonapi": {
        "version": "1.0"
    },
    "data": null
}

配置

生成

通常,首先需要创建一个配置,但是运行 basiliq 并非强制。

要创建配置,可以使用

basiliq config generate

它将在当前工作目录中生成一个名为 basiliq_config.yaml 的文件。

其中有什么

此文件将如下所示

---
resources:                 # The list of resources
  public__articles:        # The name of a resource. *It can be changed*
    target:                # The identifier object of the resource
      schema: public       # The schema this resource is bound to in the database
      table: articles      # The name of the table bound to this resource
    enabled: true          # `true` if this resource is enabled
    relationships:         # A list of relationships
      public__comments:    # Name of the relationship. *It can be changed*
        target:            # The identifier object of the resource
          schema: public   # The schema this relationship's resource is bound to in the database
          table: comments  # The name of the table bound to this relationship's resource
        enabled: true      # `true` if this relationship is enabled
        field: article     # The field to which this relationship is bound
      public__peoples:
        target:
          schema: public
          table: peoples
        through:           # Identifies the bucket table for Many-to-Many relationships 
          schema: public   # The schema of the bucket resource
          table: comments  # The table of the bucket resource
          field: author    # The field linking the relationship's resource and the bucket resource
        enabled: true
        field: id
[...]

检查配置

生成配置后,在修改后可能需要确保其正确性。

可以使用以下命令来完成

basiliq config check --input basiliq_config.yaml 

测试

要测试此软件包,您需要启动一个 Postgres 数据库并导出 DATABASE_URL 环境变量。

您可以使用提供的 docker-compose 计划

# To start the test database
docker-compose -f docker-compose.testing.yml up -d

# Don't forget to set the environment variable
export DATABASE_URL="postgres://postgres:postgres@localhost/postgres"

# Run the tests
cargo test

# To stop the test database
docker-compose -f docker-compose.testing.yml down -v

依赖关系

~34–48MB
~877K SLoC