Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormhsanaei <ho3ein.sanaei@gmail.com>2025-09-21 22:20:37 +0300
committermhsanaei <ho3ein.sanaei@gmail.com>2025-09-21 22:20:37 +0300
commit5620d739c6c9e00d2b732c0a89174f682e76e806 (patch)
tree919a3eee7062a28b9f7c26ec4078ee7e0c951969 /sub/subService.go
parentd518979e4ff8ed21d209d8ef33eb993ca29b020d (diff)
improved sub: BuildURLs
Diffstat (limited to 'sub/subService.go')
-rw-r--r--sub/subService.go80
1 files 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)
}