1、reate limit。
This commit is contained in:
parent
5326172a99
commit
92e97d8fb8
@ -20,6 +20,8 @@ func LoginPage(c *gin.Context) {
|
||||
|
||||
func UserSignInHandler(jwtC *jwt.Jwt) func(c *gin.Context) error {
|
||||
return func(c *gin.Context) error {
|
||||
log, _ := utils.GetLogFromContext(c)
|
||||
|
||||
var user models.UserInfoParams
|
||||
|
||||
if err := c.ShouldBindJSON(&user); err != nil {
|
||||
@ -39,10 +41,10 @@ func UserSignInHandler(jwtC *jwt.Jwt) func(c *gin.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(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.JSON(http.StatusOK, gin.H{"message": "Login successful"})
|
||||
@ -55,6 +57,8 @@ func UserLogOutHandler(c *gin.Context) {
|
||||
log, _ := utils.GetLogFromContext(c)
|
||||
|
||||
c.SetCookie(models.GinAuthorKey, "", -1, "/", "", false, true)
|
||||
|
||||
log.Sugar().Info("Logout successful")
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Logout successful"})
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func FileUploadHandle(c *gin.Context) error {
|
||||
}
|
||||
|
||||
// 限制文件大小(10MB)
|
||||
const maxFileSize = 10 << 20 // 10MB
|
||||
const maxFileSize = 100 << 20 // 100MB
|
||||
if file.Size > maxFileSize {
|
||||
log.Sugar().Errorf("File too large: %d bytes", file.Size)
|
||||
return errors.New("File size exceeds 10MB")
|
||||
@ -64,7 +64,8 @@ func FileUploadHandle(c *gin.Context) error {
|
||||
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)})
|
||||
|
||||
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})
|
||||
|
||||
return nil
|
||||
@ -151,7 +153,7 @@ func FileDownloadHandle(c *gin.Context) error {
|
||||
|
||||
if !fileInfo.IsDir() {
|
||||
// 处理文件下载
|
||||
const maxFileSize = 10 << 20 // 10MB
|
||||
const maxFileSize = 100 << 20 // 100MB
|
||||
if fileInfo.Size() > maxFileSize {
|
||||
log.Sugar().Errorf("File too large: %d bytes", fileInfo.Size())
|
||||
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-Type", "application/octet-stream")
|
||||
c.File(cleanPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -173,7 +176,7 @@ func FileDownloadHandle(c *gin.Context) error {
|
||||
|
||||
zipWriter := zip.NewWriter(tmpFile)
|
||||
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 {
|
||||
if err != nil {
|
||||
@ -199,7 +202,7 @@ func FileDownloadHandle(c *gin.Context) error {
|
||||
header.Method = zip.Deflate
|
||||
totalSize += info.Size()
|
||||
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-Type", "application/zip")
|
||||
c.File(tmpFile.Name())
|
||||
log.Sugar().Debug("Directory %s downloaded as zip", cleanPath)
|
||||
|
||||
log.Sugar().Debugf("Directory %s downloaded as zip", cleanPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -133,15 +133,17 @@ func GinJwtAuthor(jwtC *jwt.Jwt) appHandler {
|
||||
|
||||
func GinRateLimit(rateC settings.RateLimitConfig) appHandler {
|
||||
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)
|
||||
}
|
||||
|
||||
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{
|
||||
Code: http.StatusServiceUnavailable,
|
||||
Msg: "Exceeded rate limit",
|
||||
|
@ -21,7 +21,7 @@ func errWapper(appH appHandler) gin.HandlerFunc {
|
||||
if err != nil {
|
||||
var baseErr *models.BaseError
|
||||
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)
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<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://unpkg.com/xterm@5.3.0/lib/xterm.js"></script>
|
||||
<link href="https://unpkg.com/xterm@5.3.0/css/xterm.css" rel="stylesheet" />
|
||||
@ -28,7 +28,7 @@
|
||||
</head>
|
||||
<body class="bg-gray-100 font-sans">
|
||||
<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>
|
||||
|
||||
<!-- 系统信息 -->
|
||||
@ -63,7 +63,7 @@
|
||||
<input id="target-dir" type="text" class="w-full px-3 py-2 border rounded" placeholder="请输入目标目录">
|
||||
</div>
|
||||
<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">
|
||||
</div>
|
||||
<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 systemInfo = window.lastSystemInfo || {};
|
||||
|
||||
// 如果提示框已显示,不重新定位
|
||||
if (tooltip.style.display === 'block') {
|
||||
return;
|
||||
}
|
||||
|
||||
let content = '';
|
||||
if (tooltipId === 'cpu-tooltip') {
|
||||
content = `
|
||||
@ -167,9 +172,9 @@
|
||||
tooltip.innerHTML = content;
|
||||
tooltip.style.display = 'block';
|
||||
|
||||
// 使用鼠标坐标定位
|
||||
const offsetX = 10; // 水平偏移
|
||||
const offsetY = 10; // 垂直偏移
|
||||
// 使用鼠标坐标定位(仅计算一次)
|
||||
const offsetX = 5; // 水平偏移(更近)
|
||||
const offsetY = 5; // 垂直偏移(更近)
|
||||
let x = event.clientX + window.scrollX + offsetX;
|
||||
let y = event.clientY + window.scrollY + offsetY;
|
||||
|
||||
@ -385,6 +390,15 @@
|
||||
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();
|
||||
updateSystemInfo();
|
||||
|
Loading…
Reference in New Issue
Block a user