{"id":13414085,"url":"https://github.com/zc2638/swag","last_synced_at":"2026-01-23T02:14:56.867Z","repository":{"id":57550312,"uuid":"308492021","full_name":"zc2638/swag","owner":"zc2638","description":"No comments, simple go wrapper to create swagger 2.0 compatible APIs. Support most routing frameworks, such as built-in, gin, chi, mux, echo, httprouter, fasthttp and more.","archived":false,"fork":false,"pushed_at":"2024-05-01T18:33:56.000Z","size":3415,"stargazers_count":46,"open_issues_count":1,"forks_count":7,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-07-31T20:53:21.792Z","etag":null,"topics":["chi-swagger","echo-swagger","fasthttp-swagger","gin-swagger","httprouter-swagger","rest","swagger","swagger-docs","swagger-ui"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zc2638.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-30T01:21:57.000Z","updated_at":"2024-07-22T05:04:20.000Z","dependencies_parsed_at":"2023-01-22T18:01:01.692Z","dependency_job_id":"10a39e66-b79b-4f89-8f5e-8ceae9203c5e","html_url":"https://github.com/zc2638/swag","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/zc2638/swag","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zc2638%2Fswag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zc2638%2Fswag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zc2638%2Fswag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zc2638%2Fswag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zc2638","download_url":"https://codeload.github.com/zc2638/swag/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zc2638%2Fswag/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28677729,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T01:00:35.747Z","status":"online","status_checked_at":"2026-01-23T02:00:08.296Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chi-swagger","echo-swagger","fasthttp-swagger","gin-swagger","httprouter-swagger","rest","swagger","swagger-docs","swagger-ui"],"created_at":"2024-07-30T20:01:57.213Z","updated_at":"2026-01-23T02:14:56.840Z","avatar_url":"https://github.com/zc2638.png","language":"Go","funding_links":[],"categories":["Third-party APIs","第三方api"],"sub_categories":["Utility/Miscellaneous","实用程序/Miscellaneous"],"readme":"# swag\n\n![LICENSE](https://img.shields.io/github/license/zc2638/swag.svg?style=flat-square\u0026color=blue)\n[![GoDoc](https://godoc.org/github.com/zc2638/swag?status.svg)](https://godoc.org/github.com/zc2638/swag)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/zc2638/swag/main.yaml?branch=main\u0026style=flat-square)](https://github.com/zc2638/swag/actions)\n[![Go Report Card](https://goreportcard.com/badge/github.com/zc2638/swag?style=flat-square)](https://goreportcard.com/report/github.com/zc2638/swag)\n[![codecov](https://img.shields.io/codecov/c/github/zc2638/swag/main?logo=codecov\u0026style=flat-square)](https://codecov.io/gh/zc2638/swag)\n\nEnglish | [简体中文](./README_zh.md)\n\n```swag``` is a lightweight library to generate swagger json for Golang projects.\n\n```swag``` is heavily geared towards generating REST/JSON apis.\n\nNo code generation, no framework constraints, just a simple swagger definition.\n\n## Dependency\n\nGolang 1.16+\n\n## Installation\n\n```shell\ngo get -u github.com/zc2638/swag@v1.5.1\n```\n\n**Tip:** As of `v1.2.0`, lower versions are no longer compatible. In order to be compatible with most web frameworks,\nthe overall architecture has been greatly changed.\n\n## Default Swagger UI Server\n\n```go\nfunc main() {\n    handle := swag.UIHandler(\"/swagger/ui\", \"\", false)\n    patterns := swag.UIPatterns(\"/swagger/ui\")\n    for _, pattern := range patterns {\n        http.DefaultServeMux.Handle(pattern, handle)\n    }\n    \n    log.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n```\n\nso you can visit for UI: `http://localhost:8080/swagger/ui`\n\n## Examples\n\n### definition\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\n\t\"github.com/zc2638/swag\"\n\t\"github.com/zc2638/swag/endpoint\"\n\t\"github.com/zc2638/swag/option\"\n)\n\n// Category example from the swagger pet store\ntype Category struct {\n\tID     int64  `json:\"category\"`\n\tName   string `json:\"name\" enum:\"dog,cat\" required:\"\"`\n\tExists *bool  `json:\"exists\" required:\"\"`\n}\n\n// Pet example from the swagger pet store\ntype Pet struct {\n\tID        int64     `json:\"id\"`\n\tCategory  *Category `json:\"category\" desc:\"分类\"`\n\tName      string    `json:\"name\" required:\"\" example:\"张三\" desc:\"名称\"`\n\tPhotoUrls []string  `json:\"photoUrls\"`\n\tTags      []string  `json:\"tags\" desc:\"标签\"`\n}\n\nfunc handle(w http.ResponseWriter, r *http.Request) {\n\t_, _ = io.WriteString(w, fmt.Sprintf(\"[%s] Hello World!\", r.Method))\n}\n\nfunc main() {\n\tapi := swag.New(\n\t\toption.Title(\"Example API Doc\"),\n\t\toption.Security(\"petstore_auth\", \"read:pets\"),\n\t\toption.SecurityScheme(\"petstore_auth\",\n\t\t\toption.OAuth2Security(\"accessCode\", \"http://example.com/oauth/authorize\", \"http://example.com/oauth/token\"),\n\t\t\toption.OAuth2Scope(\"write:pets\", \"modify pets in your account\"),\n\t\t\toption.OAuth2Scope(\"read:pets\", \"read your pets\"),\n\t\t),\n\t)\n\tapi.AddEndpoint(\n\t\tendpoint.New(\n\t\t\thttp.MethodPost, \"/pet\",\n\t\t\tendpoint.Handler(handle),\n\t\t\tendpoint.Summary(\"Add a new pet to the store\"),\n\t\t\tendpoint.Description(\"Additional information on adding a pet to the store\"),\n\t\t\tendpoint.Body(Pet{}, \"Pet object that needs to be added to the store\", true),\n\t\t\tendpoint.Response(http.StatusOK, \"Successfully added pet\", endpoint.SchemaResponseOption(Pet{})),\n\t\t\tendpoint.Security(\"petstore_auth\", \"read:pets\", \"write:pets\"),\n\t\t),\n\t\tendpoint.New(\n\t\t\thttp.MethodGet, \"/pet/{petId}\",\n\t\t\tendpoint.Handler(handle),\n\t\t\tendpoint.Summary(\"Find pet by ID\"),\n\t\t\tendpoint.Path(\"petId\", \"integer\", \"ID of pet to return\", true),\n\t\t\tendpoint.Response(http.StatusOK, \"successful operation\", endpoint.SchemaResponseOption(Pet{})),\n\t\t\tendpoint.Security(\"petstore_auth\", \"read:pets\"),\n\t\t),\n\t\tendpoint.New(\n\t\t\thttp.MethodPut, \"/pet/{petId}\",\n\t\t\tendpoint.Handler(handle),\n\t\t\tendpoint.Path(\"petId\", \"integer\", \"ID of pet to return\", true),\n\t\t\tendpoint.Security(\"petstore_auth\", \"read:pets\"),\n\t\t\tendpoint.ResponseSuccess(endpoint.SchemaResponseOption(struct {\n\t\t\t\tID   string `json:\"id\"`\n\t\t\t\tName string `json:\"name\"`\n\t\t\t}{})),\n\t\t),\n\t)\n\n\t...\n}\n\n```\n\n### built-in\n\n```go\nfunc main() {\n    ...\n    // Note: Built-in routes cannot automatically resolve path parameters.\n    for p, endpoints := range api.Paths {\n        http.DefaultServeMux.Handle(path.Join(api.BasePath, p), endpoints)\n    }\n    http.DefaultServeMux.Handle(\"/swagger/json\", api.Handler())\n    patterns := swag.UIPatterns(\"/swagger/ui\")\n    for _, pattern := range patterns {\n        http.DefaultServeMux.Handle(pattern, swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true))\n    }\n    \n    log.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n### gin\n\n```go\nfunc main() {\n    ...\n    \n    router := gin.New()\n    api.Walk(func (path string, e *swag.Endpoint) {\n        h := e.Handler.(http.Handler)\n        path = swag.ColonPath(path)\n        \n        router.Handle(e.Method, path, gin.WrapH(h))\n    })\n    \n    // Register Swagger JSON route\n    router.GET(\"/swagger/json\", gin.WrapH(api.Handler()))\n    \n    // Register Swagger UI route\n    // To take effect, the swagger json route must be registered\n    router.GET(\"/swagger/ui/*any\", gin.WrapH(swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true)))\n    \n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### chi\n\n```go\nfunc main() {\n    ...\n    \n    router := chi.NewRouter()\n    api.Walk(func (path string, e *swag.Endpoint) {\n        router.Method(e.Method, path, e.Handler.(http.Handler))\n    })\n    router.Handle(\"/swagger/json\", api.Handler())\n    router.Mount(\"/swagger/ui\", swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true))\n    \n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### mux\n\n```go\nfunc main() {\n    ...\n    \n    router := mux.NewRouter()\n    api.Walk(func (path string, e *swag.Endpoint) {\n        h := e.Handler.(http.HandlerFunc)\n        router.Path(path).Methods(e.Method).Handler(h)\n    })\n    \n    router.Path(\"/swagger/json\").Methods(\"GET\").Handler(api.Handler())\n    router.PathPrefix(\"/swagger/ui\").Handler(swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true))\n    \n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### echo\n\n```go\nfunc main() {\n    ...\n    \n    router := echo.New()\n    api.Walk(func (path string, e *swag.Endpoint) {\n        h := echo.WrapHandler(e.Handler.(http.Handler))\n        path = swag.ColonPath(path)\n        \n        switch strings.ToLower(e.Method) {\n        case \"get\":\n            router.GET(path, h)\n        case \"head\":\n            router.HEAD(path, h)\n        case \"options\":\n            router.OPTIONS(path, h)\n        case \"delete\":\n            router.DELETE(path, h)\n        case \"put\":\n            router.PUT(path, h)\n        case \"post\":\n            router.POST(path, h)\n        case \"trace\":\n            router.TRACE(path, h)\n        case \"patch\":\n            router.PATCH(path, h)\n        case \"connect\":\n            router.CONNECT(path, h)\n        }\n    })\n    \n    router.GET(\"/swagger/json\", echo.WrapHandler(api.Handler()))\n    router.GET(\"/swagger/ui/*\", echo.WrapHandler(swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true)))\n    \n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### httprouter\n\n```go\nfunc main() {\n    ...\n    \n    router := httprouter.New()\n    api.Walk(func (path string, e *swag.Endpoint) {\n        h := e.Handler.(http.Handler)\n        path = swag.ColonPath(path)\n        router.Handler(e.Method, path, h)\n    })\n    \n    router.Handler(http.MethodGet, \"/swagger/json\", api.Handler())\n    router.Handler(http.MethodGet, \"/swagger/ui/*any\", swag.UIHandler(\"/swagger/ui\", \"/swagger/json\", true))\n    \n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### fasthttp\n\n```go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/fasthttp/router\"\n\t\"github.com/valyala/fasthttp\"\n\n\t\"github.com/zc2638/swag\"\n\t\"github.com/zc2638/swag/asserts\"\n\t\"github.com/zc2638/swag/endpoint\"\n\t\"github.com/zc2638/swag/option\"\n)\n\n// Category example from the swagger pet store\ntype Category struct {\n\tID     int64  `json:\"category\"`\n\tName   string `json:\"name\" enum:\"dog,cat\" required:\"\"`\n\tExists *bool  `json:\"exists\" required:\"\"`\n}\n\n// Pet example from the swagger pet store\ntype Pet struct {\n\tID        int64     `json:\"id\"`\n\tCategory  *Category `json:\"category\" desc:\"分类\"`\n\tName      string    `json:\"name\" required:\"\" example:\"张三\" desc:\"名称\"`\n\tPhotoUrls []string  `json:\"photoUrls\"`\n\tTags      []string  `json:\"tags\" desc:\"标签\"`\n}\n\nfunc handle(ctx *fasthttp.RequestCtx) {\n\tstr := fmt.Sprintf(\"[%s] Hello World!\", string(ctx.Method()))\n\t_, _ = ctx.Write([]byte(str))\n}\n\nfunc main() {\n\tpost := endpoint.New(\"post\", \"/pet\", endpoint.Summary(\"Add a new pet to the store\"),\n\t\tendpoint.Handler(handle),\n\t\tendpoint.Description(\"Additional information on adding a pet to the store\"),\n\t\tendpoint.Body(Pet{}, \"Pet object that needs to be added to the store\", true),\n\t\tendpoint.Response(http.StatusOK, \"Successfully added pet\", endpoint.SchemaResponseOption(Pet{})),\n\t\tendpoint.Security(\"petstore_auth\", \"read:pets\", \"write:pets\"),\n\t)\n\tget := endpoint.New(\"get\", \"/pet/{petId}\", endpoint.Summary(\"Find pet by ID\"),\n\t\tendpoint.Handler(handle),\n\t\tendpoint.Path(\"petId\", \"integer\", \"ID of pet to return\", true),\n\t\tendpoint.Response(http.StatusOK, \"successful operation\", endpoint.SchemaResponseOption(Pet{})),\n\t\tendpoint.Security(\"petstore_auth\", \"read:pets\"),\n\t)\n\ttest := endpoint.New(\"put\", \"/pet/{petId}\",\n\t\tendpoint.Handler(handle),\n\t\tendpoint.Path(\"petId\", \"integer\", \"ID of pet to return\", true),\n\t\tendpoint.Response(http.StatusOK, \"successful operation\", endpoint.SchemaResponseOption(struct {\n\t\t\tID   string `json:\"id\"`\n\t\t\tName string `json:\"name\"`\n\t\t}{})),\n\t\tendpoint.Security(\"petstore_auth\", \"read:pets\"),\n\t)\n\n\tapi := swag.New(\n\t\toption.Title(\"Example API Doc\"),\n\t\toption.Security(\"petstore_auth\", \"read:pets\"),\n\t\toption.SecurityScheme(\"petstore_auth\",\n\t\t\toption.OAuth2Security(\"accessCode\", \"http://example.com/oauth/authorize\", \"http://example.com/oauth/token\"),\n\t\t\toption.OAuth2Scope(\"write:pets\", \"modify pets in your account\"),\n\t\t\toption.OAuth2Scope(\"read:pets\", \"read your pets\"),\n\t\t),\n\t\toption.Endpoints(post, get),\n\t)\n\tapi.AddEndpoint(test)\n\n\tr := router.New()\n\tapi.Walk(func(path string, e *swag.Endpoint) {\n\t\tif v, ok := e.Handler.(func(ctx *fasthttp.RequestCtx)); ok {\n\t\t\tr.Handle(e.Method, path, fasthttp.RequestHandler(v))\n\t\t} else {\n\t\t\tr.Handle(e.Method, path, e.Handler.(fasthttp.RequestHandler))\n\t\t}\n\t})\n\n\tbuildSchemeFn := func(ctx *fasthttp.RequestCtx) string {\n\t\tvar scheme []byte\n\n\t\tif ctx.IsTLS() {\n\t\t\tscheme = []byte(\"https\")\n\t\t}\n\t\tif v := ctx.Request.Header.Peek(\"X-Forwarded-Proto\"); v != nil {\n\t\t\tscheme = v\n\t\t}\n\t\tif string(scheme) == \"\" {\n\t\t\tscheme = ctx.URI().Scheme()\n\t\t}\n\t\tif string(scheme) == \"\" {\n\t\t\tscheme = []byte(\"http\")\n\t\t}\n\t\treturn string(scheme)\n\t}\n\n\tdoc := api.Clone()\n\tr.GET(\"/swagger/json\", func(ctx *fasthttp.RequestCtx) {\n\t\tscheme := buildSchemeFn(ctx)\n\t\tdoc.Host = string(ctx.Host())\n\t\tdoc.Schemes = []string{scheme}\n\n\t\tb, err := json.Marshal(doc)\n\t\tif err != nil {\n\t\t\tctx.Error(\"Parse API Doc exceptions\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\t_, _ = ctx.Write(b)\n\t})\n\n\tr.ANY(\"/swagger/ui/{any:*}\", func(ctx *fasthttp.RequestCtx) {\n\t\tcurrentPath := strings.TrimPrefix(string(ctx.Path()), \"/swagger/ui\")\n\n\t\tif currentPath == \"/\" || currentPath == \"index.html\" {\n\t\t\tfullName := path.Join(asserts.DistDir, \"index.html\")\n\t\t\tfileData, err := asserts.Dist.ReadFile(fullName)\n\t\t\tif err != nil {\n\t\t\t\tctx.Error(\"index.html read exception\", http.StatusInternalServerError)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tscheme := buildSchemeFn(ctx)\n\t\t\tcurrentURI := scheme + \"://\" + path.Join(string(ctx.Host()), \"/swagger/json\")\n\n\t\t\tfileData = bytes.ReplaceAll(fileData, []byte(asserts.URL), []byte(currentURI))\n\t\t\tctx.SetContentType(\"text/html; charset=utf-8\")\n\t\t\tctx.Write(fileData)\n\t\t\treturn\n\t\t}\n\t\tsfs := swag.DirFS(asserts.DistDir, asserts.Dist)\n\t\tfile, err := sfs.Open(currentPath)\n\t\tif err != nil {\n\t\t\tctx.Error(err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tstat, err := file.Stat()\n\t\tif err != nil {\n\t\t\tctx.Error(err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tswitch strings.TrimPrefix(filepath.Ext(stat.Name()), \".\") {\n\t\tcase \"css\":\n\t\t\tctx.SetContentType(\"text/css; charset=utf-8\")\n\t\tcase \"js\":\n\t\t\tctx.SetContentType(\"application/javascript\")\n\t\t}\n\t\tio.Copy(ctx, file)\n\t})\n\n\tfasthttp.ListenAndServe(\":8080\", r.Handler)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzc2638%2Fswag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzc2638%2Fswag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzc2638%2Fswag/lists"}