1、reate limit。

This commit is contained in:
redhat 2025-05-21 11:26:54 +08:00
parent 5326172a99
commit 92e97d8fb8
5 changed files with 43 additions and 19 deletions

View File

@ -20,6 +20,8 @@ func LoginPage(c *gin.Context) {
func UserSignInHandler(jwtC *jwt.Jwt) func(c *gin.Context) error { func UserSignInHandler(jwtC *jwt.Jwt) func(c *gin.Context) error {
return func(c *gin.Context) error { return func(c *gin.Context) error {
log, _ := utils.GetLogFromContext(c)
var user models.UserInfoParams var user models.UserInfoParams
if err := c.ShouldBindJSON(&user); err != nil { if err := c.ShouldBindJSON(&user); err != nil {
@ -39,10 +41,10 @@ func UserSignInHandler(jwtC *jwt.Jwt) func(c *gin.Context) error {
return err return err
} }
fmt.Println(tokenStr)
token := fmt.Sprintf("%s%s", models.GinAuthorPrefixKey, tokenStr) token := fmt.Sprintf("%s%s", models.GinAuthorPrefixKey, tokenStr)
log.Sugar().Infof("Set token: %s", token)
c.SetCookie(models.GinAuthorKey, token, 24*60*60, "/", "", false, true) c.SetCookie(models.GinAuthorKey, token, 24*60*60, "/", "", false, true)
c.JSON(http.StatusOK, gin.H{"message": "Login successful"}) c.JSON(http.StatusOK, gin.H{"message": "Login successful"})
@ -55,6 +57,8 @@ func UserLogOutHandler(c *gin.Context) {
log, _ := utils.GetLogFromContext(c) log, _ := utils.GetLogFromContext(c)
c.SetCookie(models.GinAuthorKey, "", -1, "/", "", false, true) c.SetCookie(models.GinAuthorKey, "", -1, "/", "", false, true)
log.Sugar().Info("Logout successful") log.Sugar().Info("Logout successful")
c.JSON(http.StatusOK, gin.H{"message": "Logout successful"}) c.JSON(http.StatusOK, gin.H{"message": "Logout successful"})
} }

View File

@ -45,7 +45,7 @@ func FileUploadHandle(c *gin.Context) error {
} }
// 限制文件大小10MB // 限制文件大小10MB
const maxFileSize = 10 << 20 // 10MB const maxFileSize = 100 << 20 // 100MB
if file.Size > maxFileSize { if file.Size > maxFileSize {
log.Sugar().Errorf("File too large: %d bytes", file.Size) log.Sugar().Errorf("File too large: %d bytes", file.Size)
return errors.New("File size exceeds 10MB") return errors.New("File size exceeds 10MB")
@ -64,7 +64,8 @@ func FileUploadHandle(c *gin.Context) error {
return err return err
} }
log.Sugar().Debug("File uploaded successfully to %s", targetPath) log.Sugar().Debugf("File uploaded successfully to %s", targetPath)
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("File uploaded to %s", targetPath)}) c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("File uploaded to %s", targetPath)})
return nil return nil
@ -114,7 +115,8 @@ func FileListHandle(c *gin.Context) error {
}) })
} }
log.Sugar().Debug("Listed files in %s: %d entries", cleanPath, len(files)) log.Sugar().Debugf("Listed files in %s: %d entries", cleanPath, len(files))
c.JSON(http.StatusOK, gin.H{"files": files}) c.JSON(http.StatusOK, gin.H{"files": files})
return nil return nil
@ -151,7 +153,7 @@ func FileDownloadHandle(c *gin.Context) error {
if !fileInfo.IsDir() { if !fileInfo.IsDir() {
// 处理文件下载 // 处理文件下载
const maxFileSize = 10 << 20 // 10MB const maxFileSize = 100 << 20 // 100MB
if fileInfo.Size() > maxFileSize { if fileInfo.Size() > maxFileSize {
log.Sugar().Errorf("File too large: %d bytes", fileInfo.Size()) log.Sugar().Errorf("File too large: %d bytes", fileInfo.Size())
return errors.New("File size exceeds 10MB") return errors.New("File size exceeds 10MB")
@ -160,6 +162,7 @@ func FileDownloadHandle(c *gin.Context) error {
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filepath.Base(cleanPath))) c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filepath.Base(cleanPath)))
c.Header("Content-Type", "application/octet-stream") c.Header("Content-Type", "application/octet-stream")
c.File(cleanPath) c.File(cleanPath)
return nil return nil
} }
@ -173,7 +176,7 @@ func FileDownloadHandle(c *gin.Context) error {
zipWriter := zip.NewWriter(tmpFile) zipWriter := zip.NewWriter(tmpFile)
totalSize := int64(0) totalSize := int64(0)
const maxZipSize = 10 << 20 // 10MB const maxZipSize = 100 << 20 // 100MB
err = filepath.Walk(cleanPath, func(path string, info os.FileInfo, err error) error { err = filepath.Walk(cleanPath, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -199,7 +202,7 @@ func FileDownloadHandle(c *gin.Context) error {
header.Method = zip.Deflate header.Method = zip.Deflate
totalSize += info.Size() totalSize += info.Size()
if totalSize > maxZipSize { if totalSize > maxZipSize {
return fmt.Errorf("directory size exceeds 10MB") return fmt.Errorf("directory size exceeds 100MB")
} }
} }
@ -238,7 +241,8 @@ func FileDownloadHandle(c *gin.Context) error {
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filepath.Base(cleanPath)+".zip")) c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filepath.Base(cleanPath)+".zip"))
c.Header("Content-Type", "application/zip") c.Header("Content-Type", "application/zip")
c.File(tmpFile.Name()) c.File(tmpFile.Name())
log.Sugar().Debug("Directory %s downloaded as zip", cleanPath)
log.Sugar().Debugf("Directory %s downloaded as zip", cleanPath)
return nil return nil
} }

View File

@ -133,15 +133,17 @@ func GinJwtAuthor(jwtC *jwt.Jwt) appHandler {
func GinRateLimit(rateC settings.RateLimitConfig) appHandler { func GinRateLimit(rateC settings.RateLimitConfig) appHandler {
lrate, err := rate.New(rate.WithCapacity(rateC.Capacity), lrate, err := rate.New(rate.WithCapacity(rateC.Capacity),
rate.WithFillInterval(time.Duration(rateC.FillInterval)), rate.WithFillInterval(time.Duration(rateC.FillInterval)*time.Millisecond),
) )
if err != nil { if err != nil || lrate.Bucket == nil {
panic(err) panic(err)
} }
return func(c *gin.Context) error { return func(c *gin.Context) error {
if lrate.Available() ==0 { if !lrate.WaitMaxDuration(1, time.Duration(rateC.MaxWait)*time.Second) {
time.Sleep(time.Duration(rateC.MaxWait) * time.Second)
c.Abort()
return &models.BaseError{ return &models.BaseError{
Code: http.StatusServiceUnavailable, Code: http.StatusServiceUnavailable,
Msg: "Exceeded rate limit", Msg: "Exceeded rate limit",

View File

@ -21,7 +21,7 @@ func errWapper(appH appHandler) gin.HandlerFunc {
if err != nil { if err != nil {
var baseErr *models.BaseError var baseErr *models.BaseError
if errors.As(err, &baseErr) { if errors.As(err, &baseErr) {
log.Error("Base error", zap.Any("res", baseErr)) log.Error("Base error", zap.Any("baseErr", baseErr))
c.JSON(http.StatusBadRequest, baseErr) c.JSON(http.StatusBadRequest, baseErr)

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux 系统运维监控</title> <title>Avcnet 系统运维监控</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/xterm@5.3.0/lib/xterm.js"></script> <script src="https://unpkg.com/xterm@5.3.0/lib/xterm.js"></script>
<link href="https://unpkg.com/xterm@5.3.0/css/xterm.css" rel="stylesheet" /> <link href="https://unpkg.com/xterm@5.3.0/css/xterm.css" rel="stylesheet" />
@ -28,7 +28,7 @@
</head> </head>
<body class="bg-gray-100 font-sans"> <body class="bg-gray-100 font-sans">
<div class="container mx-auto p-4"> <div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">Linux 系统运维监控</h1> <h1 class="text-2xl font-bold mb-4">Avcnet 系统运维监控</h1>
<button id="logout" class="bg-red-500 text-white px-4 py-2 rounded mb-4">登出</button> <button id="logout" class="bg-red-500 text-white px-4 py-2 rounded mb-4">登出</button>
<!-- 系统信息 --> <!-- 系统信息 -->
@ -63,7 +63,7 @@
<input id="target-dir" type="text" class="w-full px-3 py-2 border rounded" placeholder="请输入目标目录"> <input id="target-dir" type="text" class="w-full px-3 py-2 border rounded" placeholder="请输入目标目录">
</div> </div>
<div class="mb-4"> <div class="mb-4">
<label class="block text-gray-700 mb-2" for="file">选择文件最大10MB</label> <label class="block text-gray-700 mb-2" for="file">选择文件最大100MB</label>
<input id="file" type="file" class="w-full px-3 py-2 border rounded"> <input id="file" type="file" class="w-full px-3 py-2 border rounded">
</div> </div>
<button id="upload" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">上传</button> <button id="upload" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">上传</button>
@ -137,6 +137,11 @@
const tooltip = document.getElementById(tooltipId); const tooltip = document.getElementById(tooltipId);
const systemInfo = window.lastSystemInfo || {}; const systemInfo = window.lastSystemInfo || {};
// 如果提示框已显示,不重新定位
if (tooltip.style.display === 'block') {
return;
}
let content = ''; let content = '';
if (tooltipId === 'cpu-tooltip') { if (tooltipId === 'cpu-tooltip') {
content = ` content = `
@ -167,9 +172,9 @@
tooltip.innerHTML = content; tooltip.innerHTML = content;
tooltip.style.display = 'block'; tooltip.style.display = 'block';
// 使用鼠标坐标定位 // 使用鼠标坐标定位(仅计算一次)
const offsetX = 10; // 水平偏移 const offsetX = 5; // 水平偏移(更近)
const offsetY = 10; // 垂直偏移 const offsetY = 5; // 垂直偏移(更近)
let x = event.clientX + window.scrollX + offsetX; let x = event.clientX + window.scrollX + offsetX;
let y = event.clientY + window.scrollY + offsetY; let y = event.clientY + window.scrollY + offsetY;
@ -385,6 +390,15 @@
listFiles(parentPath); listFiles(parentPath);
}); });
// 设置默认地址
window.onload = function() {
const defaultPath = '/tmp/uploads';
const defaultListPath = '/app/avcnet';
document.getElementById('target-dir').value = defaultPath; // 上传地址默认值
document.getElementById('browse-dir').value = defaultListPath; // 浏览地址默认值
listFiles(defaultListPath); // 自动加载默认路径文件列表
};
// 初始检查登录状态并定期更新系统信息 // 初始检查登录状态并定期更新系统信息
checkLoginStatus(); checkLoginStatus();
updateSystemInfo(); updateSystemInfo();