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