routers

package
v1.785.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Overview

Package routers @APIVersion 1.70.0 @Title Hanzo Cloud RESTful API @Description Swagger Docs of Hanzo Cloud Backend API @Contact cloud@hanzo.ai @SecurityDefinition AccessToken apiKey Authorization header @Schemes https,http @ExternalDocs Find out more about Hanzo Cloud @ExternalDocsUrl https://hanzo.ai/cloud

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AfterRecordMessage

func AfterRecordMessage(ctx *context.Context)

func AuthzFilter

func AuthzFilter(ctx *context.Context)

func AutoSigninFilter

func AutoSigninFilter(ctx *context.Context)

func BalanceGateFilter

func BalanceGateFilter(ctx *context.Context)

BalanceGateFilter is a Beego BeforeRouter filter that checks whether the requesting user has a positive Commerce balance before allowing paid API requests to proceed. It runs after AutoSigninFilter (which sets session users for legacy auth paths) and handles its own user resolution for JWT and IAM API key auth paths.

Design: fail-open. If Commerce is unreachable or the user cannot be identified, the request is allowed through. The controller-level balance check in resolveProviderForUser remains as a defense-in-depth backstop.

func CacheControlFilter

func CacheControlFilter(ctx *context.Context)

CacheControlFilter adds Cache-Control headers to prevent caching of sensitive API endpoints This ensures that sensitive data (like passwords, user chats, messages) are not cached by intermediary proxies, SSL terminators, or browsers

func CorsFilter

func CorsFilter(ctx *context.Context)

func GetEffectiveOrg

func GetEffectiveOrg(ctx *context.Context) string

GetEffectiveOrg resolves the organization for data-scoping in filters from the VERIFIED request principal — never a raw client header.

On the direct (non-gateway) ingress the X-Org-Id header is fully client-controlled, so trusting it would let any caller act as any org (cross-tenant read/write + billing attribution). It is honored ONLY when it matches the authenticated principal's own org, or the principal is a global admin (cross-org platform access). A non-admin can never escape their own org via a header; an unauthenticated caller's header is ignored entirely.

Behind the gateway the injected X-Org-Id equals the JWT owner, so this resolves identically — the gateway path is unaffected.

func GetSessionUser

func GetSessionUser(ctx *context.Context) *iam.User

func GetTenantOrgID

func GetTenantOrgID(ctx *context.Context) string

GetTenantOrgID returns the org from IAM context.

func GetTenantProjectID

func GetTenantProjectID(ctx *context.Context) string

GetTenantProjectID returns the project ID from IAM context.

func GetTenantUserID

func GetTenantUserID(ctx *context.Context) string

GetTenantUserID returns the user ID from IAM context.

func HstsFilter

func HstsFilter(ctx *context.Context)

HstsFilter adds HTTP Strict Transport Security header to HTTPS responses This ensures browsers only access the website using HTTPS

func InitBalanceGate

func InitBalanceGate()

InitBalanceGate reads Commerce and IAM connection parameters from app config and creates the balance gate. Must be called once during startup. If Commerce is not configured, the gate is not created and BalanceGateFilter is a no-op.

func InitTierCache

func InitTierCache()

InitTierCache reads Commerce connection parameters from app config and creates the tier cache. Must be called once during startup. If Commerce is not configured (no commerceEndpoint), the cache is not created and DefaultTierFunc falls back to env-var overrides or TierZenFree.

func PrometheusFilter

func PrometheusFilter(ctx *context.Context)

func RateLimitFilter

func RateLimitFilter(ctx *context.Context)

RateLimitFilter is a Beego BeforeRouter filter that enforces per-key rate limits on API endpoints. It extracts the API key from the Authorization header (Bearer token) or X-API-Key header.

Rate-limited paths: /v1/messages, /v1/messages, and other /v1/ endpoints that carry a bearer token. Excluded: health, metrics, models (read-only), static, UI routes.

func RecordMessage

func RecordMessage(ctx *context.Context)

func SecureCookieFilter

func SecureCookieFilter(ctx *context.Context)

SecureCookieFilter ensures session cookies have the Secure flag set This is necessary when running behind a reverse proxy that handles HTTPS

func StaticFilter

func StaticFilter(ctx *context.Context)

func TenantContextFilter

func TenantContextFilter(ctx *context.Context)

TenantContextFilter captures IAM identity context for downstream scoping and observability. The org is taken from the VERIFIED principal (GetEffectiveOrg), NOT the raw X-Org-Id header: on the direct ingress that header is client-controlled, so storing it verbatim would let any caller spoof a tenant. GetEffectiveOrg honors the header only for the principal's own org (or a global admin), so the stored org is always the caller's real tenant.

func V1CloudRewriteFilter

func V1CloudRewriteFilter(ctx *context.Context)

V1CloudRewriteFilter rewrites /v1/cloud/* requests to /api/* so the canonical /<version>/<service>/<path> pattern works without duplicating every route in router.go.

Example: /v1/cloud/get-stores → /api/get-stores

Types

type BalanceGate

type BalanceGate struct {
	// contains filtered or unexported fields
}

BalanceGate enforces a positive spendable balance before paid requests. The balance itself lives in the shared object.BalanceLedger — the ONE source of truth also used by the controller debit path to reserve (before a request) and settle (after). Reading the ledger here makes the gate reservation-aware and reflects local settles immediately, so the cache window can never serve a stale-positive balance after the funds are spent. The gate adds only its own freshness scheduling (async refresh from Commerce) and identity resolution.

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter tracks per-key rate limiters with automatic cleanup of stale entries.

func InitRateLimiter

func InitRateLimiter(tierFunc func(string) Tier) *RateLimiter

InitRateLimiter creates the global rate limiter. Must be called once during startup (before beego.Run). Returns the instance so the caller can call Stop() on shutdown.

func NewRateLimiter

func NewRateLimiter(tierFunc func(string) Tier, cleanupInterval time.Duration) *RateLimiter

NewRateLimiter creates a RateLimiter that starts a background goroutine to evict stale entries every cleanupInterval. The tierFunc callback resolves an API key to its Tier; pass nil to always use TierZenFree.

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(apiKey string) bool

Allow checks whether a request from the given API key should be permitted. It returns true if the request is within the rate limit.

func (*RateLimiter) Metrics

func (rl *RateLimiter) Metrics() (allowed, denied uint64)

Metrics returns the current rate limit hit/pass counters.

func (*RateLimiter) RetryAfter

func (rl *RateLimiter) RetryAfter(apiKey string) int

RetryAfter returns the number of seconds until the next token is available for the given API key. Returns 0 if the key has no entry.

func (*RateLimiter) Stop

func (rl *RateLimiter) Stop()

Stop terminates the background cleanup goroutine.

type Response

type Response struct {
	Status string      `json:"status"`
	Msg    string      `json:"msg"`
	Data   interface{} `json:"data"`
	Data2  interface{} `json:"data2"`
}

type Tier

type Tier string

Tier represents an API usage tier with associated rate limits. All tiers follow the "zen-*" naming convention as the canonical identifier.

const (
	TierZenFree       Tier = "zen-free"
	TierZenPro        Tier = "zen-pro"
	TierZenTeam       Tier = "zen-team"
	TierZenEnterprise Tier = "zen-enterprise"
	TierZenCustom     Tier = "zen-custom"
)

func DefaultTierFunc

func DefaultTierFunc(key string) Tier

DefaultTierFunc resolves a rate-limit key to a Tier using a three-level lookup. The key is the IAM org slug (resolved by RateLimitFilter via resolveBillingKey) for authenticated traffic, or a raw API key for anonymous traffic — both flow through the same path:

  1. Static env-var overrides (RATE_LIMIT_TIERS) -- highest priority, for operator-managed mappings. Supports exact and prefix matching (works for both org slugs like "acme=zen-enterprise" and key prefixes like "hk-0d2eb").
  2. Commerce tier cache -- backed by async lookups to Commerce billing API (GET /v1/billing/tier?user=<org>). On cache hit, the cached tier is returned immediately. On cache miss, TierZenFree is returned and a background goroutine populates the cache so the next request uses the correct tier.
  3. TierZenFree -- default when no override or cache entry exists.

This function never blocks on network I/O. Commerce lookups happen asynchronously; the worst case is that a new org's first few requests are rate-limited at the free tier until the cache is populated.

type TierCache

type TierCache struct {
	// contains filtered or unexported fields
}

TierCache caches apiKey-to-tier mappings resolved from Commerce. Stale entries (older than tierCacheTTL) are lazily ignored on read and periodically evicted by a background goroutine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL