[Go] swag를 이용한 RESTful API 문서화
Updated:
설명
- https://github.com/swaggo/swag
- Go 주석을 swagger 문서 2.0으로 변환
- 명령어
- swag 설치
go install github.com/swaggo/swag/cmd/swag@latest
- init
- 구문 분석 및 doc 생성
- 의존성이 없는 경우
~/go/bin/swag init
- 의존성이 있는 경우
- 다른 패키지의 구조체를 요청이나 응답으로 사용하는 경우 등
~/go/bin/swag init --parseDependency
- fmt
- swag 주석에 swag 포맷 적용
~/go/bin/swag init
- swag 설치
- Swagger UI
ip:port/swagger/index.html
을 통해 접근 가능- api 확인 및 테스트 가능
예제
- 코드
package main import ( "context" "net/http" "os" "os/signal" "sync" "syscall" "time" "test/docs" "github.com/gorilla/mux" httpSwagger "github.com/swaggo/http-swagger" ) var server *http.Server type TestPostRequest struct { Field1 string `json:"field_1",omitempty example:"value"` } type ResponseSuccess struct { Field1 string `json:"field_1"` } type ResponseFailure struct { Cause string `json:"cause"` } func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { println(r.RequestURI, r.Method, "start") defer println(r.RequestURI, r.Method, "end") next.ServeHTTP(w, r) }) } // @Summary get test // @Description get test // @Accept json // @Produce json // @Param param_1 query string true "param_1 selection" Enums(1, 2, 3) // @Param param_2 query string true "param_2 selection" Enums(A, B, C, D) default(A) // @Param param_3 query string true "param_3" default(AAA) // @Param id path string true "id" default(id_1) // @Success 200 {object} ResponseSuccess // @Failure default {object} ResponseFailure // @Router /v1/test/{id} [get] // @tags test func testGet(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{"field_1" : "get ok"}`)) } // @Summary post test // @Description post test // @Accept json // @Produce json // @Param id path string true "id" default(aaa) // @Param request body TestPostRequest true "country selection" // @Success 200 {object} ResponseSuccess // @Failure default {object} ResponseFailure // @Router /v1/test [post] // @tags test func testPost(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{"cause" : "post fail"}`)) } func run(wg *sync.WaitGroup, done chan int) { defer wg.Done() go finalize(done) docs.SwaggerInfo.Version = "1.0" docs.SwaggerInfo.Host = "127.0.0.1:10000" docs.SwaggerInfo.BasePath = "" docs.SwaggerInfo.Title = "test" docs.SwaggerInfo.Description = "test" router := mux.NewRouter() router.Use(loggingMiddleware) router.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler) router.HandleFunc("/v1/test/{id:[a-z,A-Z][a-z,A-Z,0-9,--,_,.]+}", testGet).Methods("GET") router.HandleFunc("/v1/test", testPost).Methods("POST") server = &http.Server{ Addr: ":10000", Handler: router} server.ListenAndServe() } func finalize(done chan int) { for len(done) == 1 { time.Sleep(1 * time.Second) } if server != nil { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) cancel() server.Shutdown(ctx) } } func main() { var wg sync.WaitGroup done := make(chan int, 1) done <- 1 signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) wg.Add(1) go run(&wg, done) <-signals <-done wg.Wait() }
- 실행 결과