feat(backup): prefer browser request host for backup filename

Name downloaded DB backups after the host shown in the panel title (c.Request.Host) when available, falling back to the configured web domain and then the public IP. Telegram-sent backups have no request context and keep the domain/IP behavior.
This commit is contained in:
MHSanaei
2026-06-23 01:13:09 +02:00
parent b11c51e736
commit dabd3f5d2b
3 changed files with 20 additions and 15 deletions
+1 -1
View File
@@ -298,7 +298,7 @@ func (a *ServerController) getDb(c *gin.Context) {
return return
} }
filename := a.serverService.BackupFilename() filename := a.serverService.BackupFilename(c.Request.Host)
if !filenameRegex.MatchString(filename) { if !filenameRegex.MatchString(filename) {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid filename")) c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid filename"))
return return
+18 -13
View File
@@ -1281,25 +1281,30 @@ func (s *ServerService) GetDb() ([]byte, error) {
} }
// BackupFilename returns the filename for a database backup, named after the // BackupFilename returns the filename for a database backup, named after the
// panel's address — the configured web domain, or the server's public IP when // panel's address so a downloaded or Telegram-sent backup identifies the server
// no domain is set — so a downloaded or Telegram-sent backup identifies the // it came from. requestHost is the browser's address (the getDb handler passes
// server it came from. The extension is .dump on PostgreSQL and .db on SQLite; // c.Request.Host, matching the host shown in the panel title); it is preferred
// the base falls back to "x-ui" when no address is known. // when present, otherwise the configured web domain and then the server's public
func (s *ServerService) BackupFilename() string { // IP are used. The extension is .dump on PostgreSQL and .db on SQLite; the base
// falls back to "x-ui" when no address is known.
func (s *ServerService) BackupFilename(requestHost string) string {
ext := ".db" ext := ".db"
if database.IsPostgres() { if database.IsPostgres() {
ext = ".dump" ext = ".dump"
} }
return s.backupHost() + ext return s.backupHost(requestHost) + ext
} }
// backupHost picks the address used to name backup files, preferring the // backupHost picks the address used to name backup files: the browser's request
// configured web domain and otherwise the cached public IP (IPv4 before IPv6), // host (port stripped, the same value the panel title shows) when available,
// reduced to safe filename characters. // otherwise the configured web domain and then the cached public IP (IPv4 before
func (s *ServerService) backupHost() string { // IPv6), reduced to safe filename characters.
host := "" func (s *ServerService) backupHost(requestHost string) string {
if domain, err := s.settingService.GetWebDomain(); err == nil { host := extractHostname(strings.TrimSpace(requestHost))
host = strings.TrimSpace(domain) if host == "" {
if domain, err := s.settingService.GetWebDomain(); err == nil {
host = strings.TrimSpace(domain)
}
} }
if host == "" { if host == "" {
if st := s.LastStatus(); st != nil { if st := s.LastStatus(); st != nil {
+1 -1
View File
@@ -402,7 +402,7 @@ func (t *Tgbot) sendBackup(chatId int64) {
// Send database backup (SQLite file, or a pg_dump archive on PostgreSQL) // Send database backup (SQLite file, or a pg_dump archive on PostgreSQL)
dbData, err := t.serverService.GetDb() dbData, err := t.serverService.GetDb()
if err == nil { if err == nil {
dbFilename := t.serverService.BackupFilename() dbFilename := t.serverService.BackupFilename("")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
document := tu.Document( document := tu.Document(
tu.ID(chatId), tu.ID(chatId),