fix: Redis 查询格式修复

- rows nil → 空数组: rowsOrDefault() 确保 HGETALL/LRANGE 空集合返回 [] 而非 null
- 扩展只读白名单: PING/CONFIG/CLIENT/SLOWLOG/CLUSTER/MEMORY/OBJECT/DEBUG 等
- 前端 sortedResult: Array.isArray() 检查防止 raw_text 模式报 not iterable
This commit is contained in:
logan committed 2026-05-31 00:34:38 +08:00
1 parent e8fd5f6b63
commit e9a700b9d9
2 files changed
+16 -2

No files matched your search

+15 -2
View File
@@ -705,6 +705,14 @@ func parseCommandParts(input string) []string {
return parts
}
// rowsOrDefault ensures rows is never nil (JSON null), always an empty slice
func rowsOrDefault(rows []interface{}) []interface{} {
if rows == nil {
return []interface{}{}
}
return rows
}
func executeRedisQuery(instance *model.Instance, dbSelect string, command string, limit int, offset int) (gin.H, error) {
// Parse Redis DB number from dbSelect (e.g. "0", "1")
redisDB := 0
@@ -731,12 +739,17 @@ func executeRedisQuery(instance *model.Instance, dbSelect string, command string
readOnly := map[string]bool{
"GET": true, "MGET": true, "HGET": true, "HGETALL": true,
"LRANGE": true, "SMEMBERS": true, "ZRANGE": true,
"TYPE": true, "TTL": true, "EXISTS": true, "KEYS": true,
"TYPE": true, "TTL": true, "PTTL": true, "EXISTS": true, "KEYS": true,
"INFO": true, "DBSIZE": true, "SCAN": true, "STRLEN": true,
"LLEN": true, "SCARD": true, "ZCARD": true, "HLEN": true,
"HKEYS": true, "HVALS": true, "HSCAN": true, "SSCAN": true,
"ZSCAN": true, "ZRANGEBYSCORE": true,
"GETSET": true, "GETRANGE": true, "SUBSTR": true,
"PING": true, "CONFIG": true, "CLIENT": true, "SLOWLOG": true,
"CLUSTER": true, "MEMORY": true, "OBJECT": true, "DEBUG": true,
"SRANDMEMBER": true, "RANDOMKEY": true, "LASTSAVE": true,
"ROLE": true, "REPLCONF": true, "SENTINEL": true,
"LATENCY": true, "MODULE": true, "COMMAND": true,
}
if !readOnly[cmd] {
return nil, fmt.Errorf("only read-only commands allowed, got: %s", cmd)
@@ -949,7 +962,7 @@ func executeRedisQuery(instance *model.Instance, dbSelect string, command string
return gin.H{
"columns": columns,
"rows": rows,
"rows": rowsOrDefault(rows),
"total": len(rows),
"count": len(rows),
}, nil
+1
View File
@@ -244,6 +244,7 @@ export default function QueriesPage() {
/* ---- Result Sorting ---- */
const sortedResult = useMemo(() => {
if (!result || !sortState.column || !sortState.direction) return result;
if (!Array.isArray(result.rows)) return result;
const col = sortState.column; const dir = sortState.direction === 'asc' ? 1 : -1;
return { ...result, rows: [...result.rows].sort((a, b) => {
const av = a[col] ?? ''; const bv = b[col] ?? '';