diff --git a/backend/app/api/v1/runtime.go b/backend/app/api/v1/runtime.go index a7d7a2941..3d6112cab 100644 --- a/backend/app/api/v1/runtime.go +++ b/backend/app/api/v1/runtime.go @@ -203,3 +203,19 @@ func (b *BaseApi) OperateNodeModules(c *gin.Context) { } helper.SuccessWithOutData(c) } + +// @Tags Runtime +// @Summary Sync runtime status +// @Description 同步运行环境状态 +// @Accept json +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/sync [post] +func (b *BaseApi) SyncStatus(c *gin.Context) { + err := runtimeService.SyncRuntimeStatus() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} diff --git a/backend/app/service/runtime.go b/backend/app/service/runtime.go index 7ea2240ed..8b3fe18ce 100644 --- a/backend/app/service/runtime.go +++ b/backend/app/service/runtime.go @@ -42,6 +42,7 @@ type IRuntimeService interface { GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error) OperateNodeModules(req request.NodeModuleOperateReq) error SyncForRestart() error + SyncRuntimeStatus() error } func NewRuntimeService() IRuntimeService { @@ -586,3 +587,16 @@ func (r *RuntimeService) SyncForRestart() error { } return nil } + +func (r *RuntimeService) SyncRuntimeStatus() error { + runtimes, err := runtimeRepo.List() + if err != nil { + return err + } + for _, runtime := range runtimes { + if runtime.Type == constant.RuntimeNode { + _ = SyncRuntimeContainerStatus(&runtime) + } + } + return nil +} diff --git a/backend/app/service/runtime_utils.go b/backend/app/service/runtime_utils.go index f19d50814..5ade63e7c 100644 --- a/backend/app/service/runtime_utils.go +++ b/backend/app/service/runtime_utils.go @@ -181,33 +181,20 @@ func SyncRuntimeContainerStatus(runtime *model.Runtime) error { } container := containers[0] - interval := 10 * time.Second - retries := 60 - for i := 0; i < retries; i++ { - resp, err := cli.InspectContainer(container.ID) - if err != nil { - time.Sleep(interval) - continue + switch container.State { + case "exited": + runtime.Status = constant.RuntimeError + case "running": + runtime.Status = constant.RuntimeRunning + case "paused": + runtime.Status = constant.RuntimeStopped + default: + if runtime.Status != constant.RuntimeBuildIng { + runtime.Status = constant.RuntimeStopped } - if resp.State.Health != nil { - status := strings.ToLower(resp.State.Health.Status) - switch status { - case "starting": - runtime.Status = constant.RuntimeStarting - _ = runtimeRepo.Save(runtime) - case "healthy": - runtime.Status = constant.RuntimeRunning - _ = runtimeRepo.Save(runtime) - return nil - case "unhealthy": - runtime.Status = constant.RuntimeUnhealthy - _ = runtimeRepo.Save(runtime) - return nil - } - } - time.Sleep(interval) } - return nil + + return runtimeRepo.Save(runtime) } func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { diff --git a/backend/router/ro_runtime.go b/backend/router/ro_runtime.go index e77ada55b..539e9901c 100644 --- a/backend/router/ro_runtime.go +++ b/backend/router/ro_runtime.go @@ -20,6 +20,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) { groupRouter.POST("/del", baseApi.DeleteRuntime) groupRouter.POST("/update", baseApi.UpdateRuntime) groupRouter.GET("/:id", baseApi.GetRuntime) + groupRouter.POST("/sync", baseApi.SyncStatus) groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript) groupRouter.POST("/operate", baseApi.OperateRuntime) diff --git a/frontend/src/api/modules/runtime.ts b/frontend/src/api/modules/runtime.ts index 8562b6692..792bf44b8 100644 --- a/frontend/src/api/modules/runtime.ts +++ b/frontend/src/api/modules/runtime.ts @@ -58,3 +58,7 @@ export const UpdatePHPExtensions = (req: Runtime.PHPExtensionsUpdate) => { export const DeletePHPExtensions = (req: Runtime.PHPExtensionsDelete) => { return http.post(`/runtimes/php/extensions/del`, req); }; + +export const SyncRuntime = () => { + return http.post(`/runtimes/sync`, {}); +}; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index a1b3901ac..be6e27340 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -2240,6 +2240,35 @@ const message = { javaFileter: 'Java Dangerous File Filtering', scannerFilter: 'Scanner filter', escapeFilter: 'escape filter', + customRule: 'custom rule', + httpMethod: 'HTTP method filter', + fileExt: 'File upload limit', + fileExtHelper: 'File extensions that are prohibited from uploading', + deny: 'forbidden', + allow: 'only allow', + field: 'match object', + pattern: 'matching condition', + ruleContent: 'match content', + contain: 'include', + equal: 'equal', + regex: 'regular expression', + notEqual: 'Not equal to', + customRuleHelper: 'Perform corresponding actions based on condition matching', + actionAllow: 'Allow', + blockIP: 'Block IP', + code: 'return status code', + noRes: 'Disconnect 444', + badReq: 'Parameter error 400', + forbidden: 'Access Forbidden 403', + serverErr: 'Server error 500', + resHtml: 'Response page', + allowHelper: 'Allowing access will skip subsequent WAF rules, please use with caution', + captcha: 'human-machine verification', + fiveSeconds: '5 seconds verification', + location: 'Region', + redisConfig: 'Redis configuration', + redisHelper: 'Enable Redis to persist temporarily blocked IPs', + wafHelper: 'All websites will lose protection after closing', }, monitor: { name: 'Website Monitor', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index df0b06733..4b0343139 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -2094,6 +2094,35 @@ const message = { javaFileter: 'Java 危險檔案過濾', scannerFilter: '掃描器過濾', escapeFilter: '轉義過濾', + customRule: '自訂規則', + httpMethod: 'HTTP 方法過濾', + fileExt: '檔案上傳限制', + fileExtHelper: '禁止上傳的檔案副檔名', + deny: '禁止', + allow: '只允許', + field: '匹配對象', + pattern: '符合條件', + ruleContent: '符合內容', + contain: '包含', + equal: '等於', + regex: '正規表示式', + notEqual: '不等於', + customRuleHelper: '根據條件匹配執行對應動作', + actionAllow: '允許', + blockIP: '封鎖 IP', + code: '返回狀態碼', + noRes: '斷開連線 444', + badReq: '參數錯誤 400', + forbidden: '禁止訪問 403', + serverErr: '伺服器錯誤 500', + resHtml: '回應頁面', + allowHelper: '允許訪問會跳過後續的 WAF 規則,請謹慎使用', + captcha: '人機驗證', + fiveSeconds: '5 秒驗證', + location: '地區', + redisConfig: 'Redis 配置', + redisHelper: '開啟 Redis 可以將暫時拉黑的 IP 持久化', + wafHelper: '關閉之後所有網站將失去防護', }, monitor: { name: '網站監控', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index c6e5f7c40..f1dac1fd0 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -2011,6 +2011,7 @@ const message = { }, xpack: { name: '专业版', + menu: '高级功能', waf: { name: 'WAF', blackWhite: '黑白名单', @@ -2065,7 +2066,7 @@ const message = { cookieHelper: '禁止请求中携带恶意 Cookie', headerDefense: 'Header 规则', headerHelper: '禁止请求中携带恶意 Header', - httpRule: 'HTTP 请求方法规则', + httpRule: 'HTTP 规则', httpHelper: '限制网站的请求方法类型', geoRule: '地区访问限制', geoHelper: '限制某些地区访问你的网站', @@ -2094,6 +2095,35 @@ const message = { javaFileter: 'Java 危险文件过滤', scannerFilter: '扫描器过滤', escapeFilter: '转义过滤', + customRule: '自定义规则', + httpMethod: 'HTTP 方法过滤', + fileExt: '文件上传限制', + fileExtHelper: '禁止上传的文件扩展名', + deny: '禁止', + allow: '仅允许', + field: '匹配对象', + pattern: '匹配条件', + ruleContent: '匹配内容', + contain: '包含', + equal: '等于', + regex: '正则表达式', + notEqual: '不等于', + customRuleHelper: '根据条件匹配执行相应动作', + actionAllow: '允许', + blockIP: '封禁 IP', + code: '返回状态码', + noRes: '断开连接 444', + badReq: '参数错误 400', + forbidden: '禁止访问 403', + serverErr: '服务器错误 500', + resHtml: '响应页面', + allowHelper: '允许访问会跳过后续的 WAF 规则,请谨慎使用', + captcha: '人机验证', + fiveSeconds: '5 秒验证', + location: '地区', + redisConfig: 'Redis 配置', + redisHelper: '开启 Redis 可以将临时拉黑的 IP 持久化', + wafHelper: '关闭之后所有网站将失去防护', }, monitor: { name: '网站监控', diff --git a/frontend/src/views/website/runtime/node/index.vue b/frontend/src/views/website/runtime/node/index.vue index b2ea0fc40..59e548b19 100644 --- a/frontend/src/views/website/runtime/node/index.vue +++ b/frontend/src/views/website/runtime/node/index.vue @@ -90,7 +90,7 @@