Files
xk-hy-forward-go/internal/forward/testweb/apilog_list.go
2026-05-28 17:04:29 +08:00

99 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package testweb
import (
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
)
var logRelRE = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}/\d{8,14}_file_[a-f0-9]+\.log$`)
// FileLogEntry api-logs 中的 file 通道日志条目。
type FileLogEntry struct {
Rel string `json:"rel"`
Name string `json:"name"`
HourDir string `json:"hourDir"`
Modified string `json:"modified"`
Size int64 `json:"size"`
}
// ListFileLogs 列出 api-logs 下所有 *_file_*.log按修改时间倒序
func ListFileLogs(root string) ([]FileLogEntry, error) {
root, err := filepath.Abs(root)
if err != nil {
return nil, err
}
var entries []FileLogEntry
err = filepath.WalkDir(root, func(path string, d os.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if d.IsDir() {
return nil
}
name := d.Name()
if !strings.Contains(name, "_file_") || !strings.HasSuffix(name, ".log") {
return nil
}
rel, err := filepath.Rel(root, path)
if err != nil {
return err
}
rel = filepath.ToSlash(rel)
if !logRelRE.MatchString(rel) {
return nil
}
info, err := d.Info()
if err != nil {
return err
}
hourDir := filepath.ToSlash(filepath.Dir(rel))
entries = append(entries, FileLogEntry{
Rel: rel,
Name: name,
HourDir: hourDir,
Modified: info.ModTime().Format(time.RFC3339),
Size: info.Size(),
})
return nil
})
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
sort.Slice(entries, func(i, j int) bool {
return entries[i].Modified > entries[j].Modified
})
return entries, nil
}
// resolveLogRelPath 校验 rel 并返回绝对路径。
func resolveLogRelPath(root, rel string) (string, error) {
rel = filepath.ToSlash(strings.TrimSpace(rel))
if rel == "" || strings.Contains(rel, "..") {
return "", fmt.Errorf("invalid rel path")
}
if !logRelRE.MatchString(rel) {
return "", fmt.Errorf("rel path not allowed")
}
root, err := filepath.Abs(root)
if err != nil {
return "", err
}
full := filepath.Join(root, filepath.FromSlash(rel))
full, err = filepath.Abs(full)
if err != nil {
return "", err
}
if !strings.HasPrefix(full, root+string(os.PathSeparator)) && full != root {
return "", fmt.Errorf("path escape")
}
return full, nil
}