Menulis handler, struct request-response, dan routing HTTP secara manual berisiko menimbulkan desinkronisasi antara dokumentasi API dan implementasi kode. Pendekatan contract-first menggunakan OpenAPI 3.0 mengeliminasi masalah ini. Tool oapi-codegen mengotomatisasi pembuatan tipe data (types), interface handler, dan registrasi router langsung ke framework Go Fiber.
1. Spesifikasi OpenAPI 3.0
Definisikan kontrak API pada file api/spec.yaml. Contoh endpoint pembuatan pengguna:
openapi: "3.0.3"
info:
title: User API
version: "1.0.0"
paths:
/users:
post:
summary: Buat user baru
operationId: CreateUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: User berhasil dibuat
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
components:
schemas:
CreateUserRequest:
type: object
required: [name, email]
properties:
name:
type: string
email:
type: string
format: email
UserResponse:
type: object
required: [id, name, email]
properties:
id:
type: string
name:
type: string
email:
type: string2. Konfigurasi oapi-codegen untuk Fiber
Buat file oapi-codegen.yaml di root project. Konfigurasi ini memerintahkan generator membuat struct data dan adaptor router berbasis Go Fiber.
package: api
output: internal/api/api.gen.go
generate:
- types
- fiber
- spec3. Otomasi Generasi via go:generate
Lacak dependensi generator menggunakan tools.go agar versi binary seragam di seluruh mesin tim:
//go:build tools
package tools
import (
_ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
)Tambahkan directive generator pada file root paket atau file terpisah seperti generate.go:
package main
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=oapi-codegen.yaml api/spec.yamlJalankan perintah berikut untuk menghasilkan kode:
go generate ./...File internal/api/api.gen.go akan terbuat, berisi interface ServerInterface dan fungsi RegisterHandlers.
4. Implementasi Handler Berbasis Interface
Buat struct yang mengimplementasikan interface api.ServerInterface. Kompiler Go akan memvalidasi apakah semua rute OpenAPI sudah ditangani.
package main
import (
"github.com/gofiber/fiber/v2"
"example.com/project/internal/api"
)
type UserHandler struct{}
func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
var req api.CreateUserRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
}
// ponytail: direct struct binding without domain abstraction; upgrade when persistence layer exists.
res := api.UserResponse{
Id: "usr-1001",
Name: req.Name,
Email: req.Email,
}
return c.Status(fiber.StatusCreated).JSON(res)
}
func main() {
app := fiber.New()
handler := &UserHandler{}
// Pasang router otomatis hasil generate
api.RegisterHandlers(app, handler)
if err := app.Listen(":8080"); err != nil {
panic(err)
}
}5. Verifikasi Kontrak API pada CI (GitHub Actions)
Cegah drift antara kontrak OpenAPI dan kode Go yang ter-commit. Workflow CI mengeksekusi go generate dan mengecek perubahan workspace menggunakan git diff --exit-code.
name: Verify API Codegen
on:
pull_request:
branches: [main]
jobs:
check-codegen:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Run Codegen
run: go generate ./...
- name: Check Git Status
run: |
git diff --exit-code || (echo "Contract drift detected: Run 'go generate ./...' locally and commit the generated files." && exit 1)Catatan: Perintahgit diff --exit-codemengembalikan return code0jika tidak ada perubahan, dan1jika ada file yang berubah atau belum di-commit. Langkah ini memastikan pull request ditolak jika developer mengubahapi/spec.yamltanpa menyertakan hasil regenerasi kode.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!