diff --git a/README.md b/README.md index 2cbce944c..054e36ec6 100644 --- a/README.md +++ b/README.md @@ -425,25 +425,26 @@ When a short string in your documentation is insufficient, or you need images, c [celler/controller](https://github.com/swaggo/swag/tree/master/example/celler/controller) -| annotation | description | -|-------------|----------------------------------------------------------------------------------------------------------------------------| -| description | A verbose explanation of the operation behavior. | -| description.markdown | A short description of the application. The description will be read from a file. E.g. `@description.markdown details` will load `details.md`| // @description.file endpoint.description.markdown | -| id | A unique string used to identify the operation. Must be unique among all API operations. | -| tags | A list of tags to each API operation that separated by commas. | -| summary | A short summary of what the operation does. | -| accept | A list of MIME types the APIs can consume. Note that Accept only affects operations with a request body, such as POST, PUT and PATCH. Value MUST be as described under [Mime Types](#mime-types). | -| produce | A list of MIME types the APIs can produce. Value MUST be as described under [Mime Types](#mime-types). | -| param | Parameters that separated by spaces. `param name`,`param type`,`data type`,`is mandatory?`,`comment` `attribute(optional)` | -| security | [Security](#security) to each API operation. | -| success | Success response that separated by spaces. `return code or default`,`{param type}`,`data type`,`comment` | -| failure | Failure response that separated by spaces. `return code or default`,`{param type}`,`data type`,`comment` | -| response | As same as `success` and `failure` | -| header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | -| router | Path definition that separated by spaces. `path`,`[httpMethod]` | -| x-name | The extension key, must be start by x- and take only json value. | -| x-codeSample | Optional Markdown usage. take `file` as parameter. This will then search for a file named like the summary in the given folder. | -| deprecated | Mark endpoint as deprecated. | +| annotation | description | +|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| description | A verbose explanation of the operation behavior. | +| description.markdown | A short description of the application. The description will be read from a file. E.g. `@description.markdown details` will load `details.md` | // @description.file endpoint.description.markdown | +| id | A unique string used to identify the operation. Must be unique among all API operations. | +| tags | A list of tags to each API operation that separated by commas. | +| summary | A short summary of what the operation does. | +| accept | A list of MIME types the APIs can consume. Note that Accept only affects operations with a request body, such as POST, PUT and PATCH. Value MUST be as described under [Mime Types](#mime-types). | +| produce | A list of MIME types the APIs can produce. Value MUST be as described under [Mime Types](#mime-types). | +| param | Parameters that separated by spaces. `param name`,`param type`,`data type`,`is mandatory?`,`comment` `attribute(optional)` | +| security | [Security](#security) to each API operation. | +| success | Success response that separated by spaces. `return code or default`,`{param type}`,`data type`,`comment` | +| failure | Failure response that separated by spaces. `return code or default`,`{param type}`,`data type`,`comment` | +| response | As same as `success` and `failure` | +| header | Header in response that separated by spaces. `return code`,`{param type}`,`data type`,`comment` | +| router | Path definition that separated by spaces. `path`,`[httpMethod]` | +| deprecatedrouter | As same as router, but deprecated. | +| x-name | The extension key, must be start by x- and take only json value. | +| x-codeSample | Optional Markdown usage. take `file` as parameter. This will then search for a file named like the summary in the given folder. | +| deprecated | Mark endpoint as deprecated. | diff --git a/README_zh-CN.md b/README_zh-CN.md index fc5c4e188..87d600b52 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -378,23 +378,25 @@ swag fmt -d ./ --exclude ./internal Example [celler/controller](https://github.com/swaggo/swag/tree/master/example/celler/controller) -| 注释 | 描述 | -| -------------------- | ------------------------------------------------------------------------------------------------------- | -| description | 操作行为的详细说明。 | -| description.markdown | 应用程序的简短描述。该描述将从名为`endpointname.md`的文件中读取。 | -| id | 用于标识操作的唯一字符串。在所有API操作中必须唯一。 | -| tags | 每个API操作的标签列表,以逗号分隔。 | +| 注释 | 描述 | +|----------------------|------------------------------------------------------------------------------------------------| +| description | 操作行为的详细说明。 | +| description.markdown | 应用程序的简短描述。该描述将从名为`endpointname.md`的文件中读取。 | +| id | 用于标识操作的唯一字符串。在所有API操作中必须唯一。 | +| tags | 每个API操作的标签列表,以逗号分隔。 | | summary | 该操作的简短摘要。 | -| accept | API 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“[Mime类型](#mime类型)”中所述。 | -| produce | API可以生成的MIME类型的列表。值必须如“[Mime类型](#mime类型)”中所述。 | +| accept | API 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“[Mime类型](#mime类型)”中所述。 | +| produce | API可以生成的MIME类型的列表。值必须如“[Mime类型](#mime类型)”中所述。 | | param | 用空格分隔的参数。`param name`,`param type`,`data type`,`is mandatory?`,`comment` `attribute(optional)` | -| security | 每个API操作的[安全性](#安全性)。 | -| success | 以空格分隔的成功响应。`return code`,`{param type}`,`data type`,`comment` | -| failure | 以空格分隔的故障响应。`return code`,`{param type}`,`data type`,`comment` | -| response | 与success、failure作用相同 | -| header | 以空格分隔的头字段。 `return code`,`{param type}`,`data type`,`comment` | -| router | 以空格分隔的路径定义。 `path`,`[httpMethod]` | -| x-name | 扩展字段必须以`x-`开头,并且只能使用json值。 | +| security | 每个API操作的[安全性](#安全性)。 | +| success | 以空格分隔的成功响应。`return code`,`{param type}`,`data type`,`comment` | +| failure | 以空格分隔的故障响应。`return code`,`{param type}`,`data type`,`comment` | +| response | 与success、failure作用相同 | +| header | 以空格分隔的头字段。 `return code`,`{param type}`,`data type`,`comment` | +| router | 以空格分隔的路径定义。 `path`,`[httpMethod]` | +| deprecatedrouter | 与router相同,但是是deprecated的。 | +| x-name | 扩展字段必须以`x-`开头,并且只能使用json值。 | +| deprecated | 将当前API操作的所有路径设置为deprecated | ## Mime类型 diff --git a/operation.go b/operation.go index fa74384dc..8cf7d5b95 100644 --- a/operation.go +++ b/operation.go @@ -21,6 +21,7 @@ import ( type RouteProperties struct { HTTPMethod string Path string + Deprecated bool } // Operation describes a single API operation on a path. @@ -147,7 +148,9 @@ func (operation *Operation) ParseComment(comment string, astFile *ast.File) erro case headerAttr: return operation.ParseResponseHeaderComment(lineRemainder, astFile) case routerAttr: - return operation.ParseRouterComment(lineRemainder) + return operation.ParseRouterComment(lineRemainder, false) + case deprecatedRouterAttr: + return operation.ParseRouterComment(lineRemainder, true) case securityAttr: return operation.ParseSecurityComment(lineRemainder) case deprecatedAttr: @@ -707,7 +710,7 @@ func parseMimeTypeList(mimeTypeList string, typeList *[]string, format string) e var routerPattern = regexp.MustCompile(`^(/[\w./\-{}+:$]*)[[:blank:]]+\[(\w+)]`) // ParseRouterComment parses comment for given `router` comment string. -func (operation *Operation) ParseRouterComment(commentLine string) error { +func (operation *Operation) ParseRouterComment(commentLine string, deprecated bool) error { matches := routerPattern.FindStringSubmatch(commentLine) if len(matches) != 3 { return fmt.Errorf("can not parse router comment \"%s\"", commentLine) @@ -716,6 +719,7 @@ func (operation *Operation) ParseRouterComment(commentLine string) error { signature := RouteProperties{ Path: matches[1], HTTPMethod: strings.ToUpper(matches[2]), + Deprecated: deprecated, } if _, ok := allMethod[signature.HTTPMethod]; !ok { diff --git a/operation_test.go b/operation_test.go index 6b684bc2c..e9214d71a 100644 --- a/operation_test.go +++ b/operation_test.go @@ -5,6 +5,8 @@ import ( "go/ast" goparser "go/parser" "go/token" + "os" + "path/filepath" "testing" "github.com/go-openapi/spec" @@ -2416,3 +2418,16 @@ func TestParseCodeSamples(t *testing.T) { assert.Error(t, err, "no error should be thrown") }) } + +func TestParseDeprecatedRouter(t *testing.T) { + p := New() + searchDir := "./testdata/deprecated_router" + if err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth); err != nil { + t.Error("Failed to parse api: " + err.Error()) + } + + b, _ := json.MarshalIndent(p.swagger, "", " ") + expected, err := os.ReadFile(filepath.Join(searchDir, "expected.json")) + assert.NoError(t, err) + assert.Equal(t, expected, b) +} diff --git a/parser.go b/parser.go index a2bafa1f9..a97da1d59 100644 --- a/parser.go +++ b/parser.go @@ -43,6 +43,7 @@ const ( headerAttr = "@header" tagsAttr = "@tags" routerAttr = "@router" + deprecatedRouterAttr = "@deprecatedrouter" summaryAttr = "@summary" deprecatedAttr = "@deprecated" securityAttr = "@security" @@ -1081,6 +1082,10 @@ func processRouterOperation(parser *Parser, operation *Operation) error { *op = &operation.Operation } + if routeProperties.Deprecated { + (*op).Deprecated = routeProperties.Deprecated + } + parser.swagger.Paths.Paths[routeProperties.Path] = pathItem } diff --git a/testdata/deprecated_router/api/api.go b/testdata/deprecated_router/api/api.go new file mode 100644 index 000000000..889613170 --- /dev/null +++ b/testdata/deprecated_router/api/api.go @@ -0,0 +1,17 @@ +package api + +import "net/http" + +// @Description add Foo +// @Deprecated +// @Success 200 {string} string +// @Router /testapi/foo1 [put] +// @Router /testapi/foo1 [post] +// @Router /test/api/foo1 [post] +func AddFoo(w http.ResponseWriter, r *http.Request) {} + +// @Description get Foo +// @Success 200 {string} string +// @Router /testapi/foo1 [get] +// @DeprecatedRouter /test/api/foo1 [get] +func GetFoo(w http.ResponseWriter, r *http.Request) {} diff --git a/testdata/deprecated_router/expected.json b/testdata/deprecated_router/expected.json new file mode 100644 index 000000000..4c473f36b --- /dev/null +++ b/testdata/deprecated_router/expected.json @@ -0,0 +1,75 @@ +{ + "swagger": "2.0", + "info": { + "description": "test data for deprecated router", + "title": "Swagger Example API", + "termsOfService": "http://swagger.io/terms/", + "contact": {}, + "version": "1.0" + }, + "paths": { + "/test/api/foo1": { + "get": { + "description": "get Foo", + "deprecated": true, + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "add Foo", + "deprecated": true, + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/testapi/foo1": { + "get": { + "description": "get Foo", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "description": "add Foo", + "deprecated": true, + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "add Foo", + "deprecated": true, + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testdata/deprecated_router/main.go b/testdata/deprecated_router/main.go new file mode 100644 index 000000000..6f513d409 --- /dev/null +++ b/testdata/deprecated_router/main.go @@ -0,0 +1,9 @@ +package main + +// @title Swagger Example API +// @version 1.0 +// @description test data for deprecated router +// @termsOfService http://swagger.io/terms/ + +func main() { +}