当前位置: 首页 > 工具软件 > PostgREST > 使用案例 >

PostgREST入门_数据库直接发布为restful api

郭麒
2023-12-01

介绍

postgresql开源数据库的优点很多,尤其是有postgis,使用范围也越来越广。
发现了一套牛X的技术PostgREST,可以将pg数据库直接发布为restful api,
也就是说有很多的后台数据库逻辑不用重复写了,直接前端就可以请求数据。
除了开发效率提高,数据访问操作的效率也会提高。
这套技术目前影响力越没有达到应有的水平,尤其是国内宣传和研究了解的不够。
我建一个群方便大家共同交流,Q群号:816402008
点击链接加入群聊【PostgREST api学习】:https://jq.qq.com/?_wv=1027&k=5lToqel

更新: 增加了一个完整功能的DEMO

官网

postgrest.org 可以选中文文档(部分汉化)

安装

1.安装postgresql数据库(可用已有数据库)
2.按照文档中教程0,下载解压注册pg的path(否则可能找不到dll)。
3.在psql中新建数据库表和用户权限,新建文本编辑配置文件(连接字符串,角色),运行。
4.浏览器访问返回json

axios访问

引入

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

get

		// get表内全部数据
		  axios.get("http://xxxxx:3000/todos")
		  .then(response =>{this.results = response.data;
		  console.log(response.data)});

post

//		//插入2行数据。插入值为对象,未填入为默认值
//		axios.post("http://xxxxx:3000/todos", [
//		{"task": "1","sid" : 3542,"name":"xxx","type":"xx","address":"xxxx"},
//		{"task": "2","sid" : 3543,"name":"xxx","type":"xx","address":"xxxx"},
//		
//		])
//			.then(response => {
//				console.log(response)//成功回调
//			}, res => {
//				console.log(res)//失败回调
//			});

示例程序

https://github.com/subzerocloud/postgrest-starter-kit
PostgREST支持构建数据驱动的API后端的不同方式。它确实“一件好事”就是为您提供数据库上的REST api,然而构建一个复杂的生产系统,可以与第三方系统交谈,发送电子邮件,实现浏览器的实时更新,编写集成测试,实现身份验证,您需要其他组件。出于这个原因,一些开发人员要么提交不属于PostgREST范围的功能请求,要么将其视为原型实用程序而不是具有出色性能的强大/灵活的生产组件。该存储库旨在成为所有基于PostgREST的项目的起点,并将所有组件集中在一个定义良好的结构中。我们还提供工具,帮助您迭代项目和工具/脚本,以使构建管道能够将所有内容推向生产。堆栈中有相当多的组件,但如果您不需要它们提供的功能/特性,您可以安全地在docker-compose.yml中注释掉pg_amqp_bridge / rabbitmq(甚至是openresty)实例

文章(机翻):别在称呼PostgRest为魔法了

https://medium.freecodecamp.org/stop-calling-postgrest-magic-8f3e1d5e5dd1
虽然开发人员对他们的工作有“魔力”感到讨人喜欢,但对于采用PostgREST可能会有害。魔术意味着未知,人们害怕未知。让我们花10分钟来了解它在内部的运作方式。

2年前我开始为 PostgREST核心做贡献。从那时起,我一直在检查人们对此的看法。有两个营地。顽固的球迷称之为“魔术”,并准备联合非信徒。然后你有怀疑论者。

这个叙述涉及怀疑论者阵营。它源于人们不了解PostgREST如何运作的事实!

这一切都很简单,很漂亮。

(REST)URL中的内容?
我们来看看这个例子吧

GET / items / 1
如果你剥离一切,比如身份验证和授权,剩下的本质就是这个

SELECT * FROM items WHERE id = 1
PostgREST接受HTTP请求,查看它,将其转换为SQL并执行它。这几乎就是它的全部内容。这是一个很大的纯功能。我希望我不会因为滥用符号而被Haskell人钉死在十字架上而忽略了实际的IO正在进行中。

postgrest :: Schema - > HTTP - > SQL
这是一个稍微复杂的例子:

GET /items?选择= id,name&id = gt.10&order = name
被翻译成

SELECT id,name FROM items WHERE id> 10 ORDER BY name
三个神奇的成分✨
PostgREST的构建核心概念,它们周围的一切都只是钟声和口哨。如果你了解它们,你就会明白PostgREST。

JSON编码
Joe Nelson的第一个好主意是认识到PostgreSQL可以对JSON编码响应。现在你可能会想“为什么人们想要这样做,对最难扩展的组件施加更多负担?”

嗯,这是原因。

PostgreSQL JSON编码器速度快,速度快。你的反应越大,增益就越大。它可以比ActiveRecord快2倍/ 10倍,对于大响应也可以是160倍。

让我们思考一下。除了让数据库做更多的工作之外,让数据库返回最终响应的含义是什么?

无论坐在数据库前面的什么,都不再需要反序列化来自数据库的响应,并将其转换为该数据语言的内部表示。然后,在数据在内存中之后,它不需要序列化回JSON。这意味着在出路时,您的代码不需要执行任何操作,只需传递从数据库获取的任何内容。

我们将一些负载从应用程序代码转移到数据库。这对于强大的PostgreSQL来说并不算什么,它不是繁重的开心所在。如果我们查看整个系统,我们通过删除一个序列化/反序列化步骤减少了需要完成的工作总量。这是为什么PostgREST如此之快的秘诀之一。它让大家伙做到了。

让我们看一下SQL中的实际情况。此查询与PostgREST生成的查询类似。

WITH essence AS(
SELECT id,name FROM items WHERE id> 10 ORDER BY name

SELECT
coalesce(
array_to_json(array_agg(row_to_json(response))),
‘[]’
):: character vary AS BODY
FROM(SELECT * FROM essence)响应
我们已经包装了essence查询。另一方面,我们将结果作为单行获取,其中一列BODY包含JSON响应。简单!

身份验证/授权
这是大多数新手在第一次遇到PostgREST时遇到麻烦的部分。他们有(完全自然的)问题:“PostgREST如何实现身份验证/授权?”。

简短的回答是,它没有。

再一次,乔的一个很好的想法,我甚至说它比JSON编码更基础。

PostgreSQL拥有丰富的角色系统。结合视图和行级安全性(RLS)等功能,您可以对数据的访问进行细粒度控制,直至单个单元格。然而,人们将他们的数据库视为“哑数据存储”。更糟糕的是,他们使用具有管理员权限的角色连接到他们。

如果应用程序连接到数据库的角色只具有特定表和行的权限,那么SQL注入攻击的重点是什么?在最坏的情况下,攻击者将删除自己的数据。但我很离题…

当第一个PostgREST连接到数据库时,它使用我们通常调用的角色连接到它authenticator。除了登录功能之外,该角色没有附加任何特权。

每当经过身份验证的请求时,并且有一个Authorization包含JWT的令牌头,PostgREST将解码的令牌,验证它使用的密钥是有效的,并期待在它的有效载荷称为特定领域role. 假设role 具有的价值alice。

这意味着此请求需要以特权执行alice。要做到这一点,我们使用一个PostgreSQL整洁的小技巧。您可以切换当前用户,有点像做sudo alice. ,甚至更好,您可以在事务的上下文中执行此操作,因此一个请求不会干扰另一个请求。我们没有创建新的数据库连接,这发生在同一个连接中。虽然alice 是数据库角色,但它没有登录权限。

以下是事情发生的顺序:

开始;
设置本地角色’alice’;

  • 主查询到这里
    COMMIT;
    这并不意味着PostgREST切换到它喜欢的任何东西。为此,您必须明确说明authenticator角色有权通过以下方式承担alice角色:

GRANT alice TO认证者;
就这样,PostgREST通过利用底层数据库角色系统获得了授权的能力。这种方法的意义和优势是巨大的。

PostgREST代码库仍然小而简单。您可以使用SQL声明每个用户的权限,而不会出现任何丑陋的命令性代码。并且,无论将来的代码访问数据库,都会始终应用规则。

另外还有一个很大的优点,不是很明显。

在构建API的传统方式中,当请求进入时,您开始检查当前用户是否有权访问该信息。这意味着额外的查询。这些类型的查询在请求总体延迟和数据库负载方面发挥着重要作用。这给人的印象是数据库速度慢,不能很好地扩展。

通过给PostgreSQL全面了解谁发出查询(角色),他的权限(授权)和他的限制(RLS),查询计划员可以做得更好,利用所有索引,甚至随着时间的推移变得更快。

提出的第一个反对意见是,每个应用程序用户都需要具有数据库角色,这不是一个非常好的设计。他们是对的,但这不是PostgREST要求你做的事情。您可以使用数据库角色来设置用户组(管理员,员工,客户),然后使用RLS 根据用户名,ID或电子邮件指定用户规则。

资源嵌入
您可能会觉得虽然PostgREST有一个很好的身份验证和暴露REST端点的解决方案,但它只是您的基本CRUD功能。这对于现代API来说还不够。毕竟,这就是为什么我们有像GraphQL这样的东西。

你是对的,如果它只是基本的CRUD那么它将是一个很好的原型设计或简单项目的工具。但是PostgREST还有最后一招,我很自豪地称这是我最大的贡献。诀窍是&select=参数。它不仅允许您指定要从表中返回的列,还可以请求相关资源:

GET / items?select = id,name,subitems(id,name)
如果你()用{}眼睛替换并眯眼,你几乎可以看到GraphQL。当从数据库中获取数据时,PostgREST接口与GraphQL的表达能力相当。

它花了我们一个完整的核心重写,然后一年使所有路径的接口统一。但我们终于到了那里。

那怎么办?

在第一次启动时,PostgREST 在您的数据库上运行一堆查询。这是为了了解您所定义的外键所在的实体以及它们之间的关系。在此之后,每当你说它subitems(…)知道items表subitems通过一个被调用的外键与表相关时item_id。基于该信息,它知道如何生成正确的连接查询。这适用于父母关系和多对多。

一个简化的(本质)查询看起来像这样

SELECT
items.id,items.name,
COALESCE(

SELECT array_to_json(array_agg(row_to_json(subitems)))
FROM(
SELECT subitems.id,subitems.name
FROM
subitems WHERE subitems.item_id = items.id
)subitems
),
'[] ’
)作为子项目
FROM项目
首先看一下可能会认为这是非常低效的,因为它似乎为每个项目行做了一个子选择,但是我们使用PostgreSQL并且它是非常棒的查询计划器,它知道你实际要求的是什么而且它已经得到了回报。不要害怕加入和分选。

一旦显示此查询并解释查询规划器知道如何正确处理它,我收到了类似的响应

“哈哈,是的,你依赖于查询优化器的怜悯。”

我会在任何一天接受这一点,非常感谢你!

我将依赖于拥有PHD的人20多年开发的软件。我没有傲慢地认为我的循环是PostgreSQL查询优化器的优秀技术。for

但为什么(我们需要PostgREST)??
现在如果你跟着并了解事情如何结合在一起,你可能会想:

“所有PostgREST都会生成一个SQL查询,将其包含在具有某些上下文的事务中并执行它。为什么我不跳过中间人,编写一个脚本,将原始SQL作为输入并做同样的事情?“
你可以做到这一点。实际上,没有人能够访问他们不应该访问的数据,并且事情会好一段时间。然后,有一天晚上你会醒来发出数据库已关闭的警报。经过一番调查,你会发现这个查询是罪魁祸首:

SELECT
crypt(
encode(digest(gen_random_bytes(1024),‘sha512’),‘base64’),
gen_salt(‘bf’,20)

FROM generate_series(1,1000000 )
WT#!

更糟糕的是,我不需要任何表的任何权限来运行此查询!

尽管如此,PostgreSQL并不是为了转移拒绝服务(DoS)攻击而构建的。这是PostgREST为您节省的地方。它在向客户端暴露大量SQL灵活性之间取得平衡,但却限制了防止恶意查询的能力。它不会允许随意加入,只应该对他们有适当的索引外键定义的值。

做好一件事?
所以你卖了!你已经下载了二进制文件,指向你的数据库和BAM!你有一个REST API!事情正在发生变化。大多数API需求都包含在内。然后你得到几个最后的位来实现,突然你停止!

“我如何用这个东西发送电子邮件?如何在用户登录时调用此第三方API?我该如何编写测试?

该死的,我知道这是个坏主意!嘿PostgREST开发者,你能帮助我实现这个功能吗?“

而你最有可能获得的答案是“你不需要它”(YAGNI)。那不是因为我们是#$%#。这是因为PostgREST是你的堆栈的一个组件,它不是“堆栈”。它有一个单一的工作,它试图做得很好。就它而言,它不会完全取代你最喜欢的后端MVC框架。但是在PostgreSQL,OpenResty,RabbitMQ等朋友的帮助下,它会为您做到这一点并取得很好的效果。查看入门套件,看看它是如何适应堆栈的。

您将不再编写API,您将定义和配置它们。

超越REST?
最近,前端社区被React和GraphQL热潮所接管,这是有充分理由的。似乎REST很快就会落后,将PostgREST与它一起使用。然而,这里的想法超越了REST,它是你用来与PostgREST交流的协议。

你可能听说过PostGraphQL。它基于相同的想法,具有完全不同的实现。该作者还顶部PostgREST贡献者之一。受PostgREST的启发和PostgREST社区内关于GraphQL的讨论,他决定自己动手。

我决定采取不同的路线。我使用了PostgREST并在其上构建了GraphQL,而不是在另一种语言中重新实现相同的逻辑。毕竟,这从一开始就是我的目标。将PostgREST功能构建到可支持GraphQL的程度。

这是一个漫长的旅程,为您的数据库开发我的原创想法subZero,一个GraphQL和REST API。但是我一路上学到了很多东西。

以subZero为旋转。我希望我们开发的其他软件对您有用。

请享用!

 类似资料: