大家好,这里是架构资源栈 !点击上方关注,添加"星标",一起学习大厂前沿架构!
关注、发送C1
即可获取JetBrains全家桶激活工具和码!
在现代应用的开发过程中,后端架构往往是最复杂、最费时的部分之一。对于希望快速上线 MVP 或构建小型项目的开发者来说,Firebase、Supabase 这类 BaaS(Backend-as-a-Service)服务是理想选择。但如果你希望用更轻量、可控性更高的方式构建自己的 BaaS,Pennybase 提供了一个非常极致的解决方案:它在不到 1000 行 Go 代码中实现了完整的后端能力,且不依赖任何第三方库。
本文将从架构设计、数据存储、权限管理、API 接口、实时能力以及模板渲染多个方面,拆解这个"穷人版 Firebase"的核心原理。
简洁的架构,文本驱动的数据存储
Pennybase 的核心是文件驱动的设计,它采用 CSV 作为数据存储格式,每一条数据是一个版本化的记录,所有更新都会以新行追加的方式写入。
CSV 的列结构约定如下:
- 第一列:记录 ID
- 第二列:版本号
- 剩余列:具体字段内容
为了让 JSON 与 CSV 数据之间互转,Pennybase 使用了一个名为 _schemas.csv
的文件定义数据结构、字段类型、校验规则等信息,例如:
arduino
s12,1,todo,_id,text,,,^.+$
s13,1,todo,_v,number,1,,
s14,1,todo,description,text,0,0,".+"
s15,1,todo,completed,number,0,1,""
以上定义了一个 todo
集合,其中包含 description
和 completed
两个字段,前者是字符串并要求非空,后者是布尔值(以 0/1 表示)。
权限模型:简单但高效的 RBAC 与所有权控制
在权限控制方面,Pennybase 支持基本的基于角色的访问控制(RBAC)机制,并结合资源所有权字段,实现了灵活的权限模型。
权限规则统一配置在 _permissions.csv
中,每条规则定义一个动作(如读取、写入)与对应的角色或所有者,例如:
sql
p3,1,todo,update,owner,"admin,editor","Only owners and users with admin or editor role can update todos"
这条规则意味着:用户如果是该资源的 owner
字段所标识的用户,或者具有 admin
、editor
角色,就可以更新 todo
数据。
用户系统:简洁的认证方式 + 明文配置文件
Pennybase 没有复杂的注册流程,用户信息统一维护在 _users.csv
中:
ini
admin,1,salt,5V5R4SO4ZIFMXRZUL2EQMT2CJSREI7EMTK7AH2ND3T7BXIDLMNVQ====,"admin"
每个用户记录中包含用户名、密码哈希(Base32 编码 + SHA256 + Salt)和对应的角色列表。
Pennybase 支持两种认证方式:
- Basic Auth:通过 HTTP 头传递用户名密码
- Session Cookie:通过
/api/login
登录,后续操作自动带上 session cookie
RESTful API:清晰明了的资源访问接口
所有 REST API 均基于 _schemas.csv
中的定义自动生成,支持完整的 CRUD 操作:
GET /api/{resource}
:获取资源列表GET /api/{resource}/{id}
:查询单条记录POST /api/{resource}
:新增记录PUT /api/{resource}/{id}
:更新记录DELETE /api/{resource}/{id}
:删除记录GET /api/events/{resource}
:基于 SSE 的实时变更推送
接口返回标准 JSON 格式,同时在权限不满足时自动返回拒绝响应。
实时能力:Server-Sent Events 实现轻量订阅
相比使用 WebSocket 实现实时推送,Pennybase 选择了更轻量的 SSE(Server-Sent Events)协议。用户只需访问 GET /api/events/{resource}
,即可在资源更新时实时获取通知。
这种设计非常适合构建协同编辑、聊天室、看板等需要轻量实时能力的应用。
模板渲染:Go Template + 权限控制 +数据查询
除了 API,Pennybase 还支持 HTML 模板渲染。用户可以在 templates/
目录中放置 .html
文件,通过 URL 访问自动解析并渲染。
模板上下文提供如下能力:
.User
:当前登录用户.Store
:数据查询接口.ID
:当前资源 ID(如果有).Authorize
:校验用户是否有权限访问资源的函数
例如:
html
{{ if .User }}
{{ if call .Authorize "todo" "read" .ID }}
<div>{{ .Store.Get "todo" .ID }}</div>
{{ else }}
<div>您无权限查看该内容。</div>
{{ end }}
{{ else }}
<div>请先登录。</div>
{{ end }}
扩展能力:一行 Hook 实现逻辑插拔
Pennybase 允许用户自定义钩子函数(Hook)来拦截 create
、update
、delete
等事件,注入自定义逻辑,例如:
go
server.Hook = func(trigger, resource string, user pennybase.Resource, res pennybase.Resource) error {
if trigger == "create" && resource == "messages" {
res["author"] = user["_id"]
res["created_at"] = time.Now().UTC().Format(time.RFC3339)
}
return nil
}
这种方式非常适合实现字段补全、权限控制、数据清洗等高级功能。
总结
Pennybase 展示了一种极致简约的后端架构实现路径:无需数据库、无需第三方依赖、无需复杂部署,仅靠 Go 标准库和文本文件即可构建具备用户认证、权限管理、REST API、实时通信、模板渲染的完整后端系统。
它并不试图取代 Firebase 或 Supabase,而是为喜欢"代码可控、结构清晰、运行简单"的开发者提供了一种朴素但高效的替代方案。
想象一下,用一个不足 1000 行的工具托管你的 Web 应用数据、认证和业务逻辑,是不是也很酷?
GitHub 地址:zserge/pennybase - Poor man's Backend-as-a-Service (BaaS), similar to Firebase/Supabase/Pocketbase
本文由博客一文多发平台 OpenWrite 发布!