Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(extensions): adds vendor extensions to all entities #477

Merged
merged 3 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions extensions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package restful

// Copyright 2021 Ernest Micklei. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

// ExtensionProperties provides storage of vendor extensions for entities
type ExtensionProperties struct {
// Extensions vendor extensions used to describe extra functionality
// (https://swagger.io/docs/specification/2-0/swagger-extensions/)
Extensions map[string]interface{}
}

// AddExtension adds or updates a key=value pair to the extension map.
func (ep *ExtensionProperties) AddExtension(key string, value interface{}) {
if ep.Extensions == nil {
ep.Extensions = map[string]interface{}{key: value}
} else {
ep.Extensions[key] = value
}
}
1 change: 1 addition & 0 deletions parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Parameter struct {
// ParameterData represents the state of a Parameter.
// It is made public to make it accessible to e.g. the Swagger package.
type ParameterData struct {
ExtensionProperties
Name, Description, DataType, DataFormat string
Kind int
Required bool
Expand Down
1 change: 1 addition & 0 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type RouteSelectionConditionFunction func(httpRequest *http.Request) bool

// Route binds a HTTP Method,Path,Consumes combination to a RouteFunction.
type Route struct {
ExtensionProperties
Method string
Produces []string
Consumes []string
Expand Down
14 changes: 13 additions & 1 deletion route_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type RouteBuilder struct {
errorMap map[int]ResponseError
defaultResponse *ResponseError
metadata map[string]interface{}
extensions map[string]interface{}
deprecated bool
contentEncodingEnabled *bool
}
Expand Down Expand Up @@ -204,13 +205,22 @@ func (b *RouteBuilder) Metadata(key string, value interface{}) *RouteBuilder {
return b
}

// AddExtension adds or updates a key=value pair to the extensions map.
func (b *RouteBuilder) AddExtension(key string, value interface{}) *RouteBuilder {
if b.extensions == nil {
b.extensions = map[string]interface{}{}
}
b.extensions[key] = value
return b
}

// Deprecate sets the value of deprecated to true. Deprecated routes have a special UI treatment to warn against use
func (b *RouteBuilder) Deprecate() *RouteBuilder {
b.deprecated = true
return b
}

// AllowedMethodsWithoutContentType overides the default list GET,HEAD,OPTIONS,DELETE,TRACE
// AllowedMethodsWithoutContentType overrides the default list GET,HEAD,OPTIONS,DELETE,TRACE
// If a request does not include a content-type header then
// depending on the method, it may return a 415 Unsupported Media.
// Must have uppercase HTTP Method names such as GET,HEAD,OPTIONS,...
Expand All @@ -221,6 +231,7 @@ func (b *RouteBuilder) AllowedMethodsWithoutContentType(methods []string) *Route

// ResponseError represents a response; not necessarily an error.
type ResponseError struct {
ExtensionProperties
Code int
Message string
Model interface{}
Expand Down Expand Up @@ -335,6 +346,7 @@ func (b *RouteBuilder) Build() Route {
contentEncodingEnabled: b.contentEncodingEnabled,
allowedMethodsWithoutContentType: b.allowedMethodsWithoutContentType,
}
route.Extensions = b.extensions
route.postBuild()
return route
}
Expand Down
17 changes: 13 additions & 4 deletions route_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ func TestRouteBuilder(t *testing.T) {
json := "application/json"
b := new(RouteBuilder)
b.To(dummy)
b.Path("/routes").Method("HEAD").Consumes(json).Produces(json).Metadata("test", "test-value").DefaultReturns("default", time.Now())
b.Path("/routes").
Method("HEAD").
Consumes(json).
Produces(json).
Metadata("test", "test-value").
AddExtension("x-restful-test", "test-value").
DefaultReturns("default", time.Now())
r := b.Build()
if r.Path != "/routes" {
t.Error("path invalid")
Expand All @@ -59,6 +65,9 @@ func TestRouteBuilder(t *testing.T) {
if r.Metadata["test"] != "test-value" {
t.Errorf("Metadata not set")
}
if r.Extensions["x-restful-test"] != "test-value" {
t.Errorf("Extensions not set")
}
if r.DefaultResponse == nil {
t.Fatal("expected default response")
}
Expand Down Expand Up @@ -91,13 +100,13 @@ func TestContentEncodingEnabled(t *testing.T) {
r := b.Build()

got := r.contentEncodingEnabled
var want *bool //nil
var want *bool // nil

if got != want {
t.Errorf("got %v want %v (default nil)", got, want)
}

//true
// true
b = new(RouteBuilder)
b.function = dummy
b.ContentEncodingEnabled(true)
Expand All @@ -108,7 +117,7 @@ func TestContentEncodingEnabled(t *testing.T) {
t.Errorf("got %v want %v (explicit true)", *got, true)
}

//true
// true
b = new(RouteBuilder)
b.function = dummy
b.ContentEncodingEnabled(false)
Expand Down