server

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package server is vrok's HTTP layer: it maps share URLs onto local files, directories and upstream applications, and enforces expiry, passwords and download limits on every request.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Chain

func Chain(h http.Handler, mw ...Middleware) http.Handler

Chain applies middleware so that the first argument is the outermost layer.

func SharePath

func SharePath(token string) string

SharePath returns the path a share is served under, for callers that need to build an absolute URL from a public origin.

Types

type Crumb

type Crumb struct {
	Name string
	URL  string
}

Crumb is one breadcrumb entry. It mirrors viewer.Crumb so the server can build navigation without the viewer package leaking into every handler.

type DirectoryHandler

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

DirectoryHandler serves a directory tree, confined to its root.

func (DirectoryHandler) ServeShare

func (h DirectoryHandler) ServeShare(w http.ResponseWriter, r *http.Request, sr *shareRequest)

ServeShare implements ShareHandler.

type FileSetHandler

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

FileSetHandler serves several unrelated files through a generated index.

func (FileSetHandler) ServeShare

func (h FileSetHandler) ServeShare(w http.ResponseWriter, r *http.Request, sr *shareRequest)

ServeShare implements ShareHandler.

type Gate

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

Gate enforces the optional share password.

A successful unlock is remembered with a signed cookie rather than by storing the password client-side. The signing key is generated per process, so cookies die with the share — which is the same lifetime promise the URL itself makes.

func NewGate

func NewGate(hasher security.Hasher, signer security.Signer, p *pages, logger *slog.Logger) *Gate

NewGate returns a Gate.

func (*Gate) Allow

func (g *Gate) Allow(w http.ResponseWriter, r *http.Request, sr *shareRequest) bool

Allow reports whether the request may proceed to the share content.

When it returns false it has already written the response: the unlock form, or a redirect back to the requested page after a successful unlock.

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

Links builds every URL a share page needs. Centralising this means path escaping is done once, correctly, instead of at each call site.

func NewLinks(token string) Links

NewLinks returns a link builder for a share token.

func (Links) Archive added in v0.2.0

func (l Links) Archive(rel string) string

Archive returns the URL that streams a folder, or a whole multi-file share, as one zip.

func (Links) Breadcrumbs

func (l Links) Breadcrumbs(root, rel string) []Crumb

Breadcrumbs splits a relative path into cumulative links, excluding the final element, which the page renders as plain text.

func (Links) Download

func (l Links) Download(rel string) string

Download returns the URL that streams the bytes as an attachment.

func (Links) Page

func (l Links) Page(rel string) string

Page returns the viewer page for a path relative to the share root.

func (Links) Raw

func (l Links) Raw(rel string) string

Raw returns the URL that streams the bytes inline, with Range support.

func (Links) Root

func (l Links) Root() string

Root is the share's landing URL.

func (Links) Static

func (l Links) Static() string

Static is the URL prefix for the viewer's own assets.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware decorates a handler. Keeping cross-cutting concerns in this shape lets the router compose them in one readable place.

type Options

type Options struct {
	// Addr is the listen address, e.g. "127.0.0.1:0" to pick a free port.
	Addr string
	// Resolver maps URL tokens to shares.
	Resolver sharing.Resolver
	// Guards decide whether a share is still available. Defaults to
	// sharing.DefaultGuards().
	Guards sharing.Guard
	// Hasher verifies share passwords.
	Hasher security.Hasher
	// Signer signs unlock cookies.
	Signer security.Signer
	// Clock supplies the current time. Defaults to the system clock.
	Clock sharing.Clock
	// Detector classifies files for previews.
	Detector preview.Detector
	// Previews renders file previews.
	Previews *preview.Registry
	// Viewer renders HTML pages.
	Viewer *viewer.Renderer
	// Logger receives request and error logs.
	Logger *slog.Logger
	// Checksums works out the SHA-256 shown on file pages. Defaults to a
	// new cache.
	Checksums *checksum.Cache
}

Options configures a Server. Every dependency is an interface so the server can be built against test doubles, and so none of its collaborators need to know they are being used by an HTTP server.

type PathResolver

type PathResolver interface {
	Root() string
	Resolve(rel string) (string, error)
}

PathResolver maps an untrusted relative path to a real file inside a root.

type ProxyHandler

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

ProxyHandler exposes a local HTTP service through a share URL.

It is a thin reverse proxy on purpose: HTTP semantics are preserved end-to-end so WebSockets, server-sent events, streaming responses and range requests all keep working exactly as they do against localhost.

func NewProxyHandler

func NewProxyHandler(p *pages, logger *slog.Logger) *ProxyHandler

NewProxyHandler returns a handler that proxies HTTP shares.

func (*ProxyHandler) ServeShare

func (h *ProxyHandler) ServeShare(w http.ResponseWriter, r *http.Request, sr *shareRequest)

ServeShare implements ShareHandler.

type RootProvider

type RootProvider interface {
	Resolver(spec sharing.Spec) (PathResolver, error)
}

RootProvider hands out the confined resolver for a share. The interface exists so the confinement strategy can be swapped (or stubbed in tests) without touching the handler.

type Server

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

Server owns the listener and the HTTP handler for a set of shares.

func New

func New(opts Options) (*Server, error)

New validates the options and assembles the handler graph.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the bound address, valid after Listen.

func (*Server) Forget

func (s *Server) Forget(shareID string)

Forget releases cached per-share state. Call it when a share is revoked.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the request handler, so the share routes can be mounted elsewhere or exercised directly in tests without binding a port.

func (*Server) Listen

func (s *Server) Listen() error

Listen binds the socket without serving yet.

Binding is separate from serving so the caller can learn the real port before any URL is printed or any tunnel is started — which is what makes "listen on :0" usable.

func (*Server) Serve

func (s *Server) Serve() error

Serve accepts connections until the server is shut down. It calls Listen first if the caller has not already done so.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown stops accepting connections and waits for in-flight requests, up to the deadline carried by ctx.

func (*Server) Warm added in v0.2.0

func (s *Server) Warm(spec sharing.Spec)

Warm starts working out the checksums of a share's files in the background, so a single large file has its fingerprint ready by the time a visitor opens the page. Directory shares are hashed per file on first view instead: hashing a whole tree up front could read gigabytes nobody asks for.

type ShareHandler

type ShareHandler interface {
	ServeShare(w http.ResponseWriter, r *http.Request, sr *shareRequest)
}

ShareHandler serves one kind of share. The router dispatches on sharing.Kind, so support for a new kind means adding an implementation here rather than extending a switch inside an existing handler.

type SingleFileHandler

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

SingleFileHandler serves a share of exactly one file. The file is the share root, so there is nothing to navigate.

func (SingleFileHandler) ServeShare

func (h SingleFileHandler) ServeShare(w http.ResponseWriter, r *http.Request, sr *shareRequest)

ServeShare implements ShareHandler.

Jump to

Keyboard shortcuts

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