From 5620d739c6c9e00d2b732c0a89174f682e76e806 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Sun, 21 Sep 2025 21:20:37 +0200 Subject: [PATCH] improved sub: BuildURLs --- sub/subService.go | 80 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/sub/subService.go b/sub/subService.go index 6204fdee..77a60356 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -1077,20 +1077,73 @@ func (s *SubService) ResolveRequest(c *gin.Context) (scheme string, host string, return } -// BuildURLs constructs absolute subscription and json URLs. -// BuildURLs constructs subscription and JSON subscription URLs for a given subscription ID. +// BuildURLs constructs absolute subscription and JSON subscription URLs for a given subscription ID. +// It prioritizes configured URIs, then individual settings, and finally falls back to request-derived components. func (s *SubService) BuildURLs(scheme, hostWithPort, subPath, subJsonPath, subId string) (subURL, subJsonURL string) { - if strings.HasSuffix(subPath, "/") { - subURL = scheme + "://" + hostWithPort + subPath + subId - } else { - subURL = scheme + "://" + hostWithPort + strings.TrimRight(subPath, "/") + "/" + subId + // Input validation + if subId == "" { + return "", "" } - if strings.HasSuffix(subJsonPath, "/") { - subJsonURL = scheme + "://" + hostWithPort + subJsonPath + subId - } else { - subJsonURL = scheme + "://" + hostWithPort + strings.TrimRight(subJsonPath, "/") + "/" + subId + + // Get configured URIs first (highest priority) + configuredSubURI, _ := s.settingService.GetSubURI() + configuredSubJsonURI, _ := s.settingService.GetSubJsonURI() + + // Determine base scheme and host (cached to avoid duplicate calls) + var baseScheme, baseHostWithPort string + if configuredSubURI == "" || configuredSubJsonURI == "" { + baseScheme, baseHostWithPort = s.getBaseSchemeAndHost(scheme, hostWithPort) } - return + + // Build subscription URL + subURL = s.buildSingleURL(configuredSubURI, baseScheme, baseHostWithPort, subPath, subId) + + // Build JSON subscription URL + subJsonURL = s.buildSingleURL(configuredSubJsonURI, baseScheme, baseHostWithPort, subJsonPath, subId) + + return subURL, subJsonURL +} + +// getBaseSchemeAndHost determines the base scheme and host from settings or falls back to request values +func (s *SubService) getBaseSchemeAndHost(requestScheme, requestHostWithPort string) (string, string) { + subDomain, err := s.settingService.GetSubDomain() + if err != nil || subDomain == "" { + return requestScheme, requestHostWithPort + } + + // Get port and TLS settings + subPort, _ := s.settingService.GetSubPort() + subKeyFile, _ := s.settingService.GetSubKeyFile() + subCertFile, _ := s.settingService.GetSubCertFile() + + // Determine scheme from TLS configuration + scheme := "http" + if subKeyFile != "" && subCertFile != "" { + scheme = "https" + } + + // Build host:port, always include port for clarity + hostWithPort := fmt.Sprintf("%s:%d", subDomain, subPort) + + return scheme, hostWithPort +} + +// buildSingleURL constructs a single URL using configured URI or base components +func (s *SubService) buildSingleURL(configuredURI, baseScheme, baseHostWithPort, basePath, subId string) string { + if configuredURI != "" { + return s.joinPathWithID(configuredURI, subId) + } + + baseURL := fmt.Sprintf("%s://%s", baseScheme, baseHostWithPort) + return s.joinPathWithID(baseURL+basePath, subId) +} + +// joinPathWithID safely joins a base path with a subscription ID +func (s *SubService) joinPathWithID(basePath, subId string) string { + if strings.HasSuffix(basePath, "/") { + return basePath + subId + } + return basePath + "/" + subId } // BuildPageData parses header and prepares the template view model. @@ -1103,10 +1156,7 @@ func (s *SubService) BuildPageData(subId string, hostHeader string, traffic xray remained := "" if traffic.Total > 0 { total = common.FormatTraffic(traffic.Total) - left := traffic.Total - (traffic.Up + traffic.Down) - if left < 0 { - left = 0 - } + left := max(traffic.Total-(traffic.Up+traffic.Down), 0) remained = common.FormatTraffic(left) }