chore(deps): upgrade echo framework from v4 to v5 and remove custom context middleware

This commit is contained in:
keven1024
2026-02-26 16:09:47 +08:00
parent e9d0848f87
commit b98853ebe1
20 changed files with 64 additions and 125 deletions

View File

@@ -8,14 +8,13 @@ require (
github.com/gorilla/sessions v1.4.0
github.com/hibiken/asynq v0.25.1
github.com/labstack/echo-contrib v0.50.0
github.com/labstack/echo/v4 v4.15.0
github.com/labstack/echo/v5 v5.0.1
github.com/matoous/go-nanoid/v2 v2.1.0
github.com/samber/lo v1.52.0
github.com/spf13/cast v1.10.0
github.com/stretchr/testify v1.11.1
go.uber.org/zap v1.27.1
golang.org/x/crypto v0.47.0
golang.org/x/time v0.14.0
)
require (
@@ -25,19 +24,13 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/labstack/echo/v5 v5.0.1 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/redis/go-redis/v9 v9.17.3 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

View File

@@ -34,18 +34,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo-contrib v0.50.0 h1:MLTQdqME3BEBczV2thYz9yPT5sBhzkoUEpwAOY9llds=
github.com/labstack/echo-contrib v0.50.0/go.mod h1:oftqJL4enNg9ao1VLpVZmisVE5/8uwHtIYE4zTpqyWU=
github.com/labstack/echo/v4 v4.15.0 h1:hoRTKWcnR5STXZFe9BmYun9AMTNeSbjHi2vtDuADJ24=
github.com/labstack/echo/v4 v4.15.0/go.mod h1:xmw1clThob0BSVRX1CRQkGQ/vjwcpOMjQZSZa9fKA/c=
github.com/labstack/echo/v5 v5.0.1 h1:60L7x1KMWRIJuaFqvnEHH322g+YnsMWq5Rzaeo6lcP4=
github.com/labstack/echo/v5 v5.0.1/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE=
github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1DQx4=
@@ -60,10 +52,6 @@ github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -74,7 +62,6 @@ golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=

View File

@@ -6,11 +6,11 @@ import (
"pkg/models"
u "pkg/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
"github.com/samber/lo"
)
func GetAbout(c echo.Context) error {
func GetAbout(c *echo.Context) error {
maxStorageSize, err := utils.GetFileSize(u.GetEnv("upload.maximum"))
if err != nil {
return utils.HTTPErrorHandler(c, err)

View File

@@ -5,11 +5,11 @@ import (
u "pkg/utils"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
"github.com/spf13/cast"
)
func GetConfig(c echo.Context) error {
func GetConfig(c *echo.Context) error {
return utils.HTTPSuccessHandler(c, map[string]any{
"site_title": u.GetEnvMapString("site.title"),
"site_desc": u.GetEnvMapString("site.desc"),

View File

@@ -2,7 +2,6 @@ package controllers
import (
"backend/internal/utils"
"backend/middleware"
"errors"
"fmt"
"pkg/models"
@@ -10,7 +9,7 @@ import (
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
"github.com/spf13/cast"
)
@@ -19,9 +18,8 @@ type DownloadShareClaims struct {
jwt.RegisteredClaims
}
func DownloadShare(c echo.Context) error {
cc := c.(*middleware.CustomContext)
token := cc.FormValue("token")
func DownloadShare(c *echo.Context) error {
token := c.FormValue("token")
if token == "" {
return utils.HTTPErrorHandler(c, errors.New("缺少token"))
}
@@ -43,7 +41,7 @@ func DownloadShare(c echo.Context) error {
if err != nil {
return err
}
return cc.Attachment(fmt.Sprintf("%s/%s", uploadPath, utils.GetFileId(fileInfo.FileHash, fileInfo.FileSize)), shareInfo.FileName)
return c.Attachment(fmt.Sprintf("%s/%s", uploadPath, utils.GetFileId(fileInfo.FileHash, fileInfo.FileSize)), shareInfo.FileName)
}
return utils.HTTPSuccessHandler(c, map[string]any{
"data": shareInfo.Data,
@@ -55,11 +53,9 @@ type VaildateShareProps struct {
Password string `json:"password"`
}
func VaildateShare(c echo.Context) error {
cc := c.(*middleware.CustomContext)
func VaildateShare(c *echo.Context) error {
r := new(VaildateShareProps)
if err := cc.Bind(r); err != nil {
if err := c.Bind(r); err != nil {
return utils.HTTPErrorHandler(c, err)
}

View File

@@ -13,10 +13,10 @@ import (
"time"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
func CreateUploadTask(c echo.Context) error {
func CreateUploadTask(c *echo.Context) error {
// cc := c.(*middleware.CustomContext)
r := new(models.FileInfo)
if err := c.Bind(r); err != nil {
@@ -124,7 +124,7 @@ type UploadFileSliceProps struct {
FileSlice *multipart.FileHeader `form:"file"`
}
func UploadFileSlice(c echo.Context) error {
func UploadFileSlice(c *echo.Context) error {
r := new(UploadFileSliceProps)
if err := c.Bind(r); err != nil {
return utils.HTTPErrorHandler(c, err)
@@ -179,7 +179,7 @@ type FinishUploadTaskProps struct {
FileId string `json:"id"`
}
func FinishUploadTask(c echo.Context) error {
func FinishUploadTask(c *echo.Context) error {
r := new(FinishUploadTaskProps)
if err := c.Bind(r); err != nil {
return utils.HTTPErrorHandler(c, err)

View File

@@ -2,7 +2,6 @@ package controllers
import (
"backend/internal/utils"
"backend/middleware"
"encoding/json"
"errors"
"pkg/models"
@@ -11,7 +10,7 @@ import (
"time"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/spf13/cast"
)
@@ -34,11 +33,11 @@ type ShareConfig struct {
HasPickupCode bool `json:"has_pickup_code"`
}
func CreateShareInfo(c echo.Context) error {
cc := c.(*middleware.CustomContext)
func CreateShareInfo(c *echo.Context) error {
owner, _ := echo.ContextGet[string](c, "auth")
r := new(CreateShareProps)
if err := cc.Bind(r); err != nil {
if err := c.Bind(r); err != nil {
return utils.HTTPErrorHandler(c, err)
}
if r.Config.ExpireAt < 1 {
@@ -79,7 +78,7 @@ func CreateShareInfo(c echo.Context) error {
Data: r.Data,
Type: r.Type,
CreatedAt: time.Now().Unix(),
Owner: cc.Auth.(string),
Owner: owner,
ViewNum: r.Config.ViewNum,
Password: password,
// NotifyEmail: r.Config.NotifyEmail,
@@ -149,9 +148,8 @@ type GetShareProps struct {
ShareId string `param:"id"`
}
func GetShareInfo(c echo.Context) error {
cc := c.(*middleware.CustomContext)
shareId := cc.Param("id")
func GetShareInfo(c *echo.Context) error {
shareId := c.Param("id")
if shareId == "" {
return utils.HTTPErrorHandler(c, errors.New("缺少分享ID"))
}
@@ -199,9 +197,8 @@ func GetShareInfo(c echo.Context) error {
})
}
func GetShareByPickupCode(c echo.Context) error {
cc := c.(*middleware.CustomContext)
pickupCode := cc.Param("code")
func GetShareByPickupCode(c *echo.Context) error {
pickupCode := c.Param("code")
if pickupCode == "" {
return utils.HTTPErrorHandler(c, errors.New("缺少提取码"))
}

View File

@@ -6,7 +6,7 @@ import (
"pkg/models"
u "pkg/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
const (
@@ -27,7 +27,7 @@ type QueueChartData struct {
Failed int `json:"failed"`
}
func GetStat(c echo.Context) error {
func GetStat(c *echo.Context) error {
statInfoMap, err := models.GetRedisStatAll()
if err != nil {
return utils.HTTPErrorHandler(c, err)

View File

@@ -3,23 +3,20 @@ package controllers
import (
"backend/internal/controllers/task"
"backend/internal/utils"
"backend/middleware"
"errors"
"pkg/models"
u "pkg/utils"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
var handleTaskMap = map[string]func(c *middleware.CustomContext) ([]byte, error){
var handleTaskMap = map[string]func(c *echo.Context) ([]byte, error){
"image:compress": task.HandleImageCompress,
}
func CreateTask(c echo.Context) error {
cc := c.(*middleware.CustomContext)
taskType := cc.Param("type")
func CreateTask(c *echo.Context) error {
taskType := c.Param("type")
if taskType == "" {
return utils.HTTPErrorHandler(c, errors.New("调用接口参数错误"))
}
@@ -27,7 +24,7 @@ func CreateTask(c echo.Context) error {
if !ok {
return utils.HTTPErrorHandler(c, errors.New("任务不存在"))
}
json, err := handleTask(cc)
json, err := handleTask(c)
if err != nil {
return utils.HTTPErrorHandler(c, err)
}
@@ -43,9 +40,8 @@ func CreateTask(c echo.Context) error {
})
}
func GetTask(c echo.Context) error {
cc := c.(*middleware.CustomContext)
taskId := cc.Param("id")
func GetTask(c *echo.Context) error {
taskId := c.Param("id")
if taskId == "" {
return utils.HTTPErrorHandler(c, errors.New("调用接口参数错误"))
}

View File

@@ -1,16 +1,17 @@
package task
import (
"backend/middleware"
"encoding/json"
"errors"
"github.com/labstack/echo/v5"
)
type GenCompressImageRequest struct {
FileId string `json:"file_id"`
}
func HandleImageCompress(c *middleware.CustomContext) ([]byte, error) {
func HandleImageCompress(c *echo.Context) ([]byte, error) {
r := new(GenCompressImageRequest)
if err := c.Bind(r); err != nil {

View File

@@ -3,7 +3,7 @@ package utils
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
type Option interface {
@@ -36,7 +36,7 @@ func (o WithData) applyTo(props *HTTPBaseResponse) {
props.data = o
}
func HTTPBaseHandler(c echo.Context, options ...Option) error {
func HTTPBaseHandler(c *echo.Context, options ...Option) error {
props := HTTPBaseResponse{code: http.StatusOK, message: "success", data: map[string]any{}}
for _, option := range options {
option.applyTo(&props)
@@ -49,10 +49,10 @@ func HTTPBaseHandler(c echo.Context, options ...Option) error {
})
}
func HTTPSuccessHandler(c echo.Context, data map[string]any, options ...HTTPBaseResponseProps) error {
func HTTPSuccessHandler(c *echo.Context, data map[string]any, options ...HTTPBaseResponseProps) error {
return HTTPBaseHandler(c, WithData(data))
}
func HTTPErrorHandler(c echo.Context, err error, options ...HTTPBaseResponseProps) error {
func HTTPErrorHandler(c *echo.Context, err error, options ...HTTPBaseResponseProps) error {
return HTTPBaseHandler(c, WithMessage(err.Error()), WithCode(http.StatusBadRequest))
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"pkg/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
"go.uber.org/zap"
)
@@ -27,5 +27,7 @@ func main() {
for _, route := range routes {
e.Match(route.Method, route.Path, route.Handler)
}
e.Logger.Fatal(e.Start(fmt.Sprintf(":%s", utils.GetEnvWithDefault("api.port", "5001"))))
if err := e.Start(fmt.Sprintf(":%s", utils.GetEnvWithDefault("api.port", "5001"))); err != nil {
logger.Fatal("server failed", zap.Error(err))
}
}

View File

@@ -3,11 +3,10 @@ package main
import (
"backend/middleware"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
var middlewares = []func() echo.MiddlewareFunc{
middleware.ContextMiddleware,
middleware.SessionMiddleware,
middleware.AuthMiddleware,
middleware.RateLimiterMiddleware,

View File

@@ -3,14 +3,14 @@ package middleware
import (
"github.com/gorilla/sessions"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
gonanoid "github.com/matoous/go-nanoid/v2"
)
// CustomMiddleware 创建自定义中间件
func AuthMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
return func(c *echo.Context) error {
sess, err := session.Get("session", c)
if err != nil {
return err
@@ -30,11 +30,8 @@ func AuthMiddleware() echo.MiddlewareFunc {
return err
}
}
cc := c.(*CustomContext)
cc.Auth = sess.Values["auth"]
// 将自定义上下文传递给下一个处理器
return next(cc)
c.Set("auth", sess.Values["auth"])
return next(c)
}
}
}

View File

@@ -1,28 +0,0 @@
package middleware
import (
"github.com/labstack/echo/v4"
)
// CustomContext 扩展 echo.Context 以添加自定义功能
type CustomContext struct {
echo.Context
Auth interface{}
}
// NewCustomContext 创建自定义上下文的构造函数
func NewCustomContext(c echo.Context) *CustomContext {
return &CustomContext{
Context: c,
}
}
// ContextMiddleware 中间件用于将标准 echo.Context 转换为 CustomContext
func ContextMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cc := NewCustomContext(c)
return next(cc)
}
}
}

View File

@@ -1,8 +1,8 @@
package middleware
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
"go.uber.org/zap"
)
@@ -10,7 +10,7 @@ func LoggerMiddleware() echo.MiddlewareFunc {
return middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogURI: true,
LogStatus: true,
LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error {
zap.L().Info("request",
zap.String("url", v.URI),
zap.Int("status", v.Status),

View File

@@ -5,9 +5,8 @@ import (
"slices"
"time"
"github.com/labstack/echo/v4"
echo_middleware "github.com/labstack/echo/v4/middleware"
"golang.org/x/time/rate"
"github.com/labstack/echo/v5"
echo_middleware "github.com/labstack/echo/v5/middleware"
)
type RateSkiper struct {
@@ -23,22 +22,22 @@ var RateSkipList = []RateSkiper{
func RateLimiterMiddleware() echo.MiddlewareFunc {
config := echo_middleware.RateLimiterConfig{
Skipper: func(e echo.Context) bool {
Skipper: func(e *echo.Context) bool {
path := e.Path()
r := e.Request()
return slices.Contains(RateSkipList, RateSkiper{Path: path, Method: r.Method})
},
Store: echo_middleware.NewRateLimiterMemoryStoreWithConfig(
echo_middleware.RateLimiterMemoryStoreConfig{Rate: rate.Limit(10), Burst: 30, ExpiresIn: 3 * time.Minute},
echo_middleware.RateLimiterMemoryStoreConfig{Rate: 10, Burst: 30, ExpiresIn: 3 * time.Minute},
),
IdentifierExtractor: func(ctx echo.Context) (string, error) {
IdentifierExtractor: func(ctx *echo.Context) (string, error) {
id := ctx.RealIP()
return id, nil
},
ErrorHandler: func(context echo.Context, err error) error {
ErrorHandler: func(context *echo.Context, err error) error {
return context.JSON(http.StatusForbidden, nil)
},
DenyHandler: func(context echo.Context, identifier string, err error) error {
DenyHandler: func(context *echo.Context, identifier string, err error) error {
return context.JSON(http.StatusTooManyRequests, nil)
},
}

View File

@@ -3,7 +3,7 @@ package middleware
import (
"github.com/gorilla/sessions"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
func SessionMiddleware() echo.MiddlewareFunc {

View File

@@ -3,13 +3,13 @@ package main
import (
"backend/internal/controllers"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
)
type Route struct {
Method []string
Path string
Handler func(c echo.Context) error
Handler func(c *echo.Context) error
}
var routes = []Route{

View File

@@ -8,7 +8,7 @@ import (
"backend/internal/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v5"
"github.com/stretchr/testify/assert"
)