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:
1 parent
e8fd5f6b63
commit
e9a700b9d9
2 files changed
+16
-2
No files matched your search
@@ -705,6 +705,14 @@ func parseCommandParts(input string) []string {
|
|||||||
return parts
|
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) {
|
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")
|
// Parse Redis DB number from dbSelect (e.g. "0", "1")
|
||||||
redisDB := 0
|
redisDB := 0
|
||||||
@@ -731,12 +739,17 @@ func executeRedisQuery(instance *model.Instance, dbSelect string, command string
|
|||||||
readOnly := map[string]bool{
|
readOnly := map[string]bool{
|
||||||
"GET": true, "MGET": true, "HGET": true, "HGETALL": true,
|
"GET": true, "MGET": true, "HGET": true, "HGETALL": true,
|
||||||
"LRANGE": true, "SMEMBERS": true, "ZRANGE": 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,
|
"INFO": true, "DBSIZE": true, "SCAN": true, "STRLEN": true,
|
||||||
"LLEN": true, "SCARD": true, "ZCARD": true, "HLEN": true,
|
"LLEN": true, "SCARD": true, "ZCARD": true, "HLEN": true,
|
||||||
"HKEYS": true, "HVALS": true, "HSCAN": true, "SSCAN": true,
|
"HKEYS": true, "HVALS": true, "HSCAN": true, "SSCAN": true,
|
||||||
"ZSCAN": true, "ZRANGEBYSCORE": true,
|
"ZSCAN": true, "ZRANGEBYSCORE": true,
|
||||||
"GETSET": true, "GETRANGE": true, "SUBSTR": 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] {
|
if !readOnly[cmd] {
|
||||||
return nil, fmt.Errorf("only read-only commands allowed, got: %s", 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{
|
return gin.H{
|
||||||
"columns": columns,
|
"columns": columns,
|
||||||
"rows": rows,
|
"rows": rowsOrDefault(rows),
|
||||||
"total": len(rows),
|
"total": len(rows),
|
||||||
"count": len(rows),
|
"count": len(rows),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ export default function QueriesPage() {
|
|||||||
/* ---- Result Sorting ---- */
|
/* ---- Result Sorting ---- */
|
||||||
const sortedResult = useMemo(() => {
|
const sortedResult = useMemo(() => {
|
||||||
if (!result || !sortState.column || !sortState.direction) return result;
|
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;
|
const col = sortState.column; const dir = sortState.direction === 'asc' ? 1 : -1;
|
||||||
return { ...result, rows: [...result.rows].sort((a, b) => {
|
return { ...result, rows: [...result.rows].sort((a, b) => {
|
||||||
const av = a[col] ?? ''; const bv = b[col] ?? '';
|
const av = a[col] ?? ''; const bv = b[col] ?? '';
|
||||||
|
|||||||
Reference in new issue
Block a user