From 02d9a282e8b53be5f22d88f43b508e479c7026b8 Mon Sep 17 00:00:00 2001 From: Ben Youngblood Date: Thu, 1 Jun 2017 10:41:46 -0600 Subject: [PATCH 1/6] skip unexported fields when building object definitions --- swagger/reflect.go | 5 +++++ swagger/reflect_test.go | 30 +++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/swagger/reflect.go b/swagger/reflect.go index aeffec1..8f452e2 100644 --- a/swagger/reflect.go +++ b/swagger/reflect.go @@ -122,6 +122,11 @@ func defineObject(v interface{}) Object { for i := 0; i < t.NumField(); i++ { field := t.Field(i) + // skip unexported fields + if strings.ToLower(field.Name[0:1]) == field.Name[0:1] { + continue + } + // determine the json name of the field name := strings.TrimSpace(field.Tag.Get("json")) if name == "" || strings.HasPrefix(name, ",") { diff --git a/swagger/reflect_test.go b/swagger/reflect_test.go index 125dd66..31ba90b 100644 --- a/swagger/reflect_test.go +++ b/swagger/reflect_test.go @@ -6,8 +6,9 @@ import ( "io/ioutil" "testing" - "github.com/stretchr/testify/assert" "fmt" + + "github.com/stretchr/testify/assert" ) type Person struct { @@ -23,6 +24,8 @@ type Pet struct { IntArray []int String string StringArray []string + + unexported string } type Empty struct { @@ -71,21 +74,21 @@ func TestNotStructDefine(t *testing.T) { obj, ok := v["int32"] assert.True(t, ok) assert.False(t, obj.IsArray) - assert.Equal(t, "integer", obj.Type ) + assert.Equal(t, "integer", obj.Type) assert.Equal(t, "int32", obj.Format) v = define(uint64(1)) obj, ok = v["uint64"] assert.True(t, ok) assert.False(t, obj.IsArray) - assert.Equal(t, "integer", obj.Type ) + assert.Equal(t, "integer", obj.Type) assert.Equal(t, "int64", obj.Format) v = define("") obj, ok = v["string"] assert.True(t, ok) assert.False(t, obj.IsArray) - assert.Equal(t, "string", obj.Type ) + assert.Equal(t, "string", obj.Type) assert.Equal(t, "", obj.Format) v = define(byte(1)) @@ -94,16 +97,16 @@ func TestNotStructDefine(t *testing.T) { fmt.Printf("%v", v) } assert.False(t, obj.IsArray) - assert.Equal(t, "integer", obj.Type ) + assert.Equal(t, "integer", obj.Type) assert.Equal(t, "int32", obj.Format) - v = define([]byte{1,2}) + v = define([]byte{1, 2}) obj, ok = v["uint8"] if !assert.True(t, ok) { fmt.Printf("%v", v) } assert.True(t, obj.IsArray) - assert.Equal(t, "integer", obj.Type ) + assert.Equal(t, "integer", obj.Type) assert.Equal(t, "int32", obj.Format) } @@ -114,3 +117,16 @@ func TestHonorJsonIgnore(t *testing.T) { assert.False(t, obj.IsArray) assert.Equal(t, 0, len(obj.Properties), "expected zero exposed properties") } + +func TestIgnoreUnexported(t *testing.T) { + type Test struct { + Exported string + unexported string + } + v := define(Test{}) + obj, ok := v["swaggerTest"] + assert.True(t, ok) + assert.Equal(t, 1, len(obj.Properties), "expected one exposed properties") + assert.Contains(t, obj.Properties, "Exported") + assert.NotContains(t, obj.Properties, "unexported") +} From 4ebdaa73dc5fccafbd4670b9f2163d15c87db097 Mon Sep 17 00:00:00 2001 From: Ben Youngblood Date: Fri, 2 Jun 2017 10:06:37 -0600 Subject: [PATCH 2/6] implement swagger security options for APIs and endpoints --- builder.go | 32 ++++++++++++ builder_test.go | 19 +++++++ endpoint/builder.go | 22 +++++++++ endpoint/builder_test.go | 33 +++++++++++++ examples/builtin/main.go | 9 ++++ swagger/api.go | 104 +++++++++++++++++++++++++++++++++------ swagger/api_test.go | 55 +++++++++++++++++++++ swagger/endpoint.go | 18 +++++++ 8 files changed, 276 insertions(+), 16 deletions(-) diff --git a/builder.go b/builder.go index 9755a6a..07421d5 100644 --- a/builder.go +++ b/builder.go @@ -120,6 +120,38 @@ func Endpoints(endpoints ...*swagger.Endpoint) Option { } } +// SecurityScheme creates a new security definition for the API. +func SecurityScheme(name string, options ...swagger.SecuritySchemeOption) Option { + return func(builder *Builder) { + if builder.API.SecurityDefinitions == nil { + builder.API.SecurityDefinitions = map[string]swagger.SecurityScheme{} + } + + scheme := swagger.SecurityScheme{} + + for _, opt := range options { + opt(&scheme) + } + + builder.API.SecurityDefinitions[name] = scheme + } +} + +// Security sets a default security scheme for all endpoints in the API. +func Security(scheme string, scopes ...string) Option { + return func(b *Builder) { + if b.API.Security == nil { + b.API.Security = &swagger.SecurityRequirement{} + } + + if b.API.Security.Requirements == nil { + b.API.Security.Requirements = []map[string][]string{} + } + + b.API.Security.Requirements = append(b.API.Security.Requirements, map[string][]string{scheme: scopes}) + } +} + // New constructs a new api builder func New(options ...Option) *swagger.API { b := &Builder{ diff --git a/builder_test.go b/builder_test.go index 4d517b2..da87b07 100644 --- a/builder_test.go +++ b/builder_test.go @@ -90,3 +90,22 @@ func TestHost(t *testing.T) { ) assert.Equal(t, "blah", api.Host) } + +func TestSecurityScheme(t *testing.T) { + api := swag.New( + swag.SecurityScheme("basic", swagger.BasicSecurity()), + swag.SecurityScheme("apikey", swagger.APIKeySecurity("Authorization", "header")), + ) + assert.Len(t, api.SecurityDefinitions, 2) + assert.Contains(t, api.SecurityDefinitions, "basic") + assert.Contains(t, api.SecurityDefinitions, "apikey") + assert.Equal(t, "header", api.SecurityDefinitions["apikey"].In) +} + +func TestSecurity(t *testing.T) { + api := swag.New( + swag.Security("basic"), + ) + assert.Len(t, api.Security.Requirements, 1) + assert.Contains(t, api.Security.Requirements[0], "basic") +} diff --git a/endpoint/builder.go b/endpoint/builder.go index d2bbc82..90e4fd1 100644 --- a/endpoint/builder.go +++ b/endpoint/builder.go @@ -116,6 +116,28 @@ func Tags(tags ...string) Option { } } +// Security allows a security scheme to be associated with the endpoint. +func Security(scheme string, scopes ...string) Option { + return func(b *Builder) { + if b.Endpoint.Security == nil { + b.Endpoint.Security = &swagger.SecurityRequirement{} + } + + if b.Endpoint.Security.Requirements == nil { + b.Endpoint.Security.Requirements = []map[string][]string{} + } + + b.Endpoint.Security.Requirements = append(b.Endpoint.Security.Requirements, map[string][]string{scheme: scopes}) + } +} + +// NoSecurity explicitly sets the endpoint to have no security requirements. +func NoSecurity() Option { + return func(b *Builder) { + b.Endpoint.Security = &swagger.SecurityRequirement{DisableSecurity: true} + } +} + // ResponseOption allows for additional configurations on responses like header information type ResponseOption func(response *swagger.Response) diff --git a/endpoint/builder_test.go b/endpoint/builder_test.go index 587fcc8..b84110f 100644 --- a/endpoint/builder_test.go +++ b/endpoint/builder_test.go @@ -5,6 +5,7 @@ import ( "net/http" "testing" + "github.com/savaki/swag" "github.com/savaki/swag/endpoint" "github.com/savaki/swag/swagger" "github.com/stretchr/testify/assert" @@ -171,3 +172,35 @@ func TestResponseHeader(t *testing.T) { assert.Equal(t, 1, len(e.Responses)) assert.Equal(t, expected, e.Responses["200"]) } + +func TestSecurityScheme(t *testing.T) { + api := swag.New( + swag.SecurityScheme("basic", swagger.BasicSecurity()), + swag.SecurityScheme("apikey", swagger.APIKeySecurity("Authorization", "header")), + ) + assert.Len(t, api.SecurityDefinitions, 2) + assert.Contains(t, api.SecurityDefinitions, "basic") + assert.Contains(t, api.SecurityDefinitions, "apikey") + assert.Equal(t, "header", api.SecurityDefinitions["apikey"].In) +} + +func TestSecurity(t *testing.T) { + e := endpoint.New("get", "/", "", + endpoint.Handler(Echo), + endpoint.Security("basic"), + endpoint.Security("oauth2", "scope1", "scope2"), + ) + assert.False(t, e.Security.DisableSecurity) + assert.Len(t, e.Security.Requirements, 2) + assert.Contains(t, e.Security.Requirements[0], "basic") + assert.Contains(t, e.Security.Requirements[1], "oauth2") + assert.Len(t, e.Security.Requirements[1]["oauth2"], 2) +} + +func TestNoSecurity(t *testing.T) { + e := endpoint.New("get", "/", "", + endpoint.Handler(Echo), + endpoint.NoSecurity(), + ) + assert.True(t, e.Security.DisableSecurity) +} diff --git a/examples/builtin/main.go b/examples/builtin/main.go index c762704..8e431a1 100644 --- a/examples/builtin/main.go +++ b/examples/builtin/main.go @@ -6,6 +6,7 @@ import ( "github.com/savaki/swag" "github.com/savaki/swag/endpoint" + "github.com/savaki/swag/swagger" ) func handle(w http.ResponseWriter, req *http.Request) { @@ -33,15 +34,23 @@ func main() { endpoint.Description("Additional information on adding a pet to the store"), endpoint.Body(Pet{}, "Pet object that needs to be added to the store", true), endpoint.Response(http.StatusOK, Pet{}, "Successfully added pet"), + endpoint.Security("petstore_auth", "read:pets", "write:pets"), ) get := endpoint.New("get", "/pet/{petId}", "Find pet by ID", endpoint.Handler(handle), endpoint.Path("petId", "integer", "ID of pet to return", true), endpoint.Response(http.StatusOK, Pet{}, "successful operation"), + endpoint.Security("petstore_auth", "read:pets"), ) api := swag.New( swag.Endpoints(post, get), + swag.Security("petstore_auth", "read:pets"), + swag.SecurityScheme("petstore_auth", + swagger.OAuth2Security("accessCode", "http://example.com/oauth/authorize", "http://example.com/oauth/token"), + swagger.OAuth2Scope("write:pets", "modify pets in your account"), + swagger.OAuth2Scope("read:pets", "read your pets"), + ), ) for path, endpoints := range api.Paths { diff --git a/swagger/api.go b/swagger/api.go index a7f2a65..6203f36 100644 --- a/swagger/api.go +++ b/swagger/api.go @@ -55,6 +55,74 @@ type Info struct { License License `json:"license"` } +// SecurityScheme represents a security scheme from the swagger definition. +type SecurityScheme struct { + Type string `json:"type"` + Description string `json:"description,omitempty"` + Name string `json:"name,omitempty"` + In string `json:"in,omitempty"` + Flow string `json:"flow,omitempty"` + AuthorizationURL string `json:"authorizationUrl,omitempty"` + TokenURL string `json:"tokenUrl,omitempty"` + Scopes map[string]string `json:"scopes,omitempty"` +} + +// SecuritySchemeOption provides additional customizations to the SecurityScheme. +type SecuritySchemeOption func(securityScheme *SecurityScheme) + +// SecuritySchemeDescription sets the security scheme's description. +func SecuritySchemeDescription(description string) SecuritySchemeOption { + return func(securityScheme *SecurityScheme) { + securityScheme.Description = description + } +} + +// BasicSecurity defines a security scheme for HTTP Basic authentication. +func BasicSecurity() SecuritySchemeOption { + return func(securityScheme *SecurityScheme) { + securityScheme.Type = "basic" + } +} + +// APIKeySecurity defines a security scheme for API key authentication. "in" is +// the location of the API key (query or header). "name" is the name of the +// header or query parameter to be used. +func APIKeySecurity(name, in string) SecuritySchemeOption { + if in != "header" && in != "query" { + panic(fmt.Errorf(`APIKeySecurity "in" parameter must be one of: "header" or "query"`)) + } + + return func(securityScheme *SecurityScheme) { + securityScheme.Type = "apiKey" + securityScheme.Name = name + securityScheme.In = in + } +} + +// OAuth2Scope adds a new scope to the security scheme. +func OAuth2Scope(scope, description string) SecuritySchemeOption { + return func(securityScheme *SecurityScheme) { + if securityScheme.Scopes == nil { + securityScheme.Scopes = map[string]string{} + } + securityScheme.Scopes[scope] = description + } +} + +// OAuth2Security defines a security scheme for OAuth2 authentication. Flow can +// be one of implicit, password, application, or accessCode. +func OAuth2Security(flow, authorizationURL, tokenURL string) SecuritySchemeOption { + return func(securityScheme *SecurityScheme) { + securityScheme.Type = "oauth2" + securityScheme.Flow = flow + securityScheme.AuthorizationURL = authorizationURL + securityScheme.TokenURL = tokenURL + if securityScheme.Scopes == nil { + securityScheme.Scopes = map[string]string{} + } + } +} + // Endpoints represents all the swagger endpoints associated with a particular path type Endpoints struct { Delete *Endpoint `json:"delete,omitempty"` @@ -144,26 +212,30 @@ func (e *Endpoints) Walk(fn func(endpoint *Endpoint)) { // API provides the top level encapsulation for the swagger definition type API struct { - Swagger string `json:"swagger,omitempty"` - Info Info `json:"info"` - BasePath string `json:"basePath,omitempty"` - Schemes []string `json:"schemes,omitempty"` - Paths map[string]*Endpoints `json:"paths,omitempty"` - Definitions map[string]Object `json:"definitions,omitempty"` - Tags []Tag `json:"tags"` - Host string `json:"host"` + Swagger string `json:"swagger,omitempty"` + Info Info `json:"info"` + BasePath string `json:"basePath,omitempty"` + Schemes []string `json:"schemes,omitempty"` + Paths map[string]*Endpoints `json:"paths,omitempty"` + Definitions map[string]Object `json:"definitions,omitempty"` + Tags []Tag `json:"tags"` + Host string `json:"host"` + SecurityDefinitions map[string]SecurityScheme `json:"securityDefinitions,omitempty"` + Security *SecurityRequirement `json:"security,omitempty"` } func (a *API) clone() *API { return &API{ - Swagger: a.Swagger, - Info: a.Info, - BasePath: a.BasePath, - Schemes: a.Schemes, - Paths: a.Paths, - Definitions: a.Definitions, - Tags: a.Tags, - Host: a.Host, + Swagger: a.Swagger, + Info: a.Info, + BasePath: a.BasePath, + Schemes: a.Schemes, + Paths: a.Paths, + Definitions: a.Definitions, + Tags: a.Tags, + Host: a.Host, + SecurityDefinitions: a.SecurityDefinitions, + Security: a.Security, } } diff --git a/swagger/api_test.go b/swagger/api_test.go index 69b4dff..b9b86d8 100644 --- a/swagger/api_test.go +++ b/swagger/api_test.go @@ -69,3 +69,58 @@ func TestEndpoints_ServeHTTP(t *testing.T) { assert.Equal(t, strings.ToUpper(w.Body.String()), strings.ToUpper(method)) } } + +func TestSecuritySchemeDescription(t *testing.T) { + scheme := &swagger.SecurityScheme{} + description := "a security scheme" + swagger.SecuritySchemeDescription(description)(scheme) + assert.Equal(t, description, scheme.Description) +} + +func TestBasicSecurity(t *testing.T) { + scheme := &swagger.SecurityScheme{} + swagger.BasicSecurity()(scheme) + assert.Equal(t, scheme.Type, "basic") +} + +func TestAPIKeySecurity(t *testing.T) { + scheme := &swagger.SecurityScheme{} + name := "Authorization" + in := "header" + swagger.APIKeySecurity(name, in)(scheme) + assert.Equal(t, scheme.Type, "apiKey") + assert.Equal(t, scheme.Name, name) + assert.Equal(t, scheme.In, in) + + assert.Panics(t, func() { + swagger.APIKeySecurity(name, "invalid") + }, "expected APIKeySecurity to panic with invalid \"in\" parameter") +} + +func TestOAuth2Security(t *testing.T) { + scheme := &swagger.SecurityScheme{} + + flow := "accessCode" + authURL := "http://example.com/oauth/authorize" + tokenURL := "http://example.com/oauth/token" + swagger.OAuth2Security(flow, authURL, tokenURL)(scheme) + + assert.Equal(t, scheme.Type, "oauth2") + assert.Equal(t, scheme.Flow, "accessCode") + assert.Equal(t, scheme.AuthorizationURL, authURL) + assert.Equal(t, scheme.TokenURL, tokenURL) +} + +func TestOAuth2Scope(t *testing.T) { + scheme := &swagger.SecurityScheme{} + + swagger.OAuth2Scope("read", "read data")(scheme) + swagger.OAuth2Scope("write", "write data")(scheme) + + assert.Len(t, scheme.Scopes, 2) + assert.Contains(t, scheme.Scopes, "read") + assert.Contains(t, scheme.Scopes, "write") + + assert.Equal(t, "read data", scheme.Scopes["read"]) + assert.Equal(t, "write data", scheme.Scopes["write"]) +} diff --git a/swagger/endpoint.go b/swagger/endpoint.go index 7d613b5..8d039ac 100644 --- a/swagger/endpoint.go +++ b/swagger/endpoint.go @@ -1,5 +1,7 @@ package swagger +import "encoding/json" + // Items represents items from the swagger doc type Items struct { Type string `json:"type,omitempty"` @@ -53,4 +55,20 @@ type Endpoint struct { Handler interface{} `json:"-"` Parameters []Parameter `json:"parameters,omitempty"` Responses map[string]Response `json:"responses,omitempty"` + + // swagger spec requires security to be an array of objects + Security *SecurityRequirement `json:"security,omitempty"` +} + +type SecurityRequirement struct { + Requirements []map[string][]string + DisableSecurity bool +} + +func (s *SecurityRequirement) MarshalJSON() ([]byte, error) { + if s.DisableSecurity { + return []byte("[]"), nil + } + + return json.Marshal(s.Requirements) } From 784f51de8e16e8321a0268e3c2734b335807de49 Mon Sep 17 00:00:00 2001 From: Ruoyan Wong Date: Thu, 22 Jun 2017 22:40:47 +0800 Subject: [PATCH 3/6] add support for Windows --- swagger/api.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/swagger/api.go b/swagger/api.go index a7f2a65..19136e7 100644 --- a/swagger/api.go +++ b/swagger/api.go @@ -5,7 +5,7 @@ import ( "fmt" "io" "net/http" - "path/filepath" + "path" "reflect" "strings" "sync" @@ -290,8 +290,8 @@ func (a *API) Handler(enableCors bool) http.HandlerFunc { // Walk invoke the callback for each endpoints defined in the swagger doc func (a *API) Walk(callback func(path string, endpoints *Endpoint)) { - for path, endpoints := range a.Paths { - u := filepath.Join(a.BasePath, path) + for rawPath, endpoints := range a.Paths { + u := path.Join(a.BasePath, rawPath) endpoints.Walk(func(endpoint *Endpoint) { callback(u, endpoint) }) From 2bf69d9bc3c40a512c9871463e4dd7be2a016162 Mon Sep 17 00:00:00 2001 From: savaki Date: Fri, 21 Jul 2017 12:22:56 -0700 Subject: [PATCH 4/6] - added license information --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++ builder.go | 14 +++ builder_test.go | 14 +++ endpoint/builder.go | 14 +++ endpoint/builder_test.go | 14 +++ endpoint/util.go | 14 +++ endpoint/util_test.go | 14 +++ examples/builtin/main.go | 14 +++ examples/echo/main.go | 14 +++ examples/gin/main.go | 14 +++ examples/gorilla/main.go | 14 +++ examples/httprouter/main.go | 14 +++ swagger/api.go | 14 +++ swagger/api_test.go | 14 +++ swagger/compiles_test.go | 14 +++ swagger/endpoint.go | 14 +++ swagger/reflect.go | 14 +++ swagger/reflect_test.go | 14 +++ swagger/tag.go | 14 +++ swagger/util.go | 14 +++ swagger/util_test.go | 14 +++ util.go | 14 +++ util_test.go | 14 +++ 23 files changed, 509 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c3de95d --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright {yyyy} {name of copyright owner} + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/builder.go b/builder.go index 9755a6a..df000e3 100644 --- a/builder.go +++ b/builder.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swag import "github.com/savaki/swag/swagger" diff --git a/builder_test.go b/builder_test.go index 4d517b2..7058efb 100644 --- a/builder_test.go +++ b/builder_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swag_test import ( diff --git a/endpoint/builder.go b/endpoint/builder.go index d2bbc82..5130bb2 100644 --- a/endpoint/builder.go +++ b/endpoint/builder.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package endpoint import ( diff --git a/endpoint/builder_test.go b/endpoint/builder_test.go index 587fcc8..698daf3 100644 --- a/endpoint/builder_test.go +++ b/endpoint/builder_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package endpoint_test import ( diff --git a/endpoint/util.go b/endpoint/util.go index 1e2704d..e1a1865 100644 --- a/endpoint/util.go +++ b/endpoint/util.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package endpoint import ( diff --git a/endpoint/util_test.go b/endpoint/util_test.go index 6b63c9e..46f8318 100644 --- a/endpoint/util_test.go +++ b/endpoint/util_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package endpoint import ( diff --git a/examples/builtin/main.go b/examples/builtin/main.go index c762704..bae3e0f 100644 --- a/examples/builtin/main.go +++ b/examples/builtin/main.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package main import ( diff --git a/examples/echo/main.go b/examples/echo/main.go index 9c918d6..af77449 100644 --- a/examples/echo/main.go +++ b/examples/echo/main.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package main import ( diff --git a/examples/gin/main.go b/examples/gin/main.go index bb7ff41..ee46f8f 100644 --- a/examples/gin/main.go +++ b/examples/gin/main.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package main import ( diff --git a/examples/gorilla/main.go b/examples/gorilla/main.go index 2ab1399..a3d421e 100644 --- a/examples/gorilla/main.go +++ b/examples/gorilla/main.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package main import ( diff --git a/examples/httprouter/main.go b/examples/httprouter/main.go index 5579be2..900884d 100644 --- a/examples/httprouter/main.go +++ b/examples/httprouter/main.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package main import ( diff --git a/swagger/api.go b/swagger/api.go index a7f2a65..8f12dac 100644 --- a/swagger/api.go +++ b/swagger/api.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger import ( diff --git a/swagger/api_test.go b/swagger/api_test.go index 69b4dff..98cd6ce 100644 --- a/swagger/api_test.go +++ b/swagger/api_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger_test import ( diff --git a/swagger/compiles_test.go b/swagger/compiles_test.go index 8744cfc..fac2ffa 100644 --- a/swagger/compiles_test.go +++ b/swagger/compiles_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger_test import "testing" diff --git a/swagger/endpoint.go b/swagger/endpoint.go index 7d613b5..7aa84b2 100644 --- a/swagger/endpoint.go +++ b/swagger/endpoint.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger // Items represents items from the swagger doc diff --git a/swagger/reflect.go b/swagger/reflect.go index aeffec1..772f9b5 100644 --- a/swagger/reflect.go +++ b/swagger/reflect.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger import ( diff --git a/swagger/reflect_test.go b/swagger/reflect_test.go index 125dd66..31169c1 100644 --- a/swagger/reflect_test.go +++ b/swagger/reflect_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger import ( diff --git a/swagger/tag.go b/swagger/tag.go index 1ed3a8e..ba8bdd8 100644 --- a/swagger/tag.go +++ b/swagger/tag.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger // Docs represents tag docs from the swagger definition diff --git a/swagger/util.go b/swagger/util.go index d9acf6a..086fd10 100644 --- a/swagger/util.go +++ b/swagger/util.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger import ( diff --git a/swagger/util_test.go b/swagger/util_test.go index b3e4a45..b0bdfac 100644 --- a/swagger/util_test.go +++ b/swagger/util_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swagger import ( diff --git a/util.go b/util.go index 6623922..6f22700 100644 --- a/util.go +++ b/util.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swag import ( diff --git a/util_test.go b/util_test.go index e9306ae..537ff4d 100644 --- a/util_test.go +++ b/util_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Matt Ho +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// package swag_test import ( From d9b30744a3d0deaeedbd86379cd4972f4f3423b3 Mon Sep 17 00:00:00 2001 From: Matt Ho Date: Fri, 21 Jul 2017 21:24:45 -0700 Subject: [PATCH 5/6] added Apply method to both Option and ResponseOption --- endpoint/builder.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/endpoint/builder.go b/endpoint/builder.go index 6d19d32..b4e2076 100644 --- a/endpoint/builder.go +++ b/endpoint/builder.go @@ -30,6 +30,11 @@ type Builder struct { // Option represents a functional option to customize the swagger endpoint type Option func(builder *Builder) +// Apply improves the readability of applied options +func (o Option) Apply(builder *Builder) { + o(builder) +} + // Handler allows an instance of the web handler to be associated with the endpoint. This can be especially useful when // using swag to bind the endpoints to the web router. See the examples package for how the Handler can be used in // conjunction with Walk to simplify binding endpoints to a router @@ -155,6 +160,11 @@ func NoSecurity() Option { // ResponseOption allows for additional configurations on responses like header information type ResponseOption func(response *swagger.Response) +// Apply improves the readability of applied options +func (o ResponseOption) Apply(response *swagger.Response) { + o(response) +} + // Header adds header definitions to swagger responses func Header(name, typ, format, description string) ResponseOption { return func(response *swagger.Response) { @@ -183,7 +193,7 @@ func Response(code int, prototype interface{}, description string, opts ...Respo } for _, opt := range opts { - opt(&r) + opt.Apply(&r) } b.Endpoint.Responses[strconv.Itoa(code)] = r @@ -206,7 +216,7 @@ func New(method, path, summary string, options ...Option) *swagger.Endpoint { } for _, opt := range options { - opt(e) + opt.Apply(e) } return e.Endpoint From 3a75479e44a3ae7f3a4cc91baa4ad000ac81a8ed Mon Sep 17 00:00:00 2001 From: savaki Date: Sat, 22 Jul 2017 10:39:31 -0700 Subject: [PATCH 6/6] - Added support for specifying both the body and the response via reflect.Type rather than an instance of the type. Supports cases where one wants to generate a swagger interface via reflection. --- endpoint/builder.go | 24 +++++++++++++++++++----- endpoint/builder_test.go | 8 +++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/endpoint/builder.go b/endpoint/builder.go index b4e2076..ca39333 100644 --- a/endpoint/builder.go +++ b/endpoint/builder.go @@ -16,6 +16,7 @@ package endpoint import ( "net/http" + "reflect" "strconv" "strings" @@ -113,17 +114,24 @@ func Query(name, typ, description string, required bool) Option { // Body defines a body parameter for the swagger endpoint as would commonly be used for the POST, PUT, and PATCH methods // prototype should be a struct or a pointer to struct that swag can use to reflect upon the return type -func Body(prototype interface{}, description string, required bool) Option { +// t represents the Type of the body +func BodyType(t reflect.Type, description string, required bool) Option { p := swagger.Parameter{ In: "body", Name: "body", Description: description, - Schema: swagger.MakeSchema(prototype), + Schema: swagger.MakeSchema(t), Required: required, } return parameter(p) } +// Body defines a body parameter for the swagger endpoint as would commonly be used for the POST, PUT, and PATCH methods +// prototype should be a struct or a pointer to struct that swag can use to reflect upon the return type +func Body(prototype interface{}, description string, required bool) Option { + return BodyType(reflect.TypeOf(prototype), description, required) +} + // Tags allows one or more tags to be associated with the endpoint func Tags(tags ...string) Option { return func(b *Builder) { @@ -180,8 +188,9 @@ func Header(name, typ, format, description string) ResponseOption { } } -// Response sets the endpoint response for the specified code; may be used multiple times with different status codes -func Response(code int, prototype interface{}, description string, opts ...ResponseOption) Option { +// ResponseType sets the endpoint response for the specified code; may be used multiple times with different status codes +// t represents the Type of the response +func ResponseType(code int, t reflect.Type, description string, opts ...ResponseOption) Option { return func(b *Builder) { if b.Endpoint.Responses == nil { b.Endpoint.Responses = map[string]swagger.Response{} @@ -189,7 +198,7 @@ func Response(code int, prototype interface{}, description string, opts ...Respo r := swagger.Response{ Description: description, - Schema: swagger.MakeSchema(prototype), + Schema: swagger.MakeSchema(t), } for _, opt := range opts { @@ -200,6 +209,11 @@ func Response(code int, prototype interface{}, description string, opts ...Respo } } +// Response sets the endpoint response for the specified code; may be used multiple times with different status codes +func Response(code int, prototype interface{}, description string, opts ...ResponseOption) Option { + return ResponseType(code, reflect.TypeOf(prototype), description, opts...) +} + // New constructs a new swagger endpoint using the fields and functional options provided func New(method, path, summary string, options ...Option) *swagger.Endpoint { method = strings.ToUpper(method) diff --git a/endpoint/builder_test.go b/endpoint/builder_test.go index ecf5504..7452715 100644 --- a/endpoint/builder_test.go +++ b/endpoint/builder_test.go @@ -19,6 +19,8 @@ import ( "net/http" "testing" + "reflect" + "github.com/savaki/swag" "github.com/savaki/swag/endpoint" "github.com/savaki/swag/swagger" @@ -132,7 +134,7 @@ func TestBody(t *testing.T) { Required: true, Schema: &swagger.Schema{ Ref: "#/definitions/endpoint_testModel", - Prototype: Model{}, + Prototype: reflect.TypeOf(Model{}), }, } @@ -149,7 +151,7 @@ func TestResponse(t *testing.T) { Description: "successful", Schema: &swagger.Schema{ Ref: "#/definitions/endpoint_testModel", - Prototype: Model{}, + Prototype: reflect.TypeOf(Model{}), }, } @@ -166,7 +168,7 @@ func TestResponseHeader(t *testing.T) { Description: "successful", Schema: &swagger.Schema{ Ref: "#/definitions/endpoint_testModel", - Prototype: Model{}, + Prototype: reflect.TypeOf(Model{}), }, Headers: map[string]swagger.Header{ "X-Rate-Limit": {