把 CNB 仓库当后端用
把 CNB 仓库当后端用 — Git 就是数据库,OpenAPI 就是 REST 接口。无需服务器、无需数据库、无需运维,用 CNB 的 Git + API 组合搭建轻量级后端服务。
所属组织:工具箱(工具开发与模板)
为什么用 CNB 当后端?
传统后端开发需要:买服务器 → 装数据库 → 写 API → 部署运维。对于很多轻量级场景(配置管理、内容发布、数据采集、微型 CMS),这套流程太重了。
CNB 提供了一种全新的思路:
| 传统后端 | CNB 当后端 |
|---|---|
| 需要服务器 | CNB 平台即服务器 |
| 需要 MySQL/PostgreSQL | Git 仓库就是数据库 |
| 需要自己写 CRUD API | CNB OpenAPI 开箱即用 |
| 需要运维部署 | 零运维,push 即发布 |
| 需要 API 网关/鉴权 | Token 鉴权内置 |
适合的场景:
- 微型 CMS / 博客后端 — 文章用 Markdown 存,API 直接读取
- 配置中心 — 多环境配置用 JSON/YAML 管理,版本可追溯
- 数据采集存储 — 定时任务把采集数据 push 到仓库
- 知识库 / 文档站 — 文件即内容,CNB 自带渲染
- 状态管理 — JSON 文件记录应用状态,Issue 系统当工单
- 简单 CRUD — 用 JSON 文件替代数据库表,Git push 就是 INSERT/UPDATE
快速开始
1. 创建仓库
在 CNB 上创建一个仓库(公开或私有均可),记下仓库路径,例如 your-org/your-repo。
2. 获取访问令牌
进入 CNB 个人设置 → 访问令牌 → 新建令牌。
令牌格式类似
1ZxxxxxxxxxxxxxxxxxxxxxxxxvA
3. 读写数据
读取数据(GET):
bash
# 列出仓库根目录
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.cnb.cool/{org}/{repo}/-/git/contents"
# 读取指定文件(原始内容)
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.cnb.cool/{org}/{repo}/-/git/raw/main/data/users.json"
# 读取文件(含元信息,base64 编码)
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.cnb.cool/{org}/{repo}/-/git/contents/data/users.json"写入数据(Git Push):
bash
# Clone 仓库
git clone https://{username}:{token}@cnb.cool/{org}/{repo}
# 写入/修改 JSON 数据
echo '{"name":"Alice","role":"admin"}' > data/users/alice.json
git add . && git commit -m "feat: add user alice" && git push写入数据(API Blob):
bash
# 创建 Blob(不产生 commit,适合预上传)
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content":"hello world","encoding":"utf-8"}' \
"https://api.cnb.cool/{org}/{repo}/-/git/blobs"
# 返回: {"sha":"3f3571faa3b7454a3ce63e71ef5c909b1b58766a"}4. 用 Issue 当"数据库表"
bash
# 创建一条记录(Issue)
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"新用户注册","body":"{\"user\":\"bob\",\"email\":\"bob@example.com\"}","labels":["user"]}' \
"https://api.cnb.cool/{org}/{repo}/-/issues"
# 查询所有记录
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.cnb.cool/{org}/{repo}/-/issues"仓库结构
cnb-as-backend/
├── README.md # 本文件
├── docs/
│ ├── api-reference.md # API 速查手册(完整端点列表)
│ └── use-cases.md # 使用场景与最佳实践
├── examples/
│ ├── data/
│ │ ├── config.json # 示例:配置文件
│ │ ├── articles.json # 示例:文章数据
│ │ └── schema.sql # 示例:SQL 建表(传统对比)
│ └── scripts/
│ ├── cnb-api.py # Python API 调用封装
│ └── cnb-api.sh # Shell API 调用脚本
└── assets/
└── architecture.png # 架构图架构总览
┌─────────────┐ Git Push ┌─────────────────┐
│ 数据写入方 │ ──────────────▶ │ CNB Git 仓库 │
│ (NPC/脚本/ │ │ (数据 = 文件) │
│ 手动/CI) │ │ (版本 = Commit) │
└─────────────┘ └────────┬────────┘
│
CNB OpenAPI
│
┌────────▼────────┐
│ 数据读取方 │
│ (Web/App/NPC/ │
│ 任何 HTTP 客户端) │
└─────────────────┘API 速查
| 功能 | 方法 | 端点 | 说明 |
|---|---|---|---|
| 列出文件 | GET | /-/git/contents/{path} | 获取目录/文件列表 |
| 读文件内容 | GET | /-/git/raw/main/{path} | 获取原始文件内容 |
| 读文件元信息 | GET | /-/git/contents/{path} | 含 SHA、大小、base64 内容 |
| 创建 Blob | POST | /-/git/blobs | 预创建数据块 |
| 提交列表 | GET | /-/git/commits | 获取 commit 历史 |
| 分支列表 | GET | /-/git/branches | 查询所有分支 |
| 创建分支 | POST | /-/git/branches | 从指定 ref 创建新分支 |
| Tag 列表 | GET | /-/git/tags | 查询所有标签 |
| 创建 Issue | POST | /-/issues | 创建"数据记录" |
| 查询 Issue | GET | /-/issues | 查询"数据表" |
| 文件上传 | POST | /-/upload/files | 获取上传 URL 后 PUT |
| 图片上传 | POST | /-/upload/imgs | 获取上传 URL 后 PUT |
| 比较 diff | GET | /-/git/compare/{base..head} | 版本差异对比 |
完整 API 文档见 docs/api-reference.md
Python 封装示例
python
import requests
class CNBBackend:
"""CNB 仓库作为后端的轻量封装"""
def __init__(self, org: str, repo: str, token: str):
self.base = f"https://api.cnb.cool/{org}/{repo}"
self.headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
def list_files(self, path: str = "") -> list:
"""列出目录下的文件"""
resp = requests.get(
f"{self.base}/-/git/contents/{path}",
headers=self.headers
)
data = resp.json()
return data.get("entries", [])
def read_file(self, path: str, raw: bool = True) -> str | dict:
"""读取文件内容"""
if raw:
resp = requests.get(
f"{self.base}/-/git/raw/main/{path}",
headers=self.headers
)
return resp.text
else:
resp = requests.get(
f"{self.base}/-/git/contents/{path}",
headers=self.headers
)
return resp.json()
def read_json(self, path: str) -> dict | list:
"""读取 JSON 文件并解析"""
content = self.read_file(path, raw=True)
import json
return json.loads(content)
def create_blob(self, content: str) -> str:
"""创建一个 Blob(数据块)"""
resp = requests.post(
f"{self.base}/-/git/blobs",
headers={**self.headers, "Content-Type": "application/json"},
json={"content": content, "encoding": "utf-8"}
)
return resp.json().get("sha", "")
def list_issues(self, state: str = "open") -> list:
"""查询 Issues(数据记录)"""
resp = requests.get(
f"{self.base}/-/issues",
headers=self.headers,
params={"state": state}
)
return resp.json()
def create_issue(self, title: str, body: str, labels: list = None) -> dict:
"""创建 Issue(写入数据记录)"""
data = {"title": title, "body": body}
if labels:
data["labels"] = labels
resp = requests.post(
f"{self.base}/-/issues",
headers={**self.headers, "Content-Type": "application/json"},
json=data
)
return resp.json()
# 使用示例
db = CNBBackend("your-org", "your-repo", "your-token")
files = db.list_files("data")
config = db.read_json("data/config.json")
db.create_issue("新订单", '{"product":"A","qty":10}', ["order"])对比:CNB 后端 vs 传统方案
| 维度 | CNB 后端 | Supabase | Firebase | 自建服务器 |
|---|---|---|---|---|
| 费用 | 免费 | 免费额度 | 免费额度 | 需付费 |
| 数据格式 | 任意文件 | SQL | NoSQL | 自选 |
| 版本管理 | Git 内置 | 需额外方案 | 需额外方案 | 需自建 |
| API | RESTful OpenAPI | RESTful + GraphQL | RESTful + SDK | 自建 |
| 鉴权 | Bearer Token | JWT | API Key | 自建 |
| 实时更新 | 不支持 | 支持 | 支持 | 需自建 WebSocket |
| 复杂查询 | 不支持 | SQL 全支持 | 有限查询 | 全支持 |
| 适合场景 | 内容/配置/文档 | 完整应用 | 实时应用 | 任何场景 |
限制与注意事项
- 不适合高频写入 — Git Push 有延迟,不适合需要实时响应的场景
- 不适合复杂查询 — 没有数据库索引,无法执行 SQL WHERE/GROUP BY
- 不适合大量数据 — 单文件建议不超过 1MB,仓库总大小有上限
- 不适合关系型数据 — 没有 JOIN、外键等概念
- 写入需要 Git — 通过 API 只能创建 Blob,完整写入需要 Git Push
- Token 安全 — 访问令牌相当于密码,不要提交到公开仓库
更多内容
- API 速查手册 — 完整端点列表与请求/响应格式
- 使用场景与最佳实践 — 5 个实战场景详解
- Python API 封装 — 可直接使用的 Python SDK
- Shell API 脚本 — curl 版本速查
<small>由 云锦鸿信息技术工作室 维护</small>