本文へ移動
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(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

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

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

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

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

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/tasktrooper1122026年10月11日 更新

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

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

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/tasktrooper1122026年10月11日 更新

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/tasktrooper1122026年10月11日 更新

Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

makifbaysal のスキルをすべて見る

このスキルの問題を報告する