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("/seer/game/cdk/*", BaseAuthorityMiddlewareComm) g.Server().BindMiddleware("/seer/game/cdk/*", BaseAuthorityMiddleware) 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() }) }