2026-05-19 13:15:18 +00:00
|
|
|
|
# Portal API Gateway (PGW)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
基於 [go-zero](https://github.com/zeromicro/go-zero) 的 API Gateway,提供統一 HTTP JSON 回應、8 碼業務錯誤碼,以及由 `.api` 定義驅動的程式碼與 OpenAPI 3.0 文件生成。
|
|
|
|
|
|
|
|
|
|
|
|
## 功能概覽
|
|
|
|
|
|
|
|
|
|
|
|
- **REST API**:go-zero `rest` 服務,預設 `http://0.0.0.0:8888`
|
|
|
|
|
|
- **統一回應格式**:成功 / 失敗皆為 `Status` envelope(`code`、`message`、`data`、`error`)
|
|
|
|
|
|
- **結構化錯誤**:8 碼 `SSCCCDDD`(Scope + Category + Detail),可映射 HTTP / gRPC
|
|
|
|
|
|
- **程式碼生成**:`goctl` + 自訂 handler 模板(自動 `response.Write`)
|
|
|
|
|
|
- **API 文件**:`go-doc` 由同一套 `.api` 產出 OpenAPI 3.0 YAML
|
|
|
|
|
|
|
|
|
|
|
|
## 環境需求
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
| 工具 | 必要 | 說明 |
|
|
|
|
|
|
|------|:----:|------|
|
|
|
|
|
|
| Go | ✓ | ≥ 1.26.1(見 `go.mod`) |
|
|
|
|
|
|
| Make | ✓ | 執行 `gen-api` / `gen-doc` 等 |
|
|
|
|
|
|
| [goctl](https://go-zero.dev/docs/tasks/installation/goctl) | ✓ | `make gen-api` 用;可 `make tools` 安裝 |
|
|
|
|
|
|
| goimports | 建議 | `make fmt` 用;`make tools` 安裝 |
|
|
|
|
|
|
| golangci-lint | 建議 | `make lint` 用;`make tools` 安裝(v2,見 `.golangci.yml`) |
|
|
|
|
|
|
| jq | 選用 | README 範例 `curl \| jq` |
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
請確認 **`$(go env GOPATH)/bin` 在 PATH**,否則 `go install` 的 `goctl` 找不到。
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
## 快速開始(首次)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd gateway
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
# 1. 工具(goctl、goimports)
|
|
|
|
|
|
make tools
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 依賴
|
2026-05-19 12:56:32 +00:00
|
|
|
|
go mod download
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
# 3. 依 .api 生成程式碼(可選,repo 內通常已有)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
make gen-api
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
# 4. 啟動
|
|
|
|
|
|
make run
|
|
|
|
|
|
# 或:go run gateway.go -f etc/gateway.yaml
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-20 07:01:08 +00:00
|
|
|
|
### 本機 Mongo + Redis(Notification / Member OTP)
|
|
|
|
|
|
|
|
|
|
|
|
需要持久化通知、異步重試或 member 驗證時:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
make deps-up # Mongo :27017、Redis :6379
|
|
|
|
|
|
make mongo-index # 建立 notifications / notification_dlq 索引
|
|
|
|
|
|
make run-dev # 使用 etc/gateway.dev.yaml
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
詳見 [deploy/README.md](deploy/README.md)、[etc/README.md](etc/README.md)。選用 MailHog:`make deps-up-smtp`。
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
產生 OpenAPI(會先編譯 `generate/doc-generate` 內的 go-doc):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
make gen-doc # 輸出 docs/openapi/gateway.yaml
|
2026-05-19 12:56:32 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
健康檢查:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://127.0.0.1:8888/api/v1/health | jq
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
預期回應:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"message": "SUCCESS",
|
|
|
|
|
|
"data": { "pong": "ok" }
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 常用指令
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
執行 `make` 或 `make help` 可看完整列表。
|
|
|
|
|
|
|
2026-05-19 12:56:32 +00:00
|
|
|
|
| 指令 | 說明 |
|
|
|
|
|
|
|------|------|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
| `make tools` | 首次安裝 goctl、goimports |
|
|
|
|
|
|
| `make gen-api` | 由 `gateway.api` 生成 Go(自訂 `generate/goctl` 模板) |
|
|
|
|
|
|
| `make gen-doc` | 編譯 go-doc 並生成 `docs/openapi/gateway.yaml` |
|
|
|
|
|
|
| `make test` | 執行測試 |
|
|
|
|
|
|
| `make fmt` | gofmt + goimports |
|
|
|
|
|
|
| `make lint` | golangci-lint 靜態檢查(必須 0 issues) |
|
|
|
|
|
|
| `make lint-fix` | 自動修正可修的 lint / import 問題 |
|
|
|
|
|
|
| `make fix` | `fmt` + `lint-fix` + `lint`(提交前建議) |
|
|
|
|
|
|
| `make check` | `fix` + `test`(PR / AI 完成前必跑) |
|
2026-05-20 07:01:08 +00:00
|
|
|
|
| `make run` | 啟動 Gateway(無 DB) |
|
|
|
|
|
|
| `make deps-up` | Docker 啟動 Mongo + Redis |
|
|
|
|
|
|
| `make run-dev` | 啟動 Gateway(`etc/gateway.dev.yaml`,需 Docker) |
|
|
|
|
|
|
| `make config-check` | 驗證 yaml 可載入 |
|
|
|
|
|
|
| `make mongo-index` | 建立 notification Mongo 索引 |
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
## 專案結構
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
gateway/
|
|
|
|
|
|
├── gateway.go # 程式入口
|
|
|
|
|
|
├── etc/gateway.yaml # 服務設定(埠號等)
|
|
|
|
|
|
├── generate/
|
|
|
|
|
|
│ ├── api/ # API 定義(goctl + go-doc 共用)
|
|
|
|
|
|
│ ├── goctl/api/handler.tpl # 自訂 handler 模板 → response.Write
|
|
|
|
|
|
│ └── doc-generate/ # go-doc(.api → OpenAPI)
|
|
|
|
|
|
├── internal/
|
|
|
|
|
|
│ ├── handler/ # HTTP handler(goctl 生成,response.Write)
|
|
|
|
|
|
│ ├── logic/ # HTTP 編排:types ↔ usecase DTO,只回 data + error
|
|
|
|
|
|
│ ├── types/ # goctl 生成的請求/回應型別
|
|
|
|
|
|
│ ├── response/ # 統一 JSON 回應封裝
|
|
|
|
|
|
│ ├── svc/ # ServiceContext:組裝各模組 UseCase
|
|
|
|
|
|
│ ├── config/ # go-zero RestConf 等服務設定
|
|
|
|
|
|
│ ├── library/errors/ # 全專案唯一結構化錯誤(8 碼 SSCCCDDD)
|
|
|
|
|
|
│ ├── library/validate/ # struct 驗證(go-playground/validator + 翻譯)
|
2026-05-19 13:33:04 +00:00
|
|
|
|
│ ├── library/mongo/ # DocumentDB + Redis cache(mongo-driver v2)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
│ ├── library/errlog/ # 可選 slog 日誌輔助
|
|
|
|
|
|
│ └── model/ # 業務模型根目錄(見下方)
|
|
|
|
|
|
│ └── {module}/ # 例如 member/、order/
|
|
|
|
|
|
└── docs/
|
|
|
|
|
|
├── model.md # model/{module} 內 entity / repository / usecase 細節
|
|
|
|
|
|
└── openapi/ # gen-doc 輸出(預設 .gitignore)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 業務模型(`internal/model/{module}/`)
|
|
|
|
|
|
|
|
|
|
|
|
業務領域程式碼一律放在 **`internal/model/`** 底下,再依模組分子目錄(例如 `internal/model/member/`)。**不使用 `pkg/`**。HTTP 層(handler / logic / types)仍由 goctl 管理;持久化與業務規則在 `model/{module}/` 內。
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
internal/model/
|
|
|
|
|
|
└── member/ # 模組名稱(member、order…)
|
|
|
|
|
|
├── entity/ # MongoDB document(Account、User…)
|
|
|
|
|
|
├── enum/ # 列舉 / 值物件(Platform、Status…)
|
|
|
|
|
|
├── repository/ # Repository 介面 + 實作(Mongo / cache)
|
|
|
|
|
|
├── usecase/ # UseCase 介面、Request/Response DTO、實作
|
|
|
|
|
|
├── config/ # 模組用設定 struct(不含 go-zero RestConf)
|
|
|
|
|
|
├── errors.go # 模組 sentinel(如 ErrNotFound),非第二套錯誤碼
|
|
|
|
|
|
├── const.go # 模組常數
|
|
|
|
|
|
├── redis.go # Redis key 命名與 helper
|
|
|
|
|
|
└── mock/ # mockgen 產物,勿手改
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**依賴方向:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
handler → logic → model/{module}/usecase(介面)
|
|
|
|
|
|
↓
|
|
|
|
|
|
model/{module}/repository(介面)
|
|
|
|
|
|
↓
|
|
|
|
|
|
entity / enum / MongoDB·Redis
|
|
|
|
|
|
|
|
|
|
|
|
entity、enum 不依賴 repository、usecase、logic
|
|
|
|
|
|
logic 不 import model/{module}/repository 或 model/{module}/entity
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**請求鏈:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
HTTP Request
|
|
|
|
|
|
→ handler(response.Write)
|
|
|
|
|
|
→ logic(types ↔ usecase DTO)
|
|
|
|
|
|
→ model/{module}/usecase
|
|
|
|
|
|
→ model/{module}/repository
|
|
|
|
|
|
→ MongoDB / Redis
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
更細的 entity / repository / usecase 撰寫規則見 [docs/model.md](docs/model.md)。
|
|
|
|
|
|
|
|
|
|
|
|
更細的說明見各子目錄 README:
|
|
|
|
|
|
|
|
|
|
|
|
- [generate/api/README.md](generate/api/README.md) — `.api` 與 `@respdoc` 約定
|
|
|
|
|
|
- [internal/response/README.md](internal/response/README.md) — Handler / Logic 分工
|
|
|
|
|
|
- [internal/library/errors/README.md](internal/library/errors/README.md) — 錯誤碼與 HTTP 對照
|
2026-05-19 13:33:04 +00:00
|
|
|
|
- [internal/library/mongo/README.md](internal/library/mongo/README.md) — MongoDB / Redis cache 流程與用法
|
2026-05-19 12:56:32 +00:00
|
|
|
|
- [docs/model.md](docs/model.md) — `internal/model/{module}` 分層(entity / repository / usecase)
|
2026-05-19 13:56:59 +00:00
|
|
|
|
- [docs/identity-member-design.md](docs/identity-member-design.md) — **Draft** Identity / Member / Permission 模組架構(ZITADEL、LDAP、SCIM、B2B 自定義權限)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
## 開發約定
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 新增 API 流程
|
|
|
|
|
|
|
|
|
|
|
|
1. 在 `generate/api/` 新增或修改 `.api`(並在 `gateway.api` import)。
|
|
|
|
|
|
2. `make gen-api` 生成程式碼(**新** handler 會自動使用 `response.Write`;已存在檔案不會覆寫,需手動刪除後再生成或自行修改)。
|
|
|
|
|
|
3. 在 `internal/logic/` 做 types 映射並呼叫模組 UseCase,只回傳 **data** 與 **error**。
|
|
|
|
|
|
4. `make gen-doc` 更新 OpenAPI 文件。
|
|
|
|
|
|
5. `go test ./...`
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Logic 與 Handler
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
// internal/logic/... — 編排與映射;有持久化時呼叫 svcCtx.{Module}UC
|
|
|
|
|
|
var errb = errs.For(code.Facade)
|
|
|
|
|
|
|
|
|
|
|
|
func (l *PingLogic) Ping() (*types.PingData, error) {
|
|
|
|
|
|
return &types.PingData{Pong: "ok"}, nil // 簡單 API 可直接回 types
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// internal/handler/... — 由模板生成
|
|
|
|
|
|
data, err := l.Ping()
|
|
|
|
|
|
response.Write(r.Context(), w, data, err)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
有 request 的 API 會自動包含 `httpx.Parse`;解析失敗會映射為 **400** `InputInvalidFormat`。
|
|
|
|
|
|
|
|
|
|
|
|
### 3. HTTP JSON 格式
|
|
|
|
|
|
|
|
|
|
|
|
**成功(HTTP 200)**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"message": "SUCCESS",
|
|
|
|
|
|
"data": { }
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**失敗(HTTP 依錯誤類別,如 404)**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 10301000,
|
|
|
|
|
|
"message": "user not found",
|
|
|
|
|
|
"error": {
|
|
|
|
|
|
"biz_code": "10301000",
|
|
|
|
|
|
"scope": 10,
|
|
|
|
|
|
"category": 301,
|
|
|
|
|
|
"detail": 0
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 錯誤處理(全專案單一型別)
|
|
|
|
|
|
|
|
|
|
|
|
對外 API 只使用 `gateway/internal/library/errors` 的 `*errs.Error`(8 碼 `SSCCCDDD`)。**不要**在模組內再維護第二套業務錯誤碼套件。
|
|
|
|
|
|
|
|
|
|
|
|
各層職責:
|
|
|
|
|
|
|
|
|
|
|
|
| 層 | 職責 | 回傳 |
|
|
|
|
|
|
|----|------|------|
|
|
|
|
|
|
| **repository** | 忠實反映基礎設施(Mongo / Redis / driver) | `*errs.Error`(DB*、ResInvalidMeasureID 等)+ `WithCause`;可預期「無資料」可回模組 `errors.go` 的 **sentinel** |
|
|
|
|
|
|
| **usecase** | 業務規則(狀態、權限、組合多 repo) | `*errs.Error`(Res*、Auth*、Svc* 等);sentinel 轉成對外語意;已是正確的 `*errs.Error` 可原樣往上傳 |
|
|
|
|
|
|
| **logic** | HTTP 輸入檢查、types 映射 | 僅在進 usecase 前用 `Input*`;其餘 **原樣** `return nil, err`,不二次包裝 |
|
|
|
|
|
|
| **handler** | 序列化 | `response.Write`(內建 `errs.FromError`) |
|
|
|
|
|
|
|
|
|
|
|
|
模組頂層 sentinel 範例(`internal/model/member/errors.go`,`package member`):
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
var (
|
|
|
|
|
|
ErrNotFound = errors.New("member: not found")
|
|
|
|
|
|
ErrInvalidObjectID = errors.New("member: invalid object id")
|
|
|
|
|
|
)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Repository 對照建議:
|
|
|
|
|
|
|
|
|
|
|
|
| 狀況 | 回傳 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `mongo.ErrNoDocuments` | `member.ErrNotFound`(由 usecase 轉 `ResNotFound`) |
|
|
|
|
|
|
| ObjectID 格式錯 | `errb.ResInvalidMeasureID("account_id")` |
|
|
|
|
|
|
| duplicate key | `errb.DBDuplicate(...)` |
|
|
|
|
|
|
| 連線 / 暫時不可用 | `errb.DBUnavailable(...).WithCause(err)` |
|
|
|
|
|
|
| 其他 driver 錯 | `errb.DBError(...).WithCause(err)` |
|
|
|
|
|
|
|
|
|
|
|
|
Usecase 範例:
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
var errb = errs.For(code.Facade)
|
|
|
|
|
|
|
|
|
|
|
|
acc, err := uc.Account.FindOne(ctx, id)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
if errors.Is(err, member.ErrNotFound) {
|
|
|
|
|
|
return nil, errb.ResNotFound("member", id).WithCause(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
if e := errs.FromError(err); e != nil {
|
|
|
|
|
|
return nil, err // DB* 等基礎設施錯誤原樣傳遞
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil, errb.DBError("get member failed").WithCause(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Logic 只做輸入與映射,錯誤直接往上:
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
out, err := l.svcCtx.MemberUC.GetByID(l.ctx, &memberusecase.GetByIDRequest{ID: req.Id})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**禁止:** repository 回傳裸 `fmt.Errorf` 給上層;logic 再包一層無語意錯誤;logic 直接操作 Mongo / repository 實作。
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
### 5. Lint 與自動修正
|
|
|
|
|
|
|
|
|
|
|
|
設定檔:`.golangci.yml`(golangci-lint v2,`standard` + revive / gosec / errorlint 等)。
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
make lint-fix # 自動修(goimports、部分 linter auto-fix)
|
|
|
|
|
|
make lint # 僅檢查
|
|
|
|
|
|
make fix # fmt + lint-fix + lint
|
|
|
|
|
|
make check # fix + test(建議每次改 Go 後執行)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
無法自動修的須手改;AI / 協作者應以 `make check` 通過為完成條件(見 `.cursor/rules/golangci-lint.mdc`)。
|
|
|
|
|
|
|
|
|
|
|
|
### 6. 請求驗證(`library/validate`)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
- `svc.ServiceContext.Validator`:啟動時以 `validate.NewWithDefaultEN()` 建立,可傳入 `validate.Option` 註冊自訂 tag。
|
|
|
|
|
|
- **Handler 模板**(`generate/goctl/api/handler.tpl`)在 `httpx.Parse` 之後自動 `ValidateAll(&req)`,失敗經 `WrapRequestError` → **400** `InputInvalidFormat`;Logic 通常不必再驗證。
|
|
|
|
|
|
- 自訂規則放在 `internal/library/validate/custom/`(依業務新增),透過 `NewWithDefaultEN(custom.YourOption)` 註冊。
|
|
|
|
|
|
- `validate.ValidationErrors` 含 `field` / `message`;勿與 `internal/library/errors/validate.go`(驗證 8 碼組成)混淆。
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
if err := l.svcCtx.Validator.ValidateAll(req); err != nil {
|
|
|
|
|
|
return nil, err // handler: response.WrapRequestError(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
### 7. 新增業務模組檢查清單
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
1. 建立 `internal/model/{module}/`,依上方目錄放置 `entity`、`enum`、`repository`、`usecase`。
|
|
|
|
|
|
2. 在 `internal/svc/service_context.go` 組裝 repository → usecase,掛上介面欄位。
|
|
|
|
|
|
3. 在 `generate/api/` 定義路由,`make gen-api`。
|
|
|
|
|
|
4. 在 `internal/logic/` 實作:types ↔ usecase DTO,呼叫 `svcCtx.{Module}UC`。
|
|
|
|
|
|
5. `make gen-doc`、`go test ./...`;介面變更後執行 mockgen 更新 `internal/model/{module}/mock/`。
|
|
|
|
|
|
|
|
|
|
|
|
完整步驟見 [docs/model.md](docs/model.md) 第 11 節。
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
### 8. 錯誤碼 API 速查
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
import (
|
|
|
|
|
|
errs "gateway/internal/library/errors"
|
|
|
|
|
|
"gateway/internal/library/errors/code"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var errb = errs.For(code.Facade)
|
|
|
|
|
|
|
|
|
|
|
|
return nil, errb.ResNotFound("user", id)
|
|
|
|
|
|
return nil, errb.InputMissingRequired("email").WithCause(err)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Category 與 HTTP 對照見 [internal/library/errors/README.md](internal/library/errors/README.md)。
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
### 9. API 文件(`@` 註解)
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
在 `.api` 中:
|
|
|
|
|
|
|
|
|
|
|
|
- `returns (FooVO)`:只描述 **data**(給 goctl / Logic)。
|
|
|
|
|
|
- `/* @respdoc-200 (FooOKStatus) ... */`:描述實際 HTTP body(給 OpenAPI)。
|
|
|
|
|
|
- `@doc(summary, description)`:單一接口說明。
|
|
|
|
|
|
|
|
|
|
|
|
範例見 `generate/api/normal.api`。
|
|
|
|
|
|
|
2026-05-19 13:15:18 +00:00
|
|
|
|
### 10. OpenAPI 產物與 Git
|
2026-05-19 12:56:32 +00:00
|
|
|
|
|
|
|
|
|
|
預設 `.gitignore` 會忽略 `docs/openapi/*.yaml`。若需提交給前端,請在 `.gitignore` 註解相關規則後執行 `make gen-doc` 並加入版本控制。
|
|
|
|
|
|
|
|
|
|
|
|
## 設定
|
|
|
|
|
|
|
|
|
|
|
|
主設定檔:`etc/gateway.yaml`
|
|
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
Name: gateway
|
|
|
|
|
|
Host: 0.0.0.0
|
|
|
|
|
|
Port: 8888
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
本地覆寫可新增 `etc/gateway-local.yaml`(已列入 `.gitignore`,勿提交機密)。
|
|
|
|
|
|
|
|
|
|
|
|
## 測試
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
go test ./...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 授權
|
|
|
|
|
|
|
|
|
|
|
|
內部專案,授權依組織規範為準。
|