update documents
This commit is contained in:
parent
c705cadadc
commit
d70bf6a402
51 changed files with 995 additions and 1997 deletions
|
|
@ -6,7 +6,7 @@ Fail fast with a consistent, machine-readable response. Handle errors at the con
|
|||
|
||||
## Go API Response Pattern
|
||||
|
||||
All HTTP responses go through two helpers in `controllers/response.go`:
|
||||
All HTTP responses go through two helpers in `controllers/response.go` (a small number of legacy handlers, e.g. `FilesController` list/dir endpoints in `controllers/files.go`, still call `ctx.JSON()` directly — treat those as bugs to fix opportunistically, not as sanctioned exceptions):
|
||||
|
||||
```go
|
||||
// Success (always HTTP 200)
|
||||
|
|
@ -18,7 +18,7 @@ ctx.Abort() // always Abort() after ReturnError in middleware
|
|||
return // always return immediately after ReturnError in handlers
|
||||
```
|
||||
|
||||
**The early-return pattern is non-negotiable.** Every error path ends with `ReturnError(...); return`.
|
||||
**The early-return pattern is non-negotiable.** Every error path ends with `ReturnError(...); return`. `ctx.Abort()` should always follow in middleware since gin does not stop the handler chain on its own — `middleware/whitelist.go`'s `WhitelistIPMiddleware` currently has one path that returns without calling `ctx.Abort()` (invalid client IP); that is a gap to close, not an accepted variant.
|
||||
|
||||
## HTTP Status Code Mapping
|
||||
|
||||
|
|
@ -78,17 +78,23 @@ if (rc < 0) {
|
|||
|
||||
## Input Validation Pattern
|
||||
|
||||
Validate at the controller boundary using a `preCheck{Resource}Request()` helper before touching services:
|
||||
Validate at the controller boundary in two steps: bind the request body with `utils.BindJSONStrict`, then pass the already-bound struct pointer to a `preCheck{Resource}Request()` helper before touching services:
|
||||
|
||||
```go
|
||||
func (c JobController) SubmitJob(ctx *gin.Context) {
|
||||
req, err := preCheckSubmitJobRequest(ctx)
|
||||
func (j JobController) CreateJob(ctx *gin.Context) {
|
||||
var req models.JobSubmitRequest
|
||||
if err := utils.BindJSONStrict(ctx, &req); err != nil {
|
||||
ReturnError(ctx, common.ERROR_CODE, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
parsedIndices, err := preCheckJobRequest(&req)
|
||||
if err != nil {
|
||||
ReturnError(ctx, common.INVALID_PARAMS_CODE, err.Error(), nil)
|
||||
ReturnError(ctx, common.ERROR_CODE, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
// ... service call
|
||||
}
|
||||
```
|
||||
|
||||
Keep `preCheck*` functions in the same file as the handler. They bind, validate, and return the typed request struct or an error.
|
||||
Keep `preCheck*` functions in the same file as the handler. They take the already-bound request struct pointer (never `ctx`) and return `error`, or `(extra, error)` when the caller also needs derived data — e.g. `preCheckJobRequest(req *models.JobSubmitRequest) ([]int, error)`, `preCheckHostControlRequest(req *models.HostControlRequest) (bool, error)`. They never bind the request themselves and never return the request struct — binding is always the separate `utils.BindJSONStrict` step shown above. Note that handlers choose the response code for bind/precheck failures per-endpoint; `common.ERROR_CODE` (500) and `common.INVALID_PARAMS_CODE` (400) both appear in practice depending on the handler.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue