diff --git a/parserv3.go b/parserv3.go index fa494c8c7..225cfcee3 100644 --- a/parserv3.go +++ b/parserv3.go @@ -7,6 +7,7 @@ import ( "go/token" "net/http" "reflect" + "regexp" "sort" "strings" @@ -32,6 +33,11 @@ func (p *Parser) GetOpenAPI() *spec.OpenAPI { return p.openAPI } +var ( + serversURLPattern = regexp.MustCompile(`\{([^}]+)\}`) + serversVariablesPattern = regexp.MustCompile(`^(\w+)\s+(.+)$`) +) + func (p *Parser) parseGeneralAPIInfoV3(comments []string) error { previousAttribute := "" @@ -167,19 +173,64 @@ func (p *Parser) parseGeneralAPIInfoV3(comments []string) error { case "@servers.url": server := spec.NewServer() server.Spec.URL = value + matches := serversURLPattern.FindAllStringSubmatch(value, -1) + server.Spec.Variables = make(map[string]*spec.Extendable[spec.ServerVariable]) + for _, match := range matches { + server.Spec.Variables[match[1]] = spec.NewServerVariable() + } p.openAPI.Servers = append(p.openAPI.Servers, server) case "@servers.description": server := p.openAPI.Servers[len(p.openAPI.Servers)-1] server.Spec.Description = value case "@servers.variables.enum": - p.debug.Printf("not yet implemented: @servers.variables.enum") + server := p.openAPI.Servers[len(p.openAPI.Servers)-1] + matches := serversVariablesPattern.FindStringSubmatch(value) + if len(matches) > 0 { + variable, ok := server.Spec.Variables[matches[1]] + if !ok { + p.debug.Printf("Variables are not detected.") + continue + } + variable.Spec.Enum = append(variable.Spec.Enum, matches[2]) + } case "@servers.variables.default": - p.debug.Printf("not yet implemented: @servers.variables.default") + server := p.openAPI.Servers[len(p.openAPI.Servers)-1] + matches := serversVariablesPattern.FindStringSubmatch(value) + if len(matches) > 0 { + variable, ok := server.Spec.Variables[matches[1]] + if !ok { + p.debug.Printf("Variables are not detected.") + continue + } + variable.Spec.Default = matches[2] + } case "@servers.variables.description": - p.debug.Printf("not yet implemented: @servers.variables.description") + server := p.openAPI.Servers[len(p.openAPI.Servers)-1] + matches := serversVariablesPattern.FindStringSubmatch(value) + if len(matches) > 0 { + variable, ok := server.Spec.Variables[matches[1]] + if !ok { + p.debug.Printf("Variables are not detected.") + continue + } + variable.Spec.Default = matches[2] + } case "@servers.variables.description.markdown": - p.debug.Printf("not yet implemented: @servers.variables.description.markdown") + server := p.openAPI.Servers[len(p.openAPI.Servers)-1] + matches := serversVariablesPattern.FindStringSubmatch(value) + if len(matches) > 0 { + variable, ok := server.Spec.Variables[matches[1]] + if !ok { + p.debug.Printf("Variables are not detected.") + continue + } + commentInfo, err := getMarkdownForTag(matches[1], p.markdownFileDir) + if err != nil { + return err + } + variable.Spec.Description = string(commentInfo) + } default: if strings.HasPrefix(attribute, "@x-") { err := p.parseExtensionsV3(value, attribute) diff --git a/parserv3_test.go b/parserv3_test.go index 2511ca6ce..38bf4453b 100644 --- a/parserv3_test.go +++ b/parserv3_test.go @@ -386,9 +386,14 @@ func TestParserParseServers(t *testing.T) { require.NotNil(t, servers) assert.Equal(t, 2, len(servers)) - assert.Equal(t, "https://test.petstore.com/v3", servers[0].Spec.URL) + assert.Equal(t, "{scheme}://{host}:{port}", servers[0].Spec.URL) assert.Equal(t, "Test Petstore server.", servers[0].Spec.Description) + assert.Equal(t, "https", servers[0].Spec.Variables["scheme"].Spec.Default) + assert.Equal(t, []string{"http", "https"}, servers[0].Spec.Variables["scheme"].Spec.Enum) + assert.Equal(t, "test.petstore.com", servers[0].Spec.Variables["host"].Spec.Default) + assert.Equal(t, "443", servers[0].Spec.Variables["port"].Spec.Default) + assert.Equal(t, "https://petstore.com/v3", servers[1].Spec.URL) assert.Equal(t, "Production Petstore server.", servers[1].Spec.Description) diff --git a/testdata/v3/servers/main.go b/testdata/v3/servers/main.go index 7820c34e8..f08733123 100644 --- a/testdata/v3/servers/main.go +++ b/testdata/v3/servers/main.go @@ -18,8 +18,13 @@ import ( // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html -// @servers.url https://test.petstore.com/v3 +// @servers.url {scheme}://{host}:{port} // @servers.description Test Petstore server. +// @servers.variables.enum scheme http +// @servers.variables.enum scheme https +// @servers.variables.default scheme https +// @servers.variables.default host test.petstore.com +// @servers.variables.default port 443 // @servers.url https://petstore.com/v3 // @servers.description Production Petstore server.