router/router.go (110 lines of code) (raw):
package router
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
var ConsoleVersion = "0"
type Logger interface {
Error(msg string, fields ...zap.Field)
}
type Router struct {
engine *gin.Engine
logger Logger
buildTime time.Time
}
type HTMLResponse struct {
StatusResponse
viewTemplate string
params gin.H
}
type StatusResponse struct {
StatusCode int
}
func (s *StatusResponse) Code() int {
return s.StatusCode
}
type RedirectResponse struct {
StatusResponse
path string
}
type JSONResponse struct {
StatusResponse
data interface{}
}
type Response interface {
Code() int
}
func MakeJSONResponse(code int, data interface{}) Response {
return &JSONResponse{
StatusResponse: StatusResponse{StatusCode: code},
data: data,
}
}
func MakeHTMLResponse(code int, viewTemplate string, params gin.H) Response {
params["consoleVersion"] = ConsoleVersion
return &HTMLResponse{
StatusResponse: StatusResponse{
StatusCode: code,
},
viewTemplate: viewTemplate,
params: params,
}
}
func MakeStatusResponse(code int) Response {
return &StatusResponse{StatusCode: code}
}
func MakeRedirectResponse(code int, path string) Response {
return &RedirectResponse{
StatusResponse: StatusResponse{StatusCode: code},
path: path,
}
}
func (r *Router) makeViewResponder(handler func(ctx *gin.Context) (Response, error)) func(ctx *gin.Context) {
return func(ctx *gin.Context) {
rsp, err := handler(ctx)
if err != nil {
r.logger.Error(fmt.Sprintf("%+v", err))
ctx.String(500, "%+v", err)
return
}
if rsp == nil {
r.logger.Error("empty view response")
ctx.String(500, "empty view response")
return
}
switch rspType := rsp.(type) {
case *StatusResponse:
ctx.Status(rsp.Code())
case *RedirectResponse:
ctx.Redirect(rspType.Code(), rspType.path)
case *HTMLResponse:
rspType.params = r.parseValidationErrors(rspType.params)
rspType.params = r.includeSessionVars(ctx, rspType.params)
ctx.HTML(rspType.Code(), rspType.viewTemplate, rspType.params)
case *JSONResponse:
ctx.JSON(rspType.Code(), rspType.data)
}
}
}
func (r *Router) includeSessionVars(ctx *gin.Context, params gin.H) gin.H {
params["username"] = ctx.GetString(UserNameSessionKey)
params["buildDate"] = r.buildTime.Unix()
params["canViewRegistries"] = ctx.GetBool(CanViewRegistriesSessionKey) || ctx.GetBool(CanCreateRegistriesSessionKey)
params["canViewClusterManagement"] = ctx.GetBool(CanViewClusterManagementSessionKey)
return params
}
func (r *Router) GET(relativePath string, handler func(ctx *gin.Context) (Response, error)) {
r.engine.GET(relativePath, r.makeViewResponder(handler))
}
func (r *Router) POST(relativePath string, handler func(ctx *gin.Context) (Response, error)) {
r.engine.POST(relativePath, r.makeViewResponder(handler))
}
func Make(engine *gin.Engine, logger Logger, buildTime time.Time) *Router {
return &Router{
engine: engine,
logger: logger,
buildTime: buildTime,
}
}