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 ¶
- func Chain(h http.Handler, mw ...Middleware) http.Handler
- func SharePath(token string) string
- type Crumb
- type DirectoryHandler
- type FileSetHandler
- type Gate
- type Links
- type Middleware
- type Offer
- type OfferFile
- type Options
- type PathResolver
- type ProxyHandler
- type ReceiveHandler
- type RootProvider
- type Server
- func (s *Server) Addr() string
- func (s *Server) Forget(shareID string)
- func (s *Server) Handler() http.Handler
- func (s *Server) Listen() error
- func (s *Server) Serve() error
- func (s *Server) ServeAtOrigin()
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Warm(spec sharing.Spec)
- type ShareHandler
- type SingleFileHandler
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Crumb ¶
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.
type Links ¶
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 ¶
NewLinks returns a link builder for a share token. The token is the whole path, so a link reads https://host/<token>/ with no extra segment.
func NewRootLinks ¶ added in v0.8.0
func NewRootLinks() Links
NewRootLinks builds links for a share served at the origin itself. A Cloudflare quick tunnel's hostname is already unguessable, so the public link is https://<host> with nothing after it.
func (Links) Archive ¶ added in v0.2.0
Archive returns the URL that streams a folder, or a whole multi-file share, as one zip.
func (Links) Breadcrumbs ¶
Breadcrumbs splits a relative path into cumulative links, excluding the final element, which the page renders as plain text.
type Middleware ¶
Middleware decorates a handler. Keeping cross-cutting concerns in this shape lets the router compose them in one readable place.
type Offer ¶ added in v0.7.0
Offer is a batch of files a visitor asks to send. Nothing is written until the owner accepts it, and then only the files it lists, at the sizes it gave: an upload that was not offered and accepted is refused.
func (*Offer) Accept ¶ added in v0.7.0
func (o *Offer) Accept()
Accept lets the files in. It does nothing once the offer is answered.
func (*Offer) Decided ¶ added in v0.7.0
func (o *Offer) Decided() <-chan struct{}
Decided is closed once the offer is accepted, declined or expires.
func (*Offer) Decline ¶ added in v0.7.0
func (o *Offer) Decline()
Decline refuses the files. It does nothing once the offer is answered.
type OfferFile ¶ added in v0.7.0
type OfferFile struct {
// Name is made safe to print: no path, no control characters.
Name string
Size int64
}
OfferFile is one file in an offer, as the owner is shown it.
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
// OnReceived, when set, is told about every file a receive share has
// taken in completely.
OnReceived func(sharing.Spec, inbox.Received)
// OnOffer, when set, asks the owner whether a batch of files may be
// sent to a receive share; it answers with Offer.Accept or Decline.
// When nil, every batch is accepted.
OnOffer func(sharing.Spec, *Offer)
// AtOrigin serves the single registered share at / as well as under its
// token. A Cloudflare quick tunnel sets this, because the hostname is
// already the secret and the public link has no path.
AtOrigin bool
}
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 ¶
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 ReceiveHandler ¶ added in v0.7.0
type ReceiveHandler struct {
// contains filtered or unexported fields
}
ReceiveHandler serves a receive share: the upload page and the chunked upload API behind it.
func (ReceiveHandler) ServeShare ¶ added in v0.7.0
func (h ReceiveHandler) 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 (*Server) 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 ¶
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 ¶
Serve accepts connections until the server is shut down. It calls Listen first if the caller has not already done so.
func (*Server) ServeAtOrigin ¶ added in v0.8.0
func (s *Server) ServeAtOrigin()
ServeAtOrigin serves the single registered share at / as well as under its token. The CLI calls this once it knows the public link is a Cloudflare quick tunnel, whose hostname is already unguessable.
func (*Server) Shutdown ¶
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
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 {
}
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.