Files
bl/modules/base/middleware/middleware.go
昔念 8bc3fd3cb7
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(dict): 添加字典数据压缩加密功能

- 在字典数据接口中集成压缩和加密机制
- 实现Gzip压缩、XOR加密和Base64编码流程
- 新增CompressAndEncrypt和DecryptAndDecompress工具函数
- 在middleware中启用压缩中间件支持
```
2026-02-28 00:21:33 +08:00

212 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"blazing/common/rpc"
"blazing/cool"
"blazing/modules/base/config"
"blazing/modules/config/service"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"net/http/httputil"
"net/url"
"path/filepath"
"strconv"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
"github.com/lxzan/gws"
)
const UpStream = "http://43.248.3.21:45632/"
func MiddlewareCORS(r *ghttp.Request) {
r.Response.CORSDefault()
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"*", "localhost", "tauri.localhost"}
if !r.Response.CORSAllowedOrigin(corsOptions) {
r.Response.WriteStatus(http.StatusForbidden)
return
}
r.Response.CORS(corsOptions)
if r.Response.Request.Method == "OPTIONS" {
r.Response.WriteStatus(http.StatusOK)
return
}
// fmt.Println(r.Response.Header())
//g.Dump(r.Response.Server.SetConfig(gtt))
//r.Response.Header().Del("Server") // 删除Server头
// r.Response.Header().Set("Server", "blazing")
r.Middleware.Next()
}
func StartServerProxy() {
s := g.Server()
// Parse the upstream URL
u, _ := url.Parse(UpStream)
// Create a new reverse proxy instance
proxy := httputil.NewSingleHostReverseProxy(u)
// Configure error handling for proxy failures
proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) {
writer.WriteHeader(http.StatusBadGateway)
}
s.BindHandler("/bbs/api/fof/upload", func(r *ghttp.Request) {
// 1. 调用上传方法仍返回单个URL字符串不改动Upload方法
urlStr, err := cool.File().Upload(r.Context())
// 2. 错误处理返回标准化错误JSON
if err != nil {
r.Response.Header().Set("Content-Type", "application/json; charset=utf-8")
r.Response.WriteHeader(http.StatusBadRequest)
json.NewEncoder(r.Response.Writer).Encode(map[string]interface{}{
"code": 1,
"msg": err.Error(),
"data": nil,
})
return
}
// 3. 基于返回的URL构造完整的JSON结构体和示例完全一致
// 解析URL中的文件名和路径从urlStr中提取
baseName := filepath.Base(urlStr) // 提取文件名如13e8d062-xxx.jpg
dir := gtime.Now().Format("Y-m-d") // 日期目录2026-02-07
path := fmt.Sprintf("%s/%s", dir, baseName) // 拼接path字段
rand.Seed(time.Now().UnixNano())
randomID := strconv.Itoa(rand.Intn(1000)) // 模拟ID如54
uuidStr := uuid.New().String() // 生成UUID
humanSize := "743kB" // 模拟易读大小(可根据实际需求优化)
fileSize := int64(760783) // 模拟文件大小(字节)
// 构造和示例完全一致的响应结构体
fullResponse := map[string]interface{}{
"data": []map[string]interface{}{
{
"type": "files",
"id": randomID,
"attributes": map[string]interface{}{
"baseName": baseName,
"path": path,
"url": urlStr, // 用Upload返回的URL
"type": "image/jpeg", // 模拟MIME类型
"size": fileSize,
"humanSize": humanSize,
"createdAt": nil, // null
"uuid": uuidStr,
"tag": "just-url",
"hidden": false,
"bbcode": `[img]` + urlStr + `[/img]`, // 和URL一致
"shared": false,
"canViewInfo": false,
"canHide": true,
"canDelete": true,
},
},
},
}
// 4. 输出完整JSON响应
r.Response.Header().Set("Content-Type", "application/json; charset=utf-8")
if err := json.NewEncoder(r.Response.Writer).Encode(fullResponse); err != nil {
// 兜底错误
fmt.Fprintf(r.Response.Writer, `{"code":1,"msg":"响应生成失败:%s","data":null}`, err.Error())
}
})
// Handle all requests with path prefix "/proxy/*"
s.BindHandler("/bbs/*url", func(r *ghttp.Request) {
var (
//originalPath = r.Request.URL.Path
proxyToPath = "/" + r.Get("url").String()
)
// Rewrite the request path
r.Request.URL.Path = proxyToPath
// Log the proxy operation
//g.Log().Infof(r.Context(), `proxy:"%s" -> backend:"%s"`, originalPath, proxyToPath)
// Ensure request body can be read multiple times if needed
r.MakeBodyRepeatableRead(false)
// Forward the request to the backend server
proxy.ServeHTTP(r.Response.Writer, r.Request)
})
}
func init() {
if config.Config.Middleware.Authority.Enable {
g.Server().BindMiddleware("/admin/*/open/*", BaseAuthorityMiddlewareOpen)
g.Server().BindMiddleware("/rpc/*", BaseAuthorityMiddlewareOpen)
g.Server().BindMiddleware("/admin/*/comm/*", BaseAuthorityMiddlewareComm)
g.Server().BindMiddleware("/admin/*", BaseAuthorityMiddleware)
// g.Server().BindMiddleware("/*", AutoI18n)
g.Server().BindMiddleware("/*", MiddlewareCORS)
}
if config.Config.Middleware.Log.Enable {
g.Server().BindMiddleware("/admin/*", BaseLog)
}
StartServerProxy()
tt := rpc.CServer()
g.Server().BindHandler("/rpc/*", func(r *ghttp.Request) {
tt.ServeHTTP(r.Response.Writer, r.Request)
})
g.Server().Use(CompressMiddleware)
g.Server().BindHandler("/server/*", func(r *ghttp.Request) {
servert := new(ServerHandler)
id := gconv.Uint16(r.URL.Query().Get("id"))
servert.isinstall = gconv.Uint32(r.URL.Query().Get("isinstall"))
servert.ServerList = service.NewServerService().StartUPdate(id, int(servert.isinstall))
upgrader := gws.NewUpgrader(servert, &gws.ServerOption{
Authorize: func(_ *http.Request, _ gws.SessionStorage) bool {
tokenString := r.URL.Query().Get("Authorization")
token, err := jwt.ParseWithClaims(tokenString, &cool.Claims{}, func(_ *jwt.Token) (interface{}, error) {
return []byte(config.Config.Jwt.Secret), nil
})
if err != nil {
return false
}
if !token.Valid {
return false
}
admin := token.Claims.(*cool.Claims)
if admin.UserId != 10001 {
return false
}
// var name = r.URL.Query().Get("name")
// if name == "" {
// return false
// }
// t, _ := service.NewBaseSysUserService().Person(admin.UserID)
//Loger.Debug(context.TODO(), t.Mimi)
// session.Store("name", t.Mimi)
//session.Store("key", r.Header.Get("Sec-WebSocket-Key"))
return true
},
})
socket, err := upgrader.Upgrade(r.Response.Writer, r.Request)
if err != nil {
fmt.Println(err)
return
}
// ants.Submit(func() {
// socket.ReadLoop()
// })
// ants.Submit(func() { socket.ReadLoop() })
go socket.ReadLoop()
})
}