Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when adding or changing a Go HTTP endpoint — Fiber v2 or v3 (detect which), thin handlers, central error mapping, boundary validation; the same rules apply to net/http, chi, echo or gin
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
A handler is a translator: HTTP in → service call → HTTP out. Business logic never lives there. The recurring defects are fat handlers, per-handler error mapping that drifts, endpoints that quietly drop the auth middleware their neighbors have, and copying a value Fiber is about to reuse.
Core principle: handlers parse, validate, delegate, and map. Nothing else.
grep -E 'gofiber/fiber/v[23]|go-chi/chi|labstack/echo|gin-gonic/gin' go.mod
Never change the router or the Fiber major version in a feature task; a repo on Fiber v2 stays v2 (security-fix branch only). A brand-new repo with no router yet gets Fiber v3 (needs Go ≥1.25) unless the task says otherwise.
| v2 | v3 | |
|---|---|---|
| Handler signature | func(c *fiber.Ctx) error | func(c fiber.Ctx) error |
| Body | c.BodyParser(&req) | c.Bind().Body(&req) |
| Query / params | c.QueryParser / c.ParamsParser | c.Bind().Query / c.Bind().URI |
| Struct tag for path params | params: | uri: |
| Typed query helper | c.QueryInt("limit", 20) | fiber.Query[int](c, "limit", 20) |
| Go-standard request context | c.UserContext() | c.Context() |
| Raw fasthttp context | c.Context() (returns *fasthttp.RequestCtx) | c.RequestCtx() |
| Request id from context | c.Locals("requestid") | requestid.FromContext(c) |
| Static files / sub-app mount | app.Static(...) / app.Mount(...) | static.New(...) / app.Use(...) |
fiber migrate --to v3 exists for a dedicated upgrade task; never fold a framework-major bump into a feature task.
The v2 bug this corrects: on Fiber v2, c.Context() returns the pooled *fasthttp.RequestCtx, not the request-scoped context.Context — passing it where a context.Context is expected either fails to compile or silently drops whatever middleware put into the real context (auth claims, request id, trace span). Use c.UserContext() on v2.
map[string]any.go-playground/validator v10 if the repo already uses it; v3 has a StructValidator hook). Reject early with 4xx and a field-specific message in the repo's one error shape (see api-design-conventions).ErrorHandler / mapper), not per handler, so the mapping can't drift. Show it mapping errors.Is/errors.As against domain sentinel errors to status + the error body.c.Params/c.Query/c.Body/c.Get are only valid for the lifetime of the handler call — Fiber reuses the underlying buffer across requests. strings.Clone (or otherwise copy) anything you store in a struct that outlives the request, send to a goroutine, or put in a cache, unless the app is configured with Immutable: true.fiber.Config{BodyLimit: ...} (v2/v3 default 4 MB) or http.MaxBytesReader on net/http — don't rely on the default alone for upload endpoints.mux.HandleFunc("POST /tasks/{id}/children", h.CreateChild)
id := r.PathValue("id")
r.Body = http.MaxBytesReader(w, r.Body, maxBody)
func (h *TaskHandler) Create(c fiber.Ctx) error {
var req createTaskRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid body")
}
if err := req.validate(); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
task, err := h.svc.Create(c.Context(), req.Title)
if err != nil {
return err
}
return c.Status(fiber.StatusCreated).JSON(taskResponseFrom(task))
}
The title-length rule lives in the service/domain, not the handler. The central error middleware maps domain.ErrInvalidTitle → 400, domain.ErrConflict → 409 — every handler benefits.
req := httptest.NewRequest(http.MethodPost, "/tasks", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, err := app.Test(req) // v2: app.Test(req, -1)
// v3: app.Test(req, fiber.TestConfig{Timeout: 0})
Assert status code and decoded body — this is still a unit test; it does not replace running the real service once (backend-runtime-check).
map[string]any request/response instead of DTOs.c.Params/c.Query/c.Body past the handler without copying it first.c.Context() where the request's context.Context is needed.pgx/repository calls inside a handler.c.Body()/c.Params().아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.