You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
6.3 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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, &parameterMap)
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")
// // }