template-monorepo/internal/response
王性驊 713a81f70b feat(auth): add unified registration/login module with Zitadel + lint cleanup
- Introduce auth module: handlers, logic, domain/repository/usecase, JWT
  middleware, and Zitadel OIDC client (password + authorization code +
  userinfo + JWKS verification)
- Wire member rate-limit, structured errors, and refactored member/
  notification usecases (introduce shared errors, drop repo_errors.go)
- Bring the codebase to zero golangci-lint issues:
  * goimports formatting
  * errcheck on io.ReadAll/Unlock cleanup paths
  * contextcheck: HandlerContext now takes (ctx, *http.Request)
  * gocritic: rename shadowed `max`, use http.NoBody
  * goconst: extract test fixtures and bsonOpSet
  * testifylint: switch to assert inside httptest handlers

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 14:45:35 +08:00
..
README.md feat(auth): add unified registration/login module with Zitadel + lint cleanup 2026-05-21 14:45:35 +08:00
request.go add validate 2026-05-19 20:56:32 +08:00
request_test.go add lint 2026-05-19 21:15:18 +08:00
response.go feat(auth): add unified registration/login module with Zitadel + lint cleanup 2026-05-21 14:45:35 +08:00
response_test.go add validate 2026-05-19 20:56:32 +08:00

README.md

HTTP 統一回應

分工

職責
Logic return data, errerr*errs.Error 或標準 error
Handler response.Write(ctx, w, data, err)
.api 只描述 data 的型別(如 PingData),不描述外層 Status

Handler 範例

有 request 的 API模板會自動生成 參數綁定 + 驗證httpx.ParsesvcCtx.Validator.ValidateAll

var req types.GetUserReq
if err := httpx.Parse(r, &req); err != nil {
    response.Write(r.Context(), w, nil, response.WrapRequestError(err)) // → 400 InputInvalidFormat
    return
}
if err := svcCtx.Validator.ValidateAll(&req); err != nil {
    response.Write(r.Context(), w, nil, response.WrapRequestError(err)) // validate:"..." 失敗
    return
}
data, err := l.GetUser(&req)
response.Write(r.Context(), w, data, err)

.api 的 request 欄位加 validate:"required,email" 等 tagmake gen-api 後會寫入 internal/types,無需在 Logic 再手動驗證。

無 request 的 APIGET /health)不會生成 Parse / ValidateAll 區塊,屬正常行為。

main 可設定驗證錯誤使用的 scope

response.RequestErrScope = code.Facade

.api 的 request struct 可加 validate: tag 或實作 Validate() error,由 go-zero httpx.Parse 觸發。

進階驗證可使用 svcCtx.Validator.ValidateAll(&req)gateway/internal/library/validate)。回傳的 validate.ValidationErrorsresponse.WrapRequestError 會映射為 400 InputInvalidFormat

Logic 範例

各模組 logic / usecase 綁定對應 scope不要一律用 code.Facade

// internal/logic/member/errors.go
var errb = errs.For(code.Member)

func (l *XLogic) GetUser(req *types.GetUserReq) (*types.UserVO, error) {
    out, err := l.svcCtx.MemberProfile.Get(...)
    if err != nil {
        return nil, err // Member scope 錯誤原樣傳遞
    }
    return vo, nil
}

回應 JSON

成功HTTP 200

{ "code": 102000, "message": "SUCCESS", "data": { ... } }

失敗HTTP 依 category如 404Member scope 範例):

{
  "code": 29301000,
  "message": "member not found",
  "error": { "biz_code": "29301000", "scope": 29, "category": 301, "detail": 0 }
}

goctl 模板(可選)

專案模板路徑:generate/goctl/api/handler.tpl不是 api/gogen/)。

make gen-api 已帶 -home generate/goctl新建的 handler 會自動使用 response.Write

注意:已存在的 handler 檔案 goctl 不會覆寫(會顯示 exists, ignored)。新增 API 沒問題;若要重生成舊 handler需先刪除該檔再 make gen-api