package routers import ( "flx/controller" "flx/middleware" "net/http" "strconv" "strings" "time" "flx/controller/congresscontrol" "github.com/gin-gonic/gin" "github.com/juju/ratelimit" log "github.com/sirupsen/logrus" ) func InitRouter(engine *gin.Engine) *gin.Engine { defer func() { if r := recover(); r != nil { log.Error("InitRouter:", r) } }() //注意 Recover 要尽量放在第一个被加载 //如不是的话,在recover前的中间件或路由,将不能被拦截到 //程序的原理是: //1.请求进来,执行recover //2.程序异常,抛出panic //3.panic被 recover捕获,返回异常信息,并Abort,终止这次请求 engine.Use(middleware.Cors()) //http://localhost:9998/static/static/master.644a85b4.jpg //http://localhost:9998/webs/upload/111.png //http://localhost:9998/webs/screen/web/meetingview.html engine.StaticFS("/webs", http.Dir("public")) engine.Use(middleware.Recover) // engine.Use(middleware.JwtVerify) //权限验证中间件 engine.GET("/screen/web/meetingview.html", controller.WsIndexs) resourceRouter(engine) group := engine.Group("/vhwcapi/v1") { groupRouter(group) // 服务分组接口 customizeRouter(group) // 自定义服务接口 websocketRouter(group) } // 解决刷新404问题 engine.NoRoute(controller.RedirectIndex) return engine } // resourceRouter 静态资源配置 func resourceRouter(engine *gin.Engine) { defer func() { if r := recover(); r != nil { log.Error("resourceRouter:", r) } }() group := engine.Group("/hucb/hygl") //首页根路径上下文http://localhost:9998/welcome { group.GET("", controller.Index) } } func timedHandler(duration time.Duration) func(c *gin.Context) { defer func() { if r := recover(); r != nil { log.Error("timedHandler:", r) } }() return func(c *gin.Context) { // get the underlying request context ctx := c.Request.Context() // create the response data type to use as a channel type type responseData struct { status int body map[string]interface{} } // create a done channel to tell the request it's done doneChan := make(chan responseData) // here you put the actual work needed for the request // and then send the doneChan with the status and body // to finish the request by writing the response go func() { time.Sleep(duration) doneChan <- responseData{ status: 200, body: gin.H{"hello": "world"}, } }() // non-blocking select on two channels see if the request // times out or finishes select { // if the context is done it timed out or was cancelled // so don't return anything case <-ctx.Done(): return // if the request finished then finish the request by // writing the response case res := <-doneChan: c.JSON(res.status, res.body) } } } func groupRouter(engine *gin.RouterGroup) { defer func() { if r := recover(); r != nil { log.Error("groupRouter:", r) } }() group := engine.Group("/web/api/service/") group.POST("congresscontrol/tacitScreen", congresscontrol.TacitScreenForWeb) } // customizeRouter 自定义服务相关 func customizeRouter(engine *gin.RouterGroup) { defer func() { if r := recover(); r != nil { log.Error("customizeRouter:", r) } }() /* customize := controller.NewCustomizeApi() group := engine.Group("customize") { group.POST("list", customize.ServerList) group.GET("running", customize.Run) group.POST("add", customize.Create) group.GET("delete", customize.Delete) } */ } func websocketRouter(engine *gin.RouterGroup) { defer func() { if r := recover(); r != nil { log.Error("websocketRouter:", r) } }() group := engine.Group("/websocket/") { group.GET("ccuwebsocket", controller.WsPage) //升级http 协议到 WebSocket } } func rateLimitMiddleware(bucket *ratelimit.Bucket) gin.HandlerFunc { defer func() { if r := recover(); r != nil { log.Error("rateLimitMiddleware:", r) } }() return func(c *gin.Context) { // 处理请求的前置逻辑 c.Next() var contentLength int64 = 0 parameterMap := make(map[string]interface{}) controller.DecodeJsonPayload(c, ¶meterMap) if parameterMap["Range"] != nil { rangeParts := strings.Split(strings.TrimPrefix(parameterMap["Range"].(string), "bytes="), "-") start, _ := strconv.ParseInt(rangeParts[0], 10, 64) var end int64 = 0 if len(rangeParts) > 1 && rangeParts[1] != "" { end, _ = strconv.ParseInt(rangeParts[1], 10, 64) } contentLength = end - start if contentLength < 0 { contentLength = 0 } } // 动态消耗令牌 if bucket.TakeAvailable(contentLength) == 0 { c.AbortWithStatus(http.StatusTooManyRequests) return } } } // // package main // // import ( // // "net/http" // // "time" // // "github.com/gin-gonic/gin" // // ) // // 创建一个流量限制器中间件,限制每秒最大传输量为200MB // func bandwidthLimiterMiddleware(limit int64) gin.HandlerFunc { // return func(c *gin.Context) { // // 创建一个带有流量统计功能的 ResponseWriter // bw := &bandwidthWriter{ // ResponseWriter: c.Writer, // limit: limit, // startTime: time.Now(), // } // c.Writer = bw // // 执行请求 // c.Next() // // 检查流量限制 // if bw.exceededLimit() { // c.AbortWithStatus(http.StatusTooManyRequests) // 超过流量限制,返回429状态码 // } // } // } // // 自定义 ResponseWriter,用于统计流量 // type bandwidthWriter struct { // gin.ResponseWriter // bytesWritten int64 // limit int64 // startTime time.Time // } // func (bw *bandwidthWriter) Write(data []byte) (int, error) { // // 统计写入的数据量 // n, err := bw.ResponseWriter.Write(data) // bw.bytesWritten += int64(n) // return n, err // } // // 判断是否超过流量限制 // func (bw *bandwidthWriter) exceededLimit() bool { // elapsed := time.Since(bw.startTime).Seconds() // if int64(elapsed) > 0 { // currentRate := bw.bytesWritten / int64(elapsed) // 计算当前的传输速率 // return currentRate > bw.limit // } // return false // } // // func main() { // // r := gin.Default() // // // 将流量限制中间件应用到 /download 路由 // // r.GET("/download", bandwidthLimiterMiddleware(200*1024*1024), func(c *gin.Context) { // // // 模拟大文件下载 // // c.File("largefile.zip") // // }) // // r.Run(":8080") // // }