server

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: LGPL-2.1 Imports: 51 Imported by: 0

README

mod/server

mod/server is the inbound serving layer. It accepts web and Yggdrasil HTTP traffic, applies ingress limits, routes generated API calls, serves package-manager endpoints, renders the HTML UI, streams artifacts, exposes metrics, and hosts brother RPC on enabled web and Yggdrasil entries. The same public release and artifact routes can also be used by a brother as a read-only fallback when RPC is disabled.

Place in the Runtime

flowchart TD
  web["web listener"] --> front["front handler"]
  ygg["Yggdrasil listener"] --> front
  front --> rpc["brother RPC gate"]
  front --> router["generated router"]
  router --> funcs["funcObj"]
  funcs --> builders["dataapi, goproxy, composer, feedatom, webui"]
  builders --> storage["storage"]
  builders --> state["state"]
  builders --> cache["byte cache"]

Responsibilities

  • Start listeners for single, shared, split, and Yggdrasil modes.
  • Add listener context, request id, method gate, URI cap, rate limits, and route-prefix handling.
  • Implement generated api.FuncInterface handlers.
  • Serve JSON APIs, Go proxy routes, Composer routes, Atom feeds, HTML UI, OpenAPI, sitemap, logos, favicon, and OG images.
  • Stream large artifacts with ETag, Last-Modified, Content-Length, Range, and HEAD support.
  • Gate brother RPC per listener with brother.rpc.web_enabled and brother.rpc.ygg_enabled.
  • Keep public release metadata and universal archives usable for brother fallback even when /rpc is disabled.
  • Expose metrics JSON groups and optional internal Prometheus text.

Request Flow

sequenceDiagram
  participant Client as client
  participant Front as front handler
  participant Router as generated router
  participant Handler as domain handler
  participant Store as storage/cache/state
  Client->>Front: HTTP request
  Front->>Front: ingress checks and listener context
  Front->>Router: route request
  Router->>Handler: typed API call
  Handler->>Store: read or build response
  Store-->>Handler: bytes, stream, or typed result
  Handler-->>Client: typed response

Contracts

  • Business handlers do not write directly to http.ResponseWriter; they return generated response types.
  • Artifacts stream from disk or builders, not through unbounded RAM buffers.
  • HTML builders must use request context so canceled clients stop expensive storage work.
  • RPC is fail-closed when disabled for the current listener.
  • /rpc accepts only CONNECT; normal HTTP methods do not enter the RPC server.
  • Public fallback uses normal generated routes, so reverse proxies handle it like ordinary read-only client traffic.
  • Metrics labels must stay low-cardinality.

Important Files

  • server.go, deps.go, listener.go: assembly and lifecycle.
  • front.go, hooks.go, respond.go, errors.go: common HTTP frame.
  • funcimpl*.go: generated API handler implementation.
  • artifact.go, objcache.go, metrics.go, assets.go: artifact serving, response cache, metrics, built-in assets.
  • brother/: RPC server.
  • dataapi/, goproxy/, composer/, feedatom/, webui/: domain response builders.

Operational Notes

shared mode is for a TLS-terminating reverse proxy where the public scheme is HTTPS but the process listens on one plain HTTP socket. split mode is for separate HTTP and HTTPS binds. single mode is simplest for local development. Brother RPC is mounted before the generated API router, so the OpenAPI route list does not describe it. Public fallback uses generated API and artifact routes and therefore follows the same prefix, cache, and proxy behavior as normal clients.

In nested mode (web.static.dir set) per-key API routes move under web.routing.prefix, but service routes stay at their well-known root paths. /info therefore stays reachable at the root and advertises route_prefix: empty when the API is served at the root, otherwise the mounted segment. A brother reads this field during discovery to derive remote keys under the prefix the node actually serves.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArtifactBuilderInterface

type ArtifactBuilderInterface = storage.ArtifactBuilderInterface

ArtifactBuilderInterface and HotFileObj are storage aliases used by overlay builders and streaming artifact serving.

type ComposerNamesInterface

type ComposerNamesInterface interface {
	ComposerPackageNames() []string
	ComposerKeyForName(name string) (string, bool)
}

ComposerNamesInterface exposes cross-key composer names and name-to-winner mapping for serve-time p2.

type DataStateInterface

type DataStateInterface interface {
	Health() state.HealthViewObj
	Snapshot() state.SnapshotObj
	KeyState(key string) (state.KeyStateObj, bool)
	KeyStates() []state.KeyStateObj
	Checksums() state.ChecksumSetObj
}

DataStateInterface exposes health, classification, and version snapshots for data APIs.

type DataStoreInterface

type DataStoreInterface interface {
	ListVersionsKeyset(ctx context.Context, key string, includeDeleted bool, afterSeq int64, afterVersion string, limit int) ([]core.VersionObj, error)
	ListVersionsKeysetBefore(ctx context.Context, key string, includeDeleted bool, beforeSeq int64, beforeVersion string, limit int) ([]core.VersionObj, error)
	ListVersionsPage(ctx context.Context, key string, includeDeleted bool, limit int, offset int) ([]core.VersionObj, error)
	CountVersions(ctx context.Context, key string) (uint64, error)
	GetVersion(ctx context.Context, key string, version string) (core.VersionObj, bool, error)
	LatestVersion(ctx context.Context, key string) (core.VersionObj, bool, error)
	GetArtifact(ctx context.Context, keyObj core.ArtifactKeyObj) (core.ArtifactObj, bool, error)
	ListArtifacts(ctx context.Context, key string, version string) ([]core.ArtifactObj, error)
	EnsureArtifactFile(ctx context.Context, keyObj core.ArtifactKeyObj, builderObj ArtifactBuilderInterface) (*HotFileObj, error)
	GetDetection(ctx context.Context, key string, version string) (core.DetectionObj, bool, error)
	RewriteSet(ctx context.Context, key string, version string) ([]core.HashObj, error)
	ReadTree(ctx context.Context, treeHashObj core.HashObj) ([]core.TreeEntryObj, error)
	ReadBlob(ctx context.Context, hashObj core.HashObj) ([]byte, error)
	ListPublishFeed(ctx context.Context, key string, limit int) ([]core.FeedEventObj, error)
}

DataStoreInterface is the storage read surface for data APIs: artifacts, detection, versions, and feeds. Signatures match storage.Obj because it is the only production provider.

type DepsObj

type DepsObj struct {
	Config    *stconf.ConfigObj
	Storage   DataStoreInterface
	State     DataStateInterface
	Overlay   *overlay.Obj
	Telemetry *telemetry.Obj
	Composer  ComposerNamesInterface
	Mesh      mesh.NodeInterface
	Log       zerolog.Logger
	// Cache is a shared RAM cache for built byte bodies. Nil disables cache and singleflight deduplication.
	Cache *cache.Obj
}

DepsObj contains edge server dependencies wired by main.go and passed into New.

type HotFileObj

type HotFileObj = storage.HotFileObj

ArtifactBuilderInterface and HotFileObj are storage aliases used by overlay builders and streaming artifact serving.

type ServerObj

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

ServerObj holds the edge server. A single ogen router serves per-listener http.Server instances on web and Yggdrasil sockets. Routing and response encoding stay in the router; listeners and lifecycle live here and in listener.go.

func New

func New(depsObj DepsObj) (*ServerObj, error)

New assembles the edge server in three steps: funcObj, sub-services, then the ogen router. The router receives telemetry, middleware, error handling and not-found pages. Listener sockets are bound separately in Start from listener.go.

func (*ServerObj) Handler

func (obj *ServerObj) Handler(lc listenerCtxObj) http.Handler

Handler is the outer handler for one entry listener. It injects listener context, applies RPC/ingress/method gates, request ID, and go-proxy host/major stripping. HEAD is routed as GET because ogen only defines GET operations here.

func (*ServerObj) Shutdown

func (obj *ServerObj) Shutdown(ctx context.Context) error

Shutdown first closes brother sessions, then drains http.Server until the ctx deadline.

func (*ServerObj) Start

func (obj *ServerObj) Start() error

Start binds sockets and serves each listener in its own goroutine.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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