How the s-ui Subscription Service Generates and Encodes Client Links
The s-ui subscription service retrieves client records from the database, generates protocol-specific proxy links using LinkGenerator, assembles them into a newline-delimited payload, and optionally Base64-encodes the result before returning it with traffic usage headers.
The subscription mechanism in the alireza0/s-ui proxy management panel dynamically produces client configuration links for protocols including VMess, VLESS, Trojan, and Shadowsocks. Understanding exactly how this subscription service generates and encodes client links enables administrators to troubleshoot connectivity issues, optimize delivery formats, and customize client information displays.
Core Implementation Files
The subscription pipeline spans three primary components that handle orchestration, link resolution, and protocol-specific URI construction.
sub/subService.go - Subscription Orchestration
The entry point resides in sub/subService.go, where SubService.GetSubs (lines 20-44) coordinates the entire workflow. This function retrieves the client record, delegates link generation, assembles the final payload, and applies optional encoding before returning the result with HTTP headers.
sub/linkService.go - Link Resolution and Formatting
The LinkService struct in sub/linkService.go handles the parsing and resolution logic through GetLinks (lines 11-18). It unmarshals the JSON-encoded link storage from the client model, processes external URLs, resolves nested subscription references, and optionally prepends client information to each link.
util/genLink.go - Protocol URI Generation
Raw protocol links are constructed in util/genLink.go via the LinkGenerator function. This utility builds standardized URIs for VMess, VLESS, Trojan, Shadowsocks, and other supported protocols, incorporating TLS settings, reality parameters, and transport configurations through helper functions like prepareTls, getTransportParams, and getTlsParams.
Step-by-Step Link Generation Process
The subscription service executes a six-stage pipeline when processing a client request:
-
Client Retrieval – The
getClientBySubIdfunction (lines 47-55 insub/subService.go) queries the database for theClientmodel matching the provided subscription identifier. -
Statistics Compilation – If the global Show Sub Info setting is enabled,
getClientInfo(lines 62-76) formats traffic-remaining statistics, expiry dates, and usage metrics into a display string. -
Link Resolution –
LinkService.GetLinksunmarshals theclient.LinksJSON array and processes each entry:- Returns raw external URLs directly when
type=="external" - Resolves nested subscription links via
util.GetExternalLinkand splits the fetched content by lines - Processes local links by passing them through
addClientInfoto append the optional statistics string
- Returns raw external URLs directly when
-
Protocol Construction – For local links, the system invokes
util.LinkGeneratorinutil/genLink.goto construct protocol-specific URIs from inbound definitions, client configurations, and domain settings. -
Payload Assembly – The resulting slice of link strings is joined with newline characters (
"\n") at lines 34-36 ofsub/subService.go. -
Encoding and Headers – If the Sub Encode setting is true, the entire payload undergoes Base64 encoding using
base64.StdEncoding.EncodeToString(lines 39-43). Simultaneously,getClientHeadersinvokesutil.GetHeaders(defined inutil/outJson.go) to generate theSubscription-Userinfoheader containing traffic statistics and update intervals.
Base64 Encoding and Transport Headers
Two optional formatting layers modify the final delivery format.
Optional Base64 Encoding
When the administrator enables the global Sub Encode configuration, the subscription service encodes the newline-delimited link list using Go's standard base64 library. This transformation occurs immediately before the function returns, ensuring that clients receive either plain text or encoded content based on their subscription client compatibility.
Subscription-Userinfo Headers
The getClientHeaders function (lines 57-60) produces standardized HTTP headers that communicate metadata to compatible clients. These headers include traffic usage statistics, remaining bandwidth quotas, and recommended update intervals parsed from the client's database record.
Practical Implementation Examples
The following examples demonstrate common interactions with the subscription generation system.
Fetching a Subscription for a Client
subService := &sub.SubService{}
payload, headers, err := subService.GetSubs("my-client-id")
if err != nil {
// handle error
}
fmt.Println("Headers:", headers)
fmt.Println("Payload:")
fmt.Println(*payload) // Base64-encoded if the setting is on
Generating Protocol-Specific Links
// Assume inbound and clientConfig are already loaded from DB
links := util.LinkGenerator(clientConfig, inbound, "example.com")
for _, l := range links {
fmt.Println(l) // e.g. vmess://eyJ2IjoiMiIsIn...
}
Appending Client Statistics to Links
uri := "vmess://eyJ2IjoiMiIsIn..."
clientInfo := " 📊1.23GB 10Days"
finalURI := sub.LinkService{}.addClientInfo(uri, clientInfo)
// finalURI becomes "...#my‑remark 📊1.23GB 10Days"
Summary
- The subscription flow originates in
sub/subService.gowhereGetSubsorchestrates the entire generation pipeline. - Client records are retrieved via
getClientBySubIdand optionally enhanced with usage statistics throughgetClientInfo. LinkService.GetLinksprocesses stored JSON link configurations, handling external URLs, nested subscriptions, and local protocol links.- Protocol-specific URIs are constructed in
util/genLink.gousingLinkGenerator, which incorporates TLS, reality, and transport parameters. - The final payload is assembled with newline delimiters and optionally Base64-encoded based on the Sub Encode global setting.
- Traffic metadata is delivered via the
Subscription-Userinfoheader generated byutil.GetHeaders.
Frequently Asked Questions
How does s-ui handle external subscription links?
When processing stored links with type=="external", the LinkService in sub/linkService.go returns the raw URL directly or fetches referenced subscriptions via util.GetExternalLink, splitting the downloaded content into individual lines for inclusion in the final payload.
What proxy protocols does the LinkGenerator support?
The util.LinkGenerator function in util/genLink.go constructs standardized subscription URIs for VMess, VLESS, Trojan, Shadowsocks, and other protocols supported by the s-ui panel, automatically appending TLS, reality, and transport-specific parameters based on the inbound configuration.
When does the subscription service apply Base64 encoding?
Base64 encoding occurs in sub/subService.go (lines 39-43) only when the administrator enables the global Sub Encode setting, transforming the newline-delimited link list using base64.StdEncoding.EncodeToString before returning the payload to the client.
Where does s-ui store individual client subscription links?
The system stores subscription link configurations as JSON-encoded arrays in the Links field of the Client database model. The LinkService.GetLinks method unmarshals this data in sub/linkService.go (lines 11-18) to process each link type according to its specific resolution requirements.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →