Update go-gin-server templates to return a configurable library (#10479)

* Update go-gin-server templates to return a configurable library

Before this change, the user would be required to make changes in the
generated code. This makes it really hard to update the API and the
documentation at the same time. With this change, the generated code can
be imported as is and used. The user just needs to set the handler
functions for each endpoint.

* Use spaces instead of tabs for api files

* Use space instead of tab for ApiHandleFunctions in go-gin-server

* Update samples for go-gin-server
This commit is contained in:
Wouter Wijsman 2023-08-19 12:42:58 +02:00 committed by GitHub
parent 141b3d4e0b
commit a55453b5f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 252 additions and 295 deletions

View File

@ -3,15 +3,16 @@ package {{packageName}}
{{#operations}} {{#operations}}
import ( import (
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
){{#operation}} )
// {{nickname}} - {{{summary}}} type {{classname}} struct {
{{#operation}}
// {{httpMethod}} {{{basePathWithoutHost}}}{{{path}}}
// {{{summary}}}
{{#isDeprecated}} {{#isDeprecated}}
// Deprecated // Deprecated
{{/isDeprecated}} {{/isDeprecated}}
func {{nickname}}(c *gin.Context) { {{nickname}} gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) {{/operation}}
}{{/operation}}{{/operations}} }{{/operations}}

View File

@ -11,9 +11,11 @@ import (
) )
func main() { func main() {
routes := sw.ApiHandleFunctions{}
log.Printf("Server started") log.Printf("Server started")
router := sw.NewRouter() router := sw.NewRouter(routes)
log.Fatal(router.Run(":{{serverPort}}")) log.Fatal(router.Run(":{{serverPort}}"))
} }

View File

@ -10,22 +10,22 @@ import (
// Route is the information for every URI. // Route is the information for every URI.
type Route struct { type Route struct {
// Name is the name of this Route. // Name is the name of this Route.
Name string Name string
// Method is the string for the HTTP method. ex) GET, POST etc.. // Method is the string for the HTTP method. ex) GET, POST etc..
Method string Method string
// Pattern is the pattern of the URI. // Pattern is the pattern of the URI.
Pattern string Pattern string
// HandlerFunc is the handler function of this route. // HandlerFunc is the handler function of this route.
HandlerFunc gin.HandlerFunc HandlerFunc gin.HandlerFunc
} }
// Routes is the list of the generated Route.
type Routes []Route
// NewRouter returns a new router. // NewRouter returns a new router.
func NewRouter() *gin.Engine { func NewRouter(handleFunctions ApiHandleFunctions) *gin.Engine {
router := gin.Default() router := gin.Default()
for _, route := range routes { for _, route := range getRoutes(handleFunctions) {
if route.HandlerFunc == nil {
route.HandlerFunc = DefaultHandleFunc
}
switch route.Method { switch route.Method {
case http.MethodGet: case http.MethodGet:
router.GET(route.Pattern, route.HandlerFunc) router.GET(route.Pattern, route.HandlerFunc)
@ -43,23 +43,25 @@ func NewRouter() *gin.Engine {
return router return router
} }
// Index is the index handler. // Default handler for not yet implemented routes
func Index(c *gin.Context) { func DefaultHandleFunc(c *gin.Context) {
c.String(http.StatusOK, "Hello World!") c.String(http.StatusNotImplemented, "501 not implemented")
} }
var routes = Routes{ type ApiHandleFunctions struct {
{ {{#apiInfo}}{{#apis}}{{#operations}}
"Index", // Routes for the {{classname}} part of the API
http.MethodGet, {{classname}} {{classname}}{{/operations}}{{/apis}}{{/apiInfo}}
"{{{basePathWithoutHost}}}/", }
Index,
},{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} func getRoutes(handleFunctions ApiHandleFunctions) []Route {
return []Route{
{ {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
"{{operationId}}", {
http.Method{{httpMethod}}, "{{operationId}}",
"{{{basePathWithoutHost}}}{{{path}}}", http.Method{{httpMethod}},
{{operationId}}, "{{{basePathWithoutHost}}}{{{path}}}",
},{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} handleFunctions.{{classname}}.{{operationId}},
},{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}
} }

View File

@ -10,48 +10,33 @@
package petstoreserver package petstoreserver
import ( import (
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// AddPet - Add a new pet to the store type PetApi struct {
func AddPet(c *gin.Context) { // Post /v2/pet
c.JSON(http.StatusOK, gin.H{}) // Add a new pet to the store
} AddPet gin.HandlerFunc
// Delete /v2/pet/:petId
// DeletePet - Deletes a pet // Deletes a pet
func DeletePet(c *gin.Context) { DeletePet gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) // Get /v2/pet/findByStatus
} // Finds Pets by status
FindPetsByStatus gin.HandlerFunc
// FindPetsByStatus - Finds Pets by status // Get /v2/pet/findByTags
func FindPetsByStatus(c *gin.Context) { // Finds Pets by tags
c.JSON(http.StatusOK, gin.H{}) // Deprecated
} FindPetsByTags gin.HandlerFunc
// Get /v2/pet/:petId
// FindPetsByTags - Finds Pets by tags // Find pet by ID
// Deprecated GetPetById gin.HandlerFunc
func FindPetsByTags(c *gin.Context) { // Put /v2/pet
c.JSON(http.StatusOK, gin.H{}) // Update an existing pet
} UpdatePet gin.HandlerFunc
// Post /v2/pet/:petId
// GetPetById - Find pet by ID // Updates a pet in the store with form data
func GetPetById(c *gin.Context) { UpdatePetWithForm gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) // Post /v2/pet/:petId/uploadImage
} // uploads an image
UploadFile gin.HandlerFunc
// UpdatePet - Update an existing pet
func UpdatePet(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
}
// UpdatePetWithForm - Updates a pet in the store with form data
func UpdatePetWithForm(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
}
// UploadFile - uploads an image
func UploadFile(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
} }

View File

@ -10,27 +10,20 @@
package petstoreserver package petstoreserver
import ( import (
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// DeleteOrder - Delete purchase order by ID type StoreApi struct {
func DeleteOrder(c *gin.Context) { // Delete /v2/store/order/:orderId
c.JSON(http.StatusOK, gin.H{}) // Delete purchase order by ID
} DeleteOrder gin.HandlerFunc
// Get /v2/store/inventory
// GetInventory - Returns pet inventories by status // Returns pet inventories by status
func GetInventory(c *gin.Context) { GetInventory gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) // Get /v2/store/order/:orderId
} // Find purchase order by ID
GetOrderById gin.HandlerFunc
// GetOrderById - Find purchase order by ID // Post /v2/store/order
func GetOrderById(c *gin.Context) { // Place an order for a pet
c.JSON(http.StatusOK, gin.H{}) PlaceOrder gin.HandlerFunc
}
// PlaceOrder - Place an order for a pet
func PlaceOrder(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
} }

View File

@ -10,47 +10,32 @@
package petstoreserver package petstoreserver
import ( import (
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// CreateUser - Create user type UserApi struct {
func CreateUser(c *gin.Context) { // Post /v2/user
c.JSON(http.StatusOK, gin.H{}) // Create user
} CreateUser gin.HandlerFunc
// Post /v2/user/createWithArray
// CreateUsersWithArrayInput - Creates list of users with given input array // Creates list of users with given input array
func CreateUsersWithArrayInput(c *gin.Context) { CreateUsersWithArrayInput gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) // Post /v2/user/createWithList
} // Creates list of users with given input array
CreateUsersWithListInput gin.HandlerFunc
// CreateUsersWithListInput - Creates list of users with given input array // Delete /v2/user/:username
func CreateUsersWithListInput(c *gin.Context) { // Delete user
c.JSON(http.StatusOK, gin.H{}) DeleteUser gin.HandlerFunc
} // Get /v2/user/:username
// Get user by user name
// DeleteUser - Delete user GetUserByName gin.HandlerFunc
func DeleteUser(c *gin.Context) { // Get /v2/user/login
c.JSON(http.StatusOK, gin.H{}) // Logs user into the system
} LoginUser gin.HandlerFunc
// Get /v2/user/logout
// GetUserByName - Get user by user name // Logs out current logged in user session
func GetUserByName(c *gin.Context) { LogoutUser gin.HandlerFunc
c.JSON(http.StatusOK, gin.H{}) // Put /v2/user/:username
} // Updated user
UpdateUser gin.HandlerFunc
// LoginUser - Logs user into the system
func LoginUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
}
// LogoutUser - Logs out current logged in user session
func LogoutUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
}
// UpdateUser - Updated user
func UpdateUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
} }

View File

@ -18,22 +18,22 @@ import (
// Route is the information for every URI. // Route is the information for every URI.
type Route struct { type Route struct {
// Name is the name of this Route. // Name is the name of this Route.
Name string Name string
// Method is the string for the HTTP method. ex) GET, POST etc.. // Method is the string for the HTTP method. ex) GET, POST etc..
Method string Method string
// Pattern is the pattern of the URI. // Pattern is the pattern of the URI.
Pattern string Pattern string
// HandlerFunc is the handler function of this route. // HandlerFunc is the handler function of this route.
HandlerFunc gin.HandlerFunc HandlerFunc gin.HandlerFunc
} }
// Routes is the list of the generated Route.
type Routes []Route
// NewRouter returns a new router. // NewRouter returns a new router.
func NewRouter() *gin.Engine { func NewRouter(handleFunctions ApiHandleFunctions) *gin.Engine {
router := gin.Default() router := gin.Default()
for _, route := range routes { for _, route := range getRoutes(handleFunctions) {
if route.HandlerFunc == nil {
route.HandlerFunc = DefaultHandleFunc
}
switch route.Method { switch route.Method {
case http.MethodGet: case http.MethodGet:
router.GET(route.Pattern, route.HandlerFunc) router.GET(route.Pattern, route.HandlerFunc)
@ -51,156 +51,143 @@ func NewRouter() *gin.Engine {
return router return router
} }
// Index is the index handler. // Default handler for not yet implemented routes
func Index(c *gin.Context) { func DefaultHandleFunc(c *gin.Context) {
c.String(http.StatusOK, "Hello World!") c.String(http.StatusNotImplemented, "501 not implemented")
} }
var routes = Routes{ type ApiHandleFunctions struct {
{
"Index",
http.MethodGet,
"/v2/",
Index,
},
{ // Routes for the PetApi part of the API
"AddPet", PetApi PetApi
http.MethodPost, // Routes for the StoreApi part of the API
"/v2/pet", StoreApi StoreApi
AddPet, // Routes for the UserApi part of the API
}, UserApi UserApi
}
{
"DeletePet", func getRoutes(handleFunctions ApiHandleFunctions) []Route {
http.MethodDelete, return []Route{
"/v2/pet/:petId",
DeletePet, {
}, "AddPet",
http.MethodPost,
{ "/v2/pet",
"FindPetsByStatus", handleFunctions.PetApi.AddPet,
http.MethodGet, },
"/v2/pet/findByStatus", {
FindPetsByStatus, "DeletePet",
}, http.MethodDelete,
"/v2/pet/:petId",
{ handleFunctions.PetApi.DeletePet,
"FindPetsByTags", },
http.MethodGet, {
"/v2/pet/findByTags", "FindPetsByStatus",
FindPetsByTags, http.MethodGet,
}, "/v2/pet/findByStatus",
handleFunctions.PetApi.FindPetsByStatus,
{ },
"GetPetById", {
http.MethodGet, "FindPetsByTags",
"/v2/pet/:petId", http.MethodGet,
GetPetById, "/v2/pet/findByTags",
}, handleFunctions.PetApi.FindPetsByTags,
},
{ {
"UpdatePet", "GetPetById",
http.MethodPut, http.MethodGet,
"/v2/pet", "/v2/pet/:petId",
UpdatePet, handleFunctions.PetApi.GetPetById,
}, },
{
{ "UpdatePet",
"UpdatePetWithForm", http.MethodPut,
http.MethodPost, "/v2/pet",
"/v2/pet/:petId", handleFunctions.PetApi.UpdatePet,
UpdatePetWithForm, },
}, {
"UpdatePetWithForm",
{ http.MethodPost,
"UploadFile", "/v2/pet/:petId",
http.MethodPost, handleFunctions.PetApi.UpdatePetWithForm,
"/v2/pet/:petId/uploadImage", },
UploadFile, {
}, "UploadFile",
http.MethodPost,
{ "/v2/pet/:petId/uploadImage",
"DeleteOrder", handleFunctions.PetApi.UploadFile,
http.MethodDelete, },
"/v2/store/order/:orderId", {
DeleteOrder, "DeleteOrder",
}, http.MethodDelete,
"/v2/store/order/:orderId",
{ handleFunctions.StoreApi.DeleteOrder,
"GetInventory", },
http.MethodGet, {
"/v2/store/inventory", "GetInventory",
GetInventory, http.MethodGet,
}, "/v2/store/inventory",
handleFunctions.StoreApi.GetInventory,
{ },
"GetOrderById", {
http.MethodGet, "GetOrderById",
"/v2/store/order/:orderId", http.MethodGet,
GetOrderById, "/v2/store/order/:orderId",
}, handleFunctions.StoreApi.GetOrderById,
},
{ {
"PlaceOrder", "PlaceOrder",
http.MethodPost, http.MethodPost,
"/v2/store/order", "/v2/store/order",
PlaceOrder, handleFunctions.StoreApi.PlaceOrder,
}, },
{
{ "CreateUser",
"CreateUser", http.MethodPost,
http.MethodPost, "/v2/user",
"/v2/user", handleFunctions.UserApi.CreateUser,
CreateUser, },
}, {
"CreateUsersWithArrayInput",
{ http.MethodPost,
"CreateUsersWithArrayInput", "/v2/user/createWithArray",
http.MethodPost, handleFunctions.UserApi.CreateUsersWithArrayInput,
"/v2/user/createWithArray", },
CreateUsersWithArrayInput, {
}, "CreateUsersWithListInput",
http.MethodPost,
{ "/v2/user/createWithList",
"CreateUsersWithListInput", handleFunctions.UserApi.CreateUsersWithListInput,
http.MethodPost, },
"/v2/user/createWithList", {
CreateUsersWithListInput, "DeleteUser",
}, http.MethodDelete,
"/v2/user/:username",
{ handleFunctions.UserApi.DeleteUser,
"DeleteUser", },
http.MethodDelete, {
"/v2/user/:username", "GetUserByName",
DeleteUser, http.MethodGet,
}, "/v2/user/:username",
handleFunctions.UserApi.GetUserByName,
{ },
"GetUserByName", {
http.MethodGet, "LoginUser",
"/v2/user/:username", http.MethodGet,
GetUserByName, "/v2/user/login",
}, handleFunctions.UserApi.LoginUser,
},
{ {
"LoginUser", "LogoutUser",
http.MethodGet, http.MethodGet,
"/v2/user/login", "/v2/user/logout",
LoginUser, handleFunctions.UserApi.LogoutUser,
}, },
{
{ "UpdateUser",
"LogoutUser", http.MethodPut,
http.MethodGet, "/v2/user/:username",
"/v2/user/logout", handleFunctions.UserApi.UpdateUser,
LogoutUser, },
}, }
{
"UpdateUser",
http.MethodPut,
"/v2/user/:username",
UpdateUser,
},
} }

View File

@ -19,9 +19,11 @@ import (
) )
func main() { func main() {
routes := sw.ApiHandleFunctions{}
log.Printf("Server started") log.Printf("Server started")
router := sw.NewRouter() router := sw.NewRouter(routes)
log.Fatal(router.Run(":8080")) log.Fatal(router.Run(":8080"))
} }