Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,19 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
for (CodegenOperation operation : operations) {
// http method verb conversion (e.g. PUT => Put)
operation.httpMethod = camelize(operation.httpMethod.toLowerCase(Locale.ROOT));

// Convert x-custom-attributes map into a list of {key, value} entries for mustache iteration
Object customAttrs = operation.vendorExtensions.get("x-custom-attributes");
if (customAttrs instanceof Map) {
List<Map<String, String>> attrList = new ArrayList<>();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) customAttrs).entrySet()) {
Map<String, String> attr = new HashMap<>();
attr.put("key", String.valueOf(entry.getKey()));
attr.put("value", String.valueOf(entry.getValue()));
attrList.add(attr);
}
operation.vendorExtensions.put("x-custom-attributes-list", attrList);
}
}

// remove model imports to avoid error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ func (c *{{classname}}Controller) Routes() Routes {
strings.ToUpper("{{httpMethod}}"),
"{{{basePathWithoutHost}}}{{{path}}}",
c.{{operationId}},
map[string]string{
{{#vendorExtensions.x-custom-attributes-list}}
"{{key}}": "{{value}}",
{{/vendorExtensions.x-custom-attributes-list}}
},
[]AuthMethod{
{{#authMethods}}
{
"{{name}}",
[]string{ {{#scopes}}"{{scope}}", {{/scopes}} },
},
{{/authMethods}}
},
},
{{/operation}}
{{/operations}}
Expand Down Expand Up @@ -462,7 +475,7 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
}
{{/items.isInteger}}
{{#items.isDateTime}}
{{paramName}}Param, err := parseTimes(query.Get("{{baseName"}}))
{{paramName}}Param, err := parseTimes(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Param: "{{baseName}}", Err: err}, nil)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func main() {
{{classname}}Service := {{packageName}}.New{{classname}}Service()
{{classname}}Controller := {{packageName}}.New{{classname}}Controller({{classname}}Service)
{{/apis}}{{/apiInfo}}
router := {{packageName}}.NewRouter({{#apiInfo}}{{#apis}}{{classname}}Controller{{^-last}}, {{/-last}}{{/apis}}{{/apiInfo}})
router := {{packageName}}.NewRouter(nil, {{#apiInfo}}{{#apis}}{{classname}}Controller{{^-last}}, {{/-last}}{{/apis}}{{/apiInfo}})

log.Fatal(http.ListenAndServe(":{{serverPort}}", router))
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,28 @@ import (
"bytes"
)

// AuthMethod describes a security scheme and its required scopes for a route
type AuthMethod struct {
Name string
Scopes []string
}

// A Route defines the parameters for an api endpoint
type Route struct {
Method string
Pattern string
HandlerFunc http.HandlerFunc
Method string
Pattern string
HandlerFunc http.HandlerFunc
CustomAttributes map[string]string
AuthMethods []AuthMethod
}

// Routes is a map of defined api endpoints
type Routes map[string]Route

// Authorizer is called before each route handler to perform authorization.
// Return nil to allow the request, or a non-nil error to deny it.
type Authorizer func(route Route, r *http.Request) error

// Router defines the required methods for retrieving api routes
type Router interface {
Routes() Routes
Expand All @@ -50,7 +62,7 @@ const errMsgMinValueConstraint = "provided parameter is not respecting minimum v
const errMsgMaxValueConstraint = "provided parameter is not respecting maximum value constraint"

// NewRouter creates a new router for any number of api routers
func NewRouter(routers ...Router) {{#routers}}{{#mux}}*mux.Router{{/mux}}{{#chi}}chi.Router{{/chi}}{{/routers}} {
func NewRouter(authorizer Authorizer, routers ...Router) {{#routers}}{{#mux}}*mux.Router{{/mux}}{{#chi}}chi.Router{{/chi}}{{/routers}} {
{{#routers}}
{{#mux}}
router := mux.NewRouter().StrictSlash(true)
Expand All @@ -66,6 +78,16 @@ func NewRouter(routers ...Router) {{#routers}}{{#mux}}*mux.Router{{/mux}}{{#chi}
for _, api := range routers {
for {{#routers}}{{#mux}}name{{/mux}}{{#chi}}_{{/chi}}{{/routers}}, route := range api.Routes() {
var handler http.Handler = route.HandlerFunc
if authorizer != nil {
route := route // capture loop variable
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := authorizer(route, r); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
route.HandlerFunc(w, r)
})
}
{{#routers}}
{{#mux}}
handler = Logger(handler, name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,21 @@ public void verifyOrder() throws IOException {
"type Routes map[string]Route");

TestUtils.assertFileExists(Paths.get(output + "/go/api_dev.go"));
// verify /getPath/latest is first route
Assert.assertEquals(Files.readAllLines(Paths.get(output + "/go/api_dev.go")).get(52), "\t\t\"GetLatest\": Route{");
// verify /getPath/{id} is second route
Assert.assertEquals(Files.readAllLines(Paths.get(output + "/go/api_dev.go")).get(57), "\t\t\"GetById\": Route{");
// verify both routes exist and /getPath/latest comes before /getPath/{id}
List<String> lines = Files.readAllLines(Paths.get(output + "/go/api_dev.go"));
int getLatestLine = -1;
int getByIdLine = -1;
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).contains("\"GetLatest\": Route{")) {
getLatestLine = i;
}
if (lines.get(i).contains("\"GetById\": Route{")) {
getByIdLine = i;
}
}
Assert.assertTrue(getLatestLine >= 0, "GetLatest route not found");
Assert.assertTrue(getByIdLine >= 0, "GetById route not found");
Assert.assertTrue(getLatestLine < getByIdLine, "GetLatest should come before GetById");

}

Expand Down
Loading