跳到正文
cccskills
免费在 GitHub 公开

fiber-rest-api

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

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(1)

  • SKILL.md5.7 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Go HTTP Endpoint Patterns

Overview

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.

Detect the repo's router and framework version first

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.

Fiber v2 → v3

v2v3
Handler signaturefunc(c *fiber.Ctx) errorfunc(c fiber.Ctx) error
Bodyc.BodyParser(&req)c.Bind().Body(&req)
Query / paramsc.QueryParser / c.ParamsParserc.Bind().Query / c.Bind().URI
Struct tag for path paramsparams:uri:
Typed query helperc.QueryInt("limit", 20)fiber.Query[int](c, "limit", 20)
Go-standard request contextc.UserContext()c.Context()
Raw fasthttp contextc.Context() (returns *fasthttp.RequestCtx)c.RequestCtx()
Request id from contextc.Locals("requestid")requestid.FromContext(c)
Static files / sub-app mountapp.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.

Rules

  • Thin handlers: parse/validate input → call the application service → map result to response DTO. No business logic, no SQL, no cross-entity rules in the handler.
  • Explicit DTO structs aligned with domain types — never map[string]any.
  • Validate and bound all input at the boundary: lengths, ranges, enum values, UUID parsing (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).
  • Map domain errors to status in ONE place (a shared 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.
  • New endpoints get the SAME middleware chain (auth, logging, request-id) as their neighbors — copy the adjacent route's wiring, don't invent one.
  • Zero-allocation rule (Fiber-specific): values Fiber hands you from 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.
  • Bound the request body: fiber.Config{BodyLimit: ...} (v2/v3 default 4 MB) or http.MaxBytesReader on net/http — don't rely on the default alone for upload endpoints.

net/http (Go ≥1.22, when the repo has no router)

mux.HandleFunc("POST /tasks/{id}/children", h.CreateChild)
id := r.PathValue("id")
r.Body = http.MaxBytesReader(w, r.Body, maxBody)

Worked Example

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.

Handler test in-process (no network)

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).

Common Mistakes

  • Business logic or SQL in the handler.
  • map[string]any request/response instead of DTOs.
  • Each handler mapping its own errors to codes → drift.
  • A new route missing the auth middleware its neighbors have.
  • 500 for a validation failure.
  • Storing a value read from c.Params/c.Query/c.Body past the handler without copying it first.
  • Passing v2's c.Context() where the request's context.Context is needed.

Red Flags

  • A handler longer than ~30 lines.
  • pgx/repository calls inside a handler.
  • A route registered without the neighbor's middleware chain.
  • A struct field or goroutine capturing a byte slice straight from c.Body()/c.Params().

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

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

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

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

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

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.

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

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

中文简介正在准备中。当前显示原文说明。

makifbaysal/tasktrooper1172026年10月18日 更新

查看 makifbaysal 的全部技能

报告此技能的问题