ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PostgREST 上手:4 行配置把 PostgreSQL 变成 REST API

PostgREST 上手:4 行配置把 PostgreSQL 变成 REST API PostgREST 上手4 行配置把 PostgreSQL 变成 REST API【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrestPostgREST 把任意 PostgreSQL 数据库直接变成 REST API。本文用内部工单场景串起部署、权限与排查帮你解决接口怎么生成、权限怎么控、改表后怎么生效三个高频问题。3 分钟跑通先看到数据我们直接用 Docker 起一个库不折腾本地安装。跑完这三步你会在终端里看到工单数据以 JSON 返回后面再回头讲为什么。第 1 步起一个带初始库的 PostgreSQLdocker run -d --name pg_helpdesk -p 5432:5432 \ -e POSTGRES_PASSWORDpginit \ -e POSTGRES_DBhelpdesk_db \ postgres:16容器在后台跑5432 端口映射到本机。如果这个端口被占把第一个5432改成5433并记住它下面配置要同步。第 2 步建一张工单表 两个角色进容器建表、建角色并授权。这里只给匿名角色guest_read读权限登录角色api_login先不给写权限先跑通只读。docker exec -it pg_helpdesk psql -U postgrescreate schema helpdesk; create table helpdesk.tickets ( id bigserial primary key, title text not null, state text not null default open, owner text, opened_at timestamptz not null default now(), due_at timestamptz ); insert into helpdesk.tickets (title, state, owner) values (修复支付回调, open, li), (导出季度报表, closed, mei); create role guest_read nologin; grant usage on schema helpdesk to guest_read; grant select on helpdesk.tickets to guest_read; create role api_login login noinherit password Ticket#2024x9; grant guest_read to api_login;第 3 步四行配置启动curl 看结果db-uri postgres://api_login:Ticket#2024x9localhost:5432/helpdesk_db db-schemas helpdesk db-anon-role guest_read server-port 3100保存为postgrest.conf启动并请求postgrest postgrest.confStarting PostgREST 12.2.0... Successfully connected to PostgreSQL 16.x ... API server listening on port 3100另开终端请求工单curl http://localhost:3100/tickets[ {id:1,title:修复支付回调,state:open,owner:li, opened_at:2026-09-03T02:55:00Z,due_at:null}, {id:2,title:导出季度报表,state:closed,owner:mei, opened_at:2026-09-03T02:55:00Z,due_at:null} ]数据出来了。此时POST /tickets会返回 401因为匿名角色只有SELECT——这正是我们要的安全默认值。它是怎么工作的前台不决定你能进哪些房间看到效果后我们把机制讲透因为后面所有权限问题都源于它。PostgREST 像一个酒店前台它只负责验你的房卡JWT不负责决定你能进哪些房间。能进哪些房间完全由房卡对应的权限数据库角色决定而前台本人连客房都进不去。对应到代码一次请求走这条路径三个「为什么」比「是什么」更重要为什么端点自动出现端点、字段、可嵌入的关联全部来自数据库里的表、视图、函数和外键。上图里外键连着的表就变成可以嵌套查询的关联资源。你改库就等于改 API。为什么权限写在数据库里PostgREST 拿到身份后只做一件事——以该角色执行 SQL。能不能读、能改哪几列、RLS 放行哪些行都是 Postgres 判的。前端伪造参数也绕不过去因为判定发生在数据库侧。为什么业务逻辑不在服务端校验、鉴权、JSON 序列化都下推给数据库服务端基本无状态可以随意横向扩容这也是它快的原因。渐进式配置实战上面四行能跑但离生产还差两步。我们按「最小可用 → 安全加固 → 生产调优」递进每层都能直接落地。第一层最小可用内网只读已够刚才的四行就是这一层。它适合内网、只读、先让前端把数据跑起来。什么时候进入下一层一旦有外部调用、或任何人可以发起写操作就必须上 JWT 和细粒度权限否则等于裸奔。第二层安全加固写操作 行级隔离在 Layer 1 的postgrest.conf基础上追加两行把密钥和兜底行数配上jwt-secret 098f6bcd4621d373cade4e832627b4f6 db-max-rows 500密钥至少 32 字符客户端签发 JWT 要用同一个。db-max-rows给意外或恶意的大结果集兜底。再给「已登录的运营」角色agent开写权限但只放行它该动的列和它自己的行create role agent nologin; grant agent to api_login; grant usage on schema helpdesk to agent; -- 只放行该动的列id/opened_at 动不了 grant select, insert, update(title, state, owner) on helpdesk.tickets to agent; -- RLSagent 只能碰 owner 等于自己 uid 的行 alter table helpdesk.tickets enable row level security; create policy agent_own on helpdesk.tickets for all using (owner current_setting(request.jwt.claims, true)::json-uid) with check (owner current_setting(request.jwt.claims, true)::json-uid); -- 默认收回函数执行权避免 PUBLIC 能调任意函数 alter default privileges revoke execute on functions from public;带 JWT 请求时把uid放进 claimcurl http://localhost:3100/tickets -X POST \ -H Content-Type: application/json \ -H Authorization: Bearer $JWT \ -d {title:新工单,owner:li}{id:3,title:新工单,state:open,owner:li, opened_at:2026-09-03T03:00:00Z,due_at:null}为什么这样拆列级GRANT决定「能不能改这一列」RLS 决定「这一行是不是你的」两者叠加才是最小权限。ALTER DEFAULT PRIVILEGES REVOKE EXECUTE那条容易被忽略因为新函数默认对PUBLIC可执行参考 数据库授权。什么时候进入下一层要对外暴露、多前端调用、或数据库结构会频繁变更时进入生产调优。第三层生产调优连接池 自动重载 密钥管理继续在上面的postgrest.conf里追加运行时与对外参数db-pool 20 db-pool-acquisition-timeout 10 db-aggregates-enabled false server-cors-allowed-origins https://ops.example.com openapi-mode follow-privilegesdb-pool控制连接池大小默认 10高并发下调大db-aggregates-enabled保持false避免有人用max(无索引列)把库拖死CORS 只放行你自己的前端域。生产环境两个高频诉求用数据库内配置和事件触发器解决改库即生效、不用重启-- 用事件触发器自动重载 schema 缓存改完表立刻生效 create or replace function postgrest.on_ddl() returns event_trigger as $$ begin perform pg_notify(pgrst, reload schema); end $$ language plpgsql; create event trigger postgrest_ddl on ddl_command_end when tag in (CREATE TABLE,DROP TABLE,ALTER TABLE, CREATE VIEW,DROP VIEW, CREATE FUNCTION,DROP FUNCTION,ALTER FUNCTION) execute function postgrest.on_ddl();密钥别硬编码进镜像用app.settings.*从环境变量注入SQL 函数里用current_setting(app.settings.xxx)读取。完整参数语义见 配置参考。高频踩坑与排查跑起来只是开始下面是我们反复碰到的四类问题每个都按「现象 → 定位 → 修复」给解法。Q1POST 一直 401message 是 permission denied现象写操作返回 401code为42501。定位要么没带 JWT 走了匿名角色没有写权限要么带了对但角色没被GRANT。修复确认请求头带了有效Authorization确认agent已GRANT对应列且GRANT agent TO api_login。Q2改了表结构API 还是老样子或直接 404现象加列后请求新字段不返回或建了新表却 404。定位PostgREST 靠 schema 缓存它不会自己感知 DDL 变更缓存是旧的。修复killall -SIGUSR1 postgrest或库内NOTIFY pgrst, reload schema长期方案上第三层的事件触发器。详见 Schema 缓存与重载。Q3改配置没生效现象改了db-max-rows重启前不生效或改了环境变量完全无效。定位不是所有参数可热重载db-pool就不可环境变量在进程启动后改不了。修复可重载项用killall -SIGUSR2 postgrest或NOTIFY pgrst, reload configdb-pool和环境变量得重启进程容器里就直接重建。Q4分不清 401 和 403现象权限不足时到底哪个码。定位同一个 Postgres 错误42501insufficient privilegesPostgREST 会按身份映射匿名请求给 401已登录请求给 403。修复码相同但含义不同重点查角色授权而不是改状态码。完整映射见 错误码。Q5偶发慢到卡死现象某个查询把连接池占满其他人排队超时。定位大概率是无索引列上的聚合或超长结果集。修复保持db-aggregates-enabledfalse并用statement_timeout给慢查询限时。生产上线前 Checklist发布前逐条勾选任何一条没把握就先别对外db-uri用专用低权限角色连接不是postgres超级用户api_login设了NOINHERIT只被GRANT到业务角色jwt-secret不少于 32 字符与客户端一致未提交进代码库已执行ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC敏感表开启 RLS且策略带WITH CHECK写路径也受控设置了db-max-rows给大结果集兜底db-aggregates-enabled保持false配置了statement_timeout慢查询会主动断已接入自动 schema 重载事件触发器密钥走app.settings.*或 in-db 配置不写进镜像 ⚠️PostgREST 的价值在于把「写 API」这件事从应用代码挪回数据库表即端点角色即权限RLS 即边界。把这三点吃透剩下的只是把配置从四行往生产推。【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表