TODO: fix middleware nil point
This commit is contained in:
parent
57662079f6
commit
574d25691c
@ -1 +0,0 @@
|
|||||||
package access
|
|
8
internal/consts/base_response.go
Normal file
8
internal/consts/base_response.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
type BaseResponse struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data any `json:"data,omitempty"`
|
||||||
|
}
|
@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Metadata struct {
|
type Request struct {
|
||||||
Http *gin.Context
|
Http *gin.Context
|
||||||
User *UserTokenInfo
|
User *UserTokenInfo
|
||||||
}
|
}
|
||||||
|
@ -22,3 +22,5 @@ type UserTokenInfo struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Groups []string `json:"groups"`
|
Groups []string `json:"groups"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UserTokenInfoKey = "user.jwt"
|
||||||
|
32
internal/helper/response.go
Normal file
32
internal/helper/response.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"framework_v2/internal/consts"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ResponseMessage(c *gin.Context, code int, message string, data interface{}) {
|
||||||
|
c.JSON(code, &consts.BaseResponse{
|
||||||
|
Message: message,
|
||||||
|
Code: code,
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Response(c *gin.Context, code int, data interface{}) {
|
||||||
|
c.JSON(code, &consts.BaseResponse{
|
||||||
|
Code: code,
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResponseError(c *gin.Context, code int, err error) {
|
||||||
|
c.JSON(code, &consts.BaseResponse{
|
||||||
|
Error: err.Error(),
|
||||||
|
Code: code,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
|
||||||
|
}
|
@ -6,8 +6,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CurrentUser(req *consts.Metadata) {
|
func CurrentUser(req *consts.Request) {
|
||||||
req.Http.JSON(http.StatusOK, gin.H{
|
req.Http.JSON(http.StatusOK, gin.H{
|
||||||
"req": req.User,
|
"req": req.User.Sub,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"framework_v2/internal/access"
|
"framework_v2/internal/access"
|
||||||
"framework_v2/internal/http/routes"
|
"framework_v2/internal/providers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitHttp() {
|
func InitHttp() {
|
||||||
@ -10,5 +10,5 @@ func InitHttp() {
|
|||||||
panic("You must call InitGin() before InitHttp()")
|
panic("You must call InitGin() before InitHttp()")
|
||||||
}
|
}
|
||||||
|
|
||||||
routes.InitApiRoutes()
|
providers.InitApiRoutes()
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package routes
|
|
||||||
|
|
||||||
import "framework_v2/internal/http/controllers/user"
|
|
||||||
|
|
||||||
func InitApiRoutes() {
|
|
||||||
HandleRoute(GET, "/", user.CurrentUser)
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package routes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"framework_v2/internal/access"
|
|
||||||
"framework_v2/internal/consts"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type httpMethod int
|
|
||||||
|
|
||||||
var httpMethodStr = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
|
|
||||||
|
|
||||||
func (h httpMethod) String() string {
|
|
||||||
return httpMethodStr[h-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
GET httpMethod = iota + 1
|
|
||||||
POST
|
|
||||||
PUT
|
|
||||||
DELETE
|
|
||||||
PATCH
|
|
||||||
HEAD
|
|
||||||
OPTIONS
|
|
||||||
)
|
|
||||||
|
|
||||||
type HandlerFunc func(metadata *consts.Metadata)
|
|
||||||
|
|
||||||
func HandleRoute(method httpMethod, relativePath string, controller HandlerFunc, middlewares ...gin.HandlerFunc) {
|
|
||||||
access.Router.Handle(method.String(), relativePath, func(c *gin.Context) {
|
|
||||||
for _, middleware := range middlewares {
|
|
||||||
middleware(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
handleWithMetadata(c, controller)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleWithMetadata(c *gin.Context, controller HandlerFunc) {
|
|
||||||
var metadata = &consts.Metadata{
|
|
||||||
Http: c,
|
|
||||||
}
|
|
||||||
|
|
||||||
controller(metadata)
|
|
||||||
}
|
|
9
internal/providers/api_routes.go
Normal file
9
internal/providers/api_routes.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"framework_v2/internal/http/controllers/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitApiRoutes() {
|
||||||
|
HandleRoute(GET, "/", user.CurrentUser, MiddlewareJWTAuth, MiddlewareJSONResponse)
|
||||||
|
}
|
@ -2,6 +2,7 @@ package providers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"framework_v2/internal/access"
|
"framework_v2/internal/access"
|
||||||
|
"framework_v2/internal/consts"
|
||||||
ginzap "github.com/gin-contrib/zap"
|
ginzap "github.com/gin-contrib/zap"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"time"
|
"time"
|
||||||
@ -12,6 +13,48 @@ func InitGin() {
|
|||||||
|
|
||||||
access.Router = gin.New()
|
access.Router = gin.New()
|
||||||
|
|
||||||
access.Router.Use(gin.Recovery(), ginzap.Ginzap(access.Logger, time.RFC3339, true))
|
access.Router.Use(ginzap.Ginzap(access.Logger, time.RFC3339, true))
|
||||||
access.Router.Use(ginzap.RecoveryWithZap(access.Logger, true))
|
//access.Router.Use(gin.Recovery())
|
||||||
|
//access.Router.Use(ginzap.RecoveryWithZap(access.Logger, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpMethod int
|
||||||
|
|
||||||
|
var httpMethodStr = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
|
||||||
|
|
||||||
|
func (h httpMethod) String() string {
|
||||||
|
return httpMethodStr[h-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
GET httpMethod = iota + 1
|
||||||
|
POST
|
||||||
|
PUT
|
||||||
|
DELETE
|
||||||
|
PATCH
|
||||||
|
HEAD
|
||||||
|
OPTIONS
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlerFunc func(metadata *consts.Request)
|
||||||
|
|
||||||
|
func HandleRoute(method httpMethod, relativePath string, controller HandlerFunc, middlewares ...gin.HandlerFunc) {
|
||||||
|
access.Router.Handle(method.String(), relativePath, func(c *gin.Context) {
|
||||||
|
for _, middleware := range middlewares {
|
||||||
|
middleware(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.IsAborted() {
|
||||||
|
handleWithMetadata(c, controller)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleWithMetadata(c *gin.Context, controller HandlerFunc) {
|
||||||
|
var metadata = &consts.Request{
|
||||||
|
Http: c,
|
||||||
|
User: GetAuthFromCtx(c),
|
||||||
|
}
|
||||||
|
|
||||||
|
controller(metadata)
|
||||||
}
|
}
|
||||||
|
77
internal/providers/gin_middleware.go
Normal file
77
internal/providers/gin_middleware.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"framework_v2/internal/consts"
|
||||||
|
"framework_v2/internal/helper"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotValidToken = errors.New("无效的 JWT 令牌。")
|
||||||
|
ErrJWTFormatError = errors.New("JWT 格式错误。")
|
||||||
|
ErrNotBearerType = errors.New("不是 Bearer 类型。")
|
||||||
|
)
|
||||||
|
|
||||||
|
const AnonymousUser = "anonymous"
|
||||||
|
|
||||||
|
func MiddlewareJWTAuth(c *gin.Context) {
|
||||||
|
var sub = AnonymousUser
|
||||||
|
var jwtIdToken = consts.UserTokenInfo{}
|
||||||
|
|
||||||
|
if Config.DebugMode.Enable {
|
||||||
|
jwtIdToken.Sub = sub
|
||||||
|
} else {
|
||||||
|
// get authorization header
|
||||||
|
authorization := c.Request.Header.Get("Authorization")
|
||||||
|
|
||||||
|
if authorization == "" {
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrJWTFormatError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
authSplit := strings.Split(authorization, " ")
|
||||||
|
if len(authSplit) != 2 {
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrJWTFormatError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if authSplit[0] != "Bearer" {
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrNotBearerType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := ParseJWT(authSplit[1])
|
||||||
|
if err != nil {
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrJWTFormatError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sub, err = token.Claims.GetSubject()
|
||||||
|
if err != nil {
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrNotValidToken)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mapstructure.Decode(token.Claims, &jwtIdToken)
|
||||||
|
if err != nil {
|
||||||
|
Logger.Error("Failed to map token claims to JwtIDToken struct.\nError: " + err.Error())
|
||||||
|
helper.ResponseError(c, http.StatusUnauthorized, ErrNotValidToken)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("test", jwtIdToken.Sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set(consts.UserTokenInfoKey, jwtIdToken)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func MiddlewareJSONResponse(c *gin.Context) {
|
||||||
|
c.Header("Content-Type", "application/json; charset=utf-8")
|
||||||
|
c.Next()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user