# How the s-ui Subscription Service Generates and Encodes Client Links

> Discover how the s-ui subscription service generates and encodes client links. Learn about protocol proxies, newline-delimited payloads, and optional Base64 encoding.

- Repository: [Alireza Ahmadi/s-ui](https://github.com/alireza0/s-ui)
- Tags: how-to-guide
- Published: 2026-05-22

---

**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`](https://github.com/alireza0/s-ui/blob/main/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`](https://github.com/alireza0/s-ui/blob/main/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`](https://github.com/alireza0/s-ui/blob/main/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:

1. **Client Retrieval** – The `getClientBySubId` function (lines 47-55 in [`sub/subService.go`](https://github.com/alireza0/s-ui/blob/main/sub/subService.go)) queries the database for the `Client` model matching the provided subscription identifier.

2. **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.

3. **Link Resolution** – `LinkService.GetLinks` unmarshals the `client.Links` JSON array and processes each entry:
   - Returns raw external URLs directly when `type=="external"`
   - Resolves nested subscription links via `util.GetExternalLink` and splits the fetched content by lines
   - Processes local links by passing them through `addClientInfo` to append the optional statistics string

4. **Protocol Construction** – For local links, the system invokes `util.LinkGenerator` in [`util/genLink.go`](https://github.com/alireza0/s-ui/blob/main/util/genLink.go) to construct protocol-specific URIs from inbound definitions, client configurations, and domain settings.

5. **Payload Assembly** – The resulting slice of link strings is joined with newline characters (`"\n"`) at lines 34-36 of [`sub/subService.go`](https://github.com/alireza0/s-ui/blob/main/sub/subService.go).

6. **Encoding and Headers** – If the *Sub Encode* setting is true, the entire payload undergoes Base64 encoding using `base64.StdEncoding.EncodeToString` (lines 39-43). Simultaneously, `getClientHeaders` invokes `util.GetHeaders` (defined in [`util/outJson.go`](https://github.com/alireza0/s-ui/blob/main/util/outJson.go)) to generate the `Subscription-Userinfo` header 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

```go
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

```go
// 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

```go
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.go`](https://github.com/alireza0/s-ui/blob/main/sub/subService.go) where `GetSubs` orchestrates the entire generation pipeline.
- Client records are retrieved via `getClientBySubId` and optionally enhanced with usage statistics through `getClientInfo`.
- `LinkService.GetLinks` processes stored JSON link configurations, handling external URLs, nested subscriptions, and local protocol links.
- Protocol-specific URIs are constructed in [`util/genLink.go`](https://github.com/alireza0/s-ui/blob/main/util/genLink.go) using `LinkGenerator`, 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-Userinfo` header generated by `util.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`](https://github.com/alireza0/s-ui/blob/main/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`](https://github.com/alireza0/s-ui/blob/main/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`](https://github.com/alireza0/s-ui/blob/main/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`](https://github.com/alireza0/s-ui/blob/main/sub/linkService.go) (lines 11-18) to process each link type according to its specific resolution requirements.