PostgREST 是什么
PostgREST 能把 PostgreSQL 数据库直接封装成符合 RESTful 规范的 API 服务器。你无需再写一层 Node/Go 服务,只要约定好角色权限、视图和函数,它会自动完成:
- 按照表/视图结构生成标准的 CRUD 接口;
- 基于 SQL 权限模型实现细粒度的访问控制;
- 支持过滤、排序、分页、多表关联等查询;
- 集成 JWT 鉴权用于多租户或行级安全(RLS)。
这篇笔记介绍如何快速搭建、配置 JWT、梳理常用查询操作符,以及一些上线经验。
Docker Compose 快速启动
version: '3'
services:
db:
image: postgres:16
environment:
POSTGRES_DB: appdb
POSTGRES_USER: admin
POSTGRES_PASSWORD: change_me
volumes:
- ./data:/var/lib/postgresql/data
ports:
- "5432:5432"
postgrest:
image: postgrest/postgrest:v12.0.2
depends_on:
- db
ports:
- "3000:3000"
environment:
PGRST_DB_URI: postgres://admin:change_me@db:5432/appdb
PGRST_DB_SCHEMAS: api
PGRST_DB_ANON_ROLE: anon
PGRST_OPENAPI_SERVER_PROXY_URI: http://127.0.0.1:3000
PGRST_JWT_SECRET: my_super_secret_32_bytes_key
关键环境变量说明:
PGRST_DB_URI:连接字符串,至少使用具备USAGE权限的用户。PGRST_DB_SCHEMAS:暴露给 API 的 schema,建议单独建apischema 放视图和函数。PGRST_DB_ANON_ROLE:匿名访问使用的 PostgreSQL role。PGRST_JWT_SECRET:JWT 共享密钥,生产环境请通过openssl rand -base64 32生成并写入.env。
TIP如果部署在反向代理之后,需要把
PGRST_SERVER_PROXY_URI或PGRST_OPENAPI_SERVER_PROXY_URI指向外部访问域名,确保 OpenAPI 文档和重定向正确。
角色与权限模型
PostgREST 完全依赖 PostgreSQL 的角色/权限体系。推荐的最小结构如下:
-- 匿名角色(仅能 GET)
create role anon nologin;
grant usage on schema api to anon;
grant select on all tables in schema api to anon;
-- 受信任角色(可以写)
create role webuser nologin;
grant usage on schema api to webuser;
grant select, insert, update, delete on all tables in schema api to webuser;
-- 将数据库登录用户映射到这些角色
create role admin login password 'change_me';
grant anon, webuser to admin;
- 匿名请求默认使用
PGRST_DB_ANON_ROLE。 - 带 JWT 的请求如果包含
role字段,PostgREST 会尝试切换到目标角色(需确保 token 里的角色是登录角色的成员)。
NOTEPostgreSQL 默认不会自动把权限应用到新表/视图。可使用
ALTER DEFAULT PRIVILEGES或数据库迁移工具(如 Sqitch、Flyway)统一维护。
准备 API Schema
在业务 schema(例如 public)里定义真实表,再在 api schema 中创建视图/函数对外暴露。这样可以隐藏内部字段,并内置联表逻辑。
create schema if not exists api;
create table public.todos (
id serial primary key,
user_id int not null,
title text not null,
done boolean default false,
inserted_at timestamptz default now()
);
create view api.todos as
select id, title, done, inserted_at
from public.todos;
重载 /todos 接口即可拿到 api.todos 视图结果,user_id 字段不会被暴露。
启用行级安全(RLS)
alter table public.todos enable row level security;
create policy select_own_todos on public.todos
for select
using (current_setting('request.jwt.claim.user_id', true)::int = user_id);
create policy write_own_todos on public.todos
for all
using (current_setting('request.jwt.claim.user_id', true)::int = user_id)
with check (current_setting('request.jwt.claim.user_id', true)::int = user_id);
当请求携带的 JWT 包含 user_id claim 时,PostgREST 会写入 request.jwt.claim.user_id 这个 GUC 变量,策略自然就生效。
生成 JWT
openssl rand -base64 32
# 复制结果写入 PGRST_JWT_SECRET
示例 payload:
{
"role": "webuser",
"user_id": 42
}
将 payload 使用 HS256 与密钥签名后即可调用受保护接口。可以用 jwt.io 生成并调试。
请求示例:
curl https://api.example.com/todos \
-H "Authorization: Bearer $TOKEN"
查询语法速查
PostgREST 通过 URL 查询参数映射 SQL 过滤器。核心操作符示例:
| 操作 | 语法 | 说明 |
|---|---|---|
| 等于 | ?done=eq.true | eq 表示 = |
| 模糊 | ?title=ilike.*bug* | ilike 支持大小写不敏感 |
| 范围 | ?inserted_at=gte.2025-01-01 | gte/gt/lte/lt |
IN | ?id=in.(1,2,3) | 逗号分隔 |
嵌套 OR | ?or=(done.eq.true,title.ilike.*urgent*) | 记得 URL encode |
| JSONB | ?meta->>status=eq.active | 支持 ->、->> |
分页与排序
- 排序:
?order=inserted_at.desc - 限制:
?limit=20 - 游标翻页:使用
Range头或?offset=20
服务端会在响应头给出 Content-Range。
多表嵌套
PostgREST 支持通过外键自动嵌套资源:
alter table public.todos
add constraint todos_user_fk foreign key (user_id) references public.users(id);
create view api.users as
select id, email from public.users;
请求 GET /users?select=id,email,todos(id,title) 会自动返回嵌套 JSON。
调用存储过程
PostgREST 将 SQL 函数映射为 RPC 接口,例如:
create function api.complete_todo(_id int)
returns public.todos as $$
update public.todos
set done = true
where id = _id
returning *;
$$ language sql security definer;
调用:POST /rpc/complete_todo,请求体为 {"_id": 1}。
函数默认运行在调用者角色下。若需提升权限,请使用 security definer 并仔细设定 search_path。
常见排错
- 接口 401/403:确认 JWT 是否包含
role,且该角色被登录用户授予;检查 RLS 是否放行。 - 新建表无法访问:忘记给
apischema 或新表授权,或视图没同步。 - OpenAPI 缺字段:必须在
apischema 下暴露视图,或在函数设置stable属性。 - CORS 问题:配置反向代理添加 CORS 头,或使用
PGRST_SERVER_PROXY_URI。
生产实践建议
- 使用迁移脚本统一管理角色、策略和视图,避免手工操作。
- 为
postgrest服务加上healthcheck,配合 Nginx/Traefik 自动探活。 - 结合
pg_stat_statements分析慢查询,必要时创建索引或重写视图。 - 对外暴露前务必在 staging 环境跑一轮权限测试,防止数据泄露。
参考资料
- 官方文档:涵盖全部配置项与示例。
- Query Cheatsheet:查询参数详解。
- Row Level Security 指南:RLS 策略写法。


