API Documentation

บทความโดย ผศ.ดร.ณัฐโชติ พรหมฤทธิ์ และ อ.ดร.สัจจาภรณ์ ไวจรรยา
ภาควิชาคอมพิวเตอร์
คณะวิทยาศาสตร์
มหาวิทยาลัยศิลปากร

การสร้าง API Document ใน Go สามารถทำได้โดยใช้เครื่องมือที่ช่วยในการสร้างเอกสาร เช่น Swaggo ซึ่งได้รับความนิยมในชุมชนชาว Go เนื่องจากใช้งานง่ายและสามารถสร้างเอกสารแบบ Interactive ได้โดยอัตโนมัติจาก Code ที่เราเขียน

Swaggo จะช่วยแปลงคำสั่งหลัง Comment ใน Go เป็น OpenAPI Specification เพื่อนำมาแสดงผลเป็น API Document บน Browser

OpenAPI Specification (OAS) ซึ่งเดิมมาจากโครงการ Swagger คือ มาตรฐานกลางสำหรับการออกแบบและอธิบาย RESTful API โดยมีการกำหนดรูปแบบ (Format) ในการบรรยาย Endpoint, Method, Parameter, Request Body, Response Body และ Authentication ฯลฯ ทำให้ผู้พัฒนา API และผู้ใช้งาน API สามารถสื่อสารและทำงานร่วมกันได้ง่ายขึ้น

เมื่อทีมพัฒนาใหญ่ขึ้น API Document จึงเป็นตัวกลางในการสื่อสารเพื่อลดปัญหาความเข้าใจไม่ตรงกันระหว่างทีม Frontend, Backend และ QA หรือผู้ใช้งานภายนอกได้

โดย OAS ได้รับการยอมรับในระดับสากลและถูกใช้งานแพร่หลายกับ RESTful API ได้เกือบทุกภาษาและ Framework

OAS ถูกเก็บในรูปแบบ JSON หรือ YAML (เช่น swagger.yaml) โดยมีโครงสร้างสำคัญ เช่น

openapi: ระบุ version ของ OAS เช่น 3.1.0
info: ข้อมูลเกี่ยวกับ API เช่น ชื่อ, เวอร์ชัน, คำอธิบาย
paths: รวม Endpoint ทั้งหมด เช่น GET /users, POST /users
components: ข้อมูลที่ใช้ร่วมกันอย่างเช่น Schemas (Model), Security Definitions (การกำหนด Bearer Token และ BasicAuth ฯลฯ)

openapi: 3.1.0
info:
  title: My API
  version: "1.0.0"
paths:
  /users:
    get:
      summary: Get all users
      operationId: getUsers
      responses:
        '200':
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
  /users/{userId}:
    get:
      summary: Get user by ID
      operationId: getUserById
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: A single user
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
swagger.yaml

โดยเราสามารถใช้เครื่องมืออย่างเช่น Swagger UI หรือ Redoc ในการอ่าน File แล้วแปลงเป็นหน้า Web ของ API Document โดยไม่ต้องเขียนเอกสารเอง

Swagger UI

เราสามารถใช้ Swagger UI แปลง File swagger.yaml ไปเปิดบน Browser ได้ โดยการรัน Swagger UI บน Docker Container ตามขั้นตอนต่อไปนี้

  • สร้าง Folder Project เช่น api_docs และ File ต่าง ๆ ตามโครงสร้างต่อไปนี้
api_docs 
├── docker-compose.yml
└── swagger.yaml
  • แก้ไข File docker-compose.yml
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    container_name: swagger-ui
    ports:
      - "8888:8080"
    environment:
      - SWAGGER_JSON=/docs/swagger.yaml
    volumes:
      - ./swagger.yaml:/docs/swagger.yaml
  • แก้ไข File swagger.yaml ตามตัวอย่างด้านบน
  • Deploy Swagger UI ด้วยคำสั่ง docker-compose up -d
  • ตรวจสอบ Container ที่รันด้วยคำสั่ง docker-compose ps
  • เปิด Browser ไปที่ http://localhost:8888 จะเห็นหน้า Web ของ Swagger UI ดังตัวอย่างต่อไปนี้

Redoc

Redoc เป็นอีกหนึ่งเครื่องมือยอดนิยมในการแปลง File แบบ OAS ให้เป็นหน้า Web ของ API Document ที่มี Design สวยงามและอ่านง่ายกว่า Swagger UI แต่ไม่มีปุ่ม Try it out แบบ Swagger UI

เราสามารถ Build หน้า Web เป็น File HTML แล้วแจกจ่ายให้ทีม หรือ Deploy บน Server เอง

ขั้นตอนการ Build หน้า Web

  • ติดตั้ง @redocly/cli ผ่าน npm
npm install -g @redocly/cli

หมายเหตุ หากยังไม่มี npm ให้ติดตั้งตามระบบปฏิบัติการดังต่อไปนี้

macOS

brew install node

Linux (Ubuntu, Debian ฯลฯ)

sudo apt update
sudo apt install nodejs npm

Windows

- ไปที่ https://nodejs.org
- เลือกรุ่นที่ต้องการติดตั้ง โดยปกติแนะนำให้เลือก LTS (Long-Term Support) เพื่อความเสถียร
- Download File ติดตั้ง (นามสกุล .msi) ที่รองรับสถาปัตยกรรมของ Windows
- ดับเบิลคลิก File .msi ที่ Download มา
- กด Next ไปเรื่อย ๆ และกดยืนยันให้ Setup ติดตั้งจนเสร็จสิ้น

ตรวจสอบ Version ของ npm ด้วยคำสั่ง node -v

  • สั่ง Generate เอกสารจาก File OAS ของเรา
redocly build-docs swagger.yaml

Redocly จะสร้าง File redoc-static.html ใน Folder ปัจจุบัน

  • เปิด redoc-static.html ใน Browser ก็จะเห็น API Document ตามสไตล์ Redoc หรือจะ Upload redoc-static.html ขึ้น Server ที่ต้องการก็ได้

Swagger UI vs Redoc

การทำ API Document ใน Go

Swaggo เป็น Library สำหรับสร้างเอกสาร Swagger (เช่น swagger.yaml) โดยอัตโนมัติจากการใส่ Comment ใน Code ของ Go

ขั้นตอนการใช้งาน Swaggo

  • สร้าง Folder Project เช่น simple_api และ File ต่าง ๆ ตามโครงสร้างต่อไปนี้
simple_api
├── cmd
│   └── main.go
└── internal
    └── handler
        └── user_handler.go
  • สร้าง Module ชื่อ users
go mod init users
  • ติดตั้ง Swaggo
// Compile Package เป็น Binary และติดตั้งใน $HOME/go/bin
go install github.com/swaggo/swag/cmd/swag@latest

go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files

macOS

  • ตรวจสอบ File swag โดยปกติ Fileswag จะถูกติดตั้งใน Folder $HOME/go/bin
ls -l $HOME/go/bin
  • เพิ่ม Folder $HOME/go/bin ลงใน $PATH โดยแก้ไข File ~/.zshrc (File ตั้งค่าของ Zsh Shell) ด้วยคำสั่ง
vi ~/.zshrc

//เพิ่มบรรทัดนี้
export PATH=$PATH:$HOME/go/bin
  • บันทึก File แล้ว Reload การตั้งค่า Shell
source ~/.zshrc

Windows

  • ตรวจสอบตำแหน่ง $HOME\go\bin โดยค่าเริ่มต้น File Binary จะอยู่ใน C:\Users\<username>\go\bin
  • เพิ่ม $HOME\go\bin ลงใน Environment Variables โดย
- เปิด Environment Variables (กดปุ่ม Win + S แล้วพิมพ์ Environment Variables)
- คลิก Edit the system environment variables
- ที่หน้าต่าง System Properties เลือก Environment Variables
- เลือก Path ในส่วน User variables หรือ System variables (ขึ้นอยู่กับว่าต้องการเพิ่มแบบส่วนตัวหรือสำหรับทุกผู้ใช้)
- คลิก Edit และเพิ่ม Path $HOME\go\bin
- กด OK เพื่อบันทึกการตั้งค่า
- เปิด Command Prompt ใหม่ (การตั้งค่า PATH จะมีผลเมื่อเปิด Command Prompt หรือ PowerShell ใหม่เท่านั้น)

ตรวจสอบการติดตั้ง

swag --version
  • เพิ่ม Comment เพื่ออธิบาย API ในแต่ละ Endpoint ของ Gin Framework ตามรูปแบบของ Swaggo ดังตัวอย่างต่อไปนี้
package handler

import "github.com/gin-gonic/gin"

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

type ErrorResponse struct {
	Message string `json:"message"`
}

// @Summary Get user by ID
// @Description Get details of a user by ID
// @Tags Users
// @Produce  json
// @Param   id   path      int     true  "User ID"
// @Success 200  {object}  User
// @Failure 404  {object}  ErrorResponse
// @Router  /users/{id} [get]
func GetUserByID(c *gin.Context) {
	id := c.Param("id")
	c.JSON(200, gin.H{"id": id, "name": "ณัฐโชติ พรหมฤทธิ์"})
}
user_handler.go
  • เพิ่ม Swagger UI เป็น Endpoint หนึ่งใน Project เช่น
package main

import (
	_ "users/docs" // ให้ Swag สร้างเอกสารใน Folder docs โดยอัตโนมัติ

	"users/internal/handler"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

// @title           Simple API Example
// @version         1.0
// @description     This is a simple example of using Gin with Swagger.
// @host            localhost:8080
// @BasePath        /api/v1
func main() {
	r := gin.Default()

	// Swagger endpoint
	r.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// User API routes
	api := r.Group("/api/v1")
	{
		api.GET("/users/:id", handler.GetUserByID) // ใช้ Handler จากไฟล์ user_handler.go
	}

	// Start server
	r.Run(":8080")
}
main.go

คำสั่งหลัง Comment ของ Swaggo

- @title สำหรับระบุชื่อ Project หรือ API ที่จะแสดงในหน้าเอกสารของ Swagger

- @version ระบุ Version ของ API หรือ Project

- @description สำหรับอธิบายภาพรวม หรือจุดประสงค์ของ API

- @host ระบุ hostname หรือโดเมนของ API ที่ Swagger จะเรียกใช้งาน ในที่นี้เราใช้ localhost:8080 ซึ่งหมายถึงรันที่เครื่องเราเองที่ port 8080

- @BasePath ระบุ Path หลัก (Base Path) ของ API ในตัวอย่างคือ "/api/v1" ซึ่งการเรียก API ทั้งหมดจะถูก prefix ด้วย /api/v1 (เช่น /api/v1/users)

- @Summary สำหรับการอธิบายสั้น ๆ ถึงจุดประสงค์ของ API Endpoints เช่น Get user by ID (เป็นข้อความย่อ ๆ ที่จะแสดงในเอกสาร Swagger)

- @Description รายละเอียดขยายความของ API Endpoint เช่น Get details of a user by ID (เป็นรายละเอียดเพิ่มเติม แสดงในหน้ารายละเอียดแต่ละ Endpoint)

- @Tags ใช้สำหรับจัดกลุ่มให้ API Endpoint โดย Swagger จะจัดกลุ่ม API ที่มี Tag เดียวกันเข้าด้วยกัน

- @Produce ระบุชนิดของข้อมูล (Content-Type) ที่ API ส่งกลับมา เช่น json, xml หรืออื่น ๆ

- @Param สำหรับระบุชื่อ Parameter ที่รับเข้ามา (name) ลักษณะการใช้งาน (path, query หรือ body ฯลฯ) ชนิดข้อมูล (int หรือ string ฯลฯ) บังคับหรือไม่ (true/false) และคำอธิบาย (“User ID”)

- @Success ระบุโครงสร้างข้อมูลตอบกลับในกรณีที่ Request สำเร็จ ซึ่ง {object} User หมายถึงส่งค่าออกมาเป็น JSON Object โดยโครงสร้างของ object จะดูจาก struct User ที่มีการประกาศไว้

- @Failure ระบุโครงสร้างข้อมูลตอบกลับในกรณีที่เกิดข้อผิดพลาด โดย {object} ErrorResponse หมายถึงจะส่งค่าออกมาเป็น JSON Object โดยโครงสร้างใช้ struct ErrorResponse

- @Router ระบุ Endpoint URL และ HTTP Method ที่ใช้
  • จัดระเบียบ Dependency ด้วยคำสั่ง go mod tidy
  • Generate เอกสาร โดยรันคำสั่ง swag init ใน root ของ Project
swag init -g cmd/main.go
  • Compile Code
go build cmd/main.go
  • รัน Program และทดสอบ Swagger UI โดยเปิด Browser แล้วไปที่ http://localhost:8080/docs/index.html เพื่อดู API Document ที่สร้างขึ้น
  • ทดลองยิง API เส้น /users/{id} ของเรา โดยกด Try it out ใส่ User ID แล้วกด Execute

สร้าง API Document ด้วย Redoc

ใช้ Redoc เพื่อสร้างเอกสารแบบสวยงาม

  • ไปที่ Folder docs แล้วใช้คำสั่ง redocly build-docs เพื่อสร้าง API Document
redocly build-docs swagger.yaml
  • เปิด redoc-static.html ใน Browser จะเห็น API Document ของเราตามสไตล์ Redoc