Browse Source

improved sub: BuildURLs

mhsanaei 1 day ago
parent
commit
5620d739c6
1 changed files with 65 additions and 15 deletions
  1. 65 15
      sub/subService.go

+ 65 - 15
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)
 	}