Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Gateway

Package: openshell/v1/gateway

The gateway package reads on-disk gateway configurations created by the OpenShell Rust CLI and constructs fully wired SDK clients. It eliminates the boilerplate of locating config files, parsing metadata, loading tokens, and wiring auth providers.

Quick Start

import "github.com/rhuss/openshell-sdk-go/openshell/v1/gateway"

// Connect to a named gateway
client, err := gateway.NewClient("prod")
if err != nil {
    log.Fatal(err)
}
defer client.Close()

Functions

FunctionDescription
NewClient(name, opts...)Create a fully wired SDK client from gateway config
LoadConfig(name)Parse gateway config without connecting
ListGateways()Enumerate all available gateways

NewClient

func NewClient(name string, opts ...ClientOption) (*v1.Client, error)

Creates a fully configured SDK client for the named gateway. If name is empty, the active gateway (set via openshell gateway use) is used.

The function resolves the gateway directory, parses metadata.json, loads tokens lazily, maps the auth mode to an SDK auth provider, and applies any ClientOption values before delegating to v1.NewClient.

// Named gateway
client, err := gateway.NewClient("prod")

// Active gateway
client, err := gateway.NewClient("")

// With options
client, err := gateway.NewClient("staging",
    gateway.WithTimeout(10 * time.Second),
    gateway.WithLogger(myLogger),
)

Errors: ErrGatewayNotFound, ErrConfigParse, ErrTokenLoad, ErrUnsupportedAuthMode, ErrInvalidGatewayName, ErrNoActiveGateway

LoadConfig

func LoadConfig(name string) (*Config, error)

Parses gateway configuration without creating a client connection. Returns a frozen snapshot; changes to on-disk files after the call are not reflected.

cfg, err := gateway.LoadConfig("staging")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Endpoint: %s, Auth: %s\n", cfg.Endpoint, cfg.AuthMode)

ListGateways

func ListGateways() ([]Info, error)

Enumerates all available gateways from user and system directories. User gateways appear first. Duplicate names resolve to user precedence. Returns an empty slice (not an error) when no gateways are configured.

gateways, err := gateway.ListGateways()
for _, gw := range gateways {
    fmt.Printf("%s (active=%v, source=%s)\n", gw.Name, gw.Active, gw.Source)
}

Types

Config

type Config struct {
    Name     string       // Validated gateway name
    Endpoint string       // Host:port of the gateway
    AuthMode AuthMode     // Resolved auth mode
    Source   ConfigSource // User or System origin
    Dir      string       // Absolute path to gateway config directory
}

Info

type Info struct {
    Name   string       // Gateway name from directory listing
    Active bool         // Whether this is the active gateway
    Source ConfigSource // User or System origin
}

AuthMode

ValueConstantSDK AuthProvider
"" or "none"AuthModeNonev1.NoAuth()
"plaintext"AuthModePlaintextv1.NoAuth() + insecure TLS
"cloudflare_jwt"AuthModeCloudflareJWTLazy edge token auth
"oidc"AuthModeOIDCv1.RefreshableToken with disk source
"mtls"AuthModeMTLSUnsupported (use WithAuth)

ClientOption

ConstructorEffect
WithLogger(l)Set logger on the SDK client
WithTimeout(d)Set connection timeout
WithTLS(cfg)Override TLS settings from gateway config
WithAuth(provider)Override auto-resolved auth provider
WithRetryPolicy(p)Set retry policy

Error Handling

All errors support errors.Is for classification:

client, err := gateway.NewClient("my-gateway")
if errors.Is(err, gateway.ErrGatewayNotFound) {
    fmt.Println("Gateway not configured. Run: openshell gateway add my-gateway")
}
if errors.Is(err, gateway.ErrTokenLoad) {
    fmt.Println("Token expired or missing. Run: openshell gateway login my-gateway")
}
ErrorMeaning
ErrGatewayNotFoundNo gateway directory in user or system paths
ErrConfigParsemetadata.json missing or malformed
ErrTokenLoadToken file missing or unreadable
ErrUnsupportedAuthModeUnrecognized auth_mode value
ErrInvalidGatewayNameName fails validation
ErrNoActiveGatewayNo active gateway configured

On-Disk Layout

The package reads gateway metadata from these locations:

$XDG_CONFIG_HOME/openshell/          (user, default: ~/.config/openshell/)
├── active_gateway                   # Plain text: active gateway name
└── gateways/
    └── <name>/
        ├── metadata.json            # {"endpoint":"...","auth_mode":"...","name":"..."}
        ├── edge_token               # Cloudflare edge JWT (plaintext)
        ├── cf_token                 # Legacy edge token (fallback)
        └── oidc_token.json          # OIDC token bundle

/etc/openshell/gateways/             (system, fallback)

User gateways take precedence over system gateways with the same name.

Thread Safety

All exported functions (NewClient, LoadConfig, ListGateways) are safe for concurrent use from multiple goroutines. Token loading uses internal synchronization.