Documentation
¶
Index ¶
Constants ¶
const ShutdownBudget = 3 * time.Second
ShutdownBudget is how long graceful shutdown may take. main.go uses it for its shutdown context, and sseWriteDeadline is defined strictly under it, so the two cannot drift apart into a shutdown that always force-closes.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Hooks ¶ added in v1.3.0
type Hooks struct {
// Confirm replaces the native read-permission dialog. Nil uses the real one.
//
// allowTrust reports whether the dialog may offer to trust the folder
// durably. The app decides it from its refusal rules BEFORE the dialog is
// drawn, so a folder that could never be trusted is never offered; the
// button used to be drawn always and the refusal arrived afterwards as a
// notification, which asked the user for a choice that could not be honored.
Confirm func(title, message string, allowTrust bool) (platform.ConfirmChoice, error)
// TrustedCovers reports whether absPath sits inside a DECLARED trusted
// folder. It is the config fact, not this site's runtime roots: a file can
// belong to a trusted folder this site holds no root for, and answering from
// the roots is exactly what made a folder declared below an already-open
// site grant nothing at all. It must not touch the filesystem; see
// shouldAutoRegister for why the ordering there is load-bearing.
TrustedCovers func(absPath string) bool
// TrustedLive is the same question with the identity pin applied: is absPath
// inside a trusted folder that is still the folder that was trusted? A folder
// deleted and recreated still covers lexically but is no longer live, and the
// two must not be confused. TrustedCovers is the gate on whether to TRY
// auto-registering, and answers from memory; this one is the standing
// capability, and stats. Only handleTrustRequest asks it, on the file its own
// token was minted for, so the stat reveals nothing a caller did not know.
TrustedLive func(absPath string) bool
// Route registers absPath through the app and reports where it serves, so
// this site can redirect when the registration landed on another origin.
// Trusted-folder auto-registration is its only caller, and the app refuses
// anything that does not anchor at a live trusted folder.
Route func(absPath string) (url string, ok bool)
// MayTrustFolder gates Confirm's allowTrust for a candidate folder.
MayTrustFolder func(dir string) bool
// TrustFolder is the durable half of the read prompt's "Trust this folder"
// choice. The folder there is one the PAGE steered, by choosing which
// out-of-scope assets to request, so the app applies its stricter refusal
// rule behind this.
TrustFolder func(dir string) error
// TrustRequest is the one door for "trust this file's folder". Both routes
// into it name a FILE the server already vouches for, never a folder: the
// banner's nonce resolves to the descriptor that was served, and the JSON
// route's token to a registration. openedByUser is false when the file was
// reached by a link, and the dialog says so on its first line.
TrustRequest func(requestingFile string, openedByUser bool) (url string, ok bool)
}
Hooks are the decisions a site's server cannot make for itself. Each one needs the declared trusted-folder list, the app's site registry, or a native dialog, and the server imports none of those.
Wiring them as one struct at construction makes the whole app-to-server contract a single declaration that can be read from either end. As five separate setters mutating a live server, it could only be reconstructed by grepping, and two of them had to take the broker's lock because they could be called at any moment.
A nil field disables that route, which is what a standalone server (every server test) wants.
type LiveSync ¶ added in v1.2.0
type LiveSync struct {
// contains filtered or unexported fields
}
LiveSync bundles the process-wide live-sync machinery: the pub/sub hub, the file watcher, and the coordinator that keeps their membership in step. One LiveSync is shared by every per-tree site. It keys all state by absolute file path, and absolute paths are unique across the single home directory, so sharing one instance never collides between sites.
func NewLiveSync ¶ added in v1.2.0
NewLiveSync builds the shared live-sync runtime. seqPath is the persisted sequence high-water mark, which lives beside the backups in a private 0700 directory the server refuses to serve.
func (*LiveSync) DropSubscribers ¶ added in v1.3.0
DropSubscribers closes every SSE stream for path, across every site. Used by revocation: a live stream resolved its *session.File once and would otherwise loop forever after the registration died. Each stopped stream unwinds through its handler's deferred coordinator remove, which drops the watcher reference and hub membership idempotently — teardown by eviction, not a second bookkeeping path.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
func New ¶
func New(ln net.Listener, sessions *session.Manager, logger *logging.Logger, store *versions.Store) *Server
New builds a server that owns its own live-sync runtime and tears it down on Shutdown/Close. Used by tests and any single-server caller.
func NewWithLiveSync ¶ added in v1.2.0
func NewWithLiveSync(ln net.Listener, sessions *session.Manager, logger *logging.Logger, store *versions.Store, ls *LiveSync) *Server
NewWithLiveSync builds a server that shares an injected live-sync runtime with its sibling sites. The runtime is owned by the process, not by any one server, so Shutdown/Close leave it running; the process shuts it down once.
func (*Server) SetHooks ¶ added in v1.3.0
SetHooks wires the app behind this server. Call once, before Start.
func (*Server) SetInternalDir ¶ added in v1.2.0
SetInternalDir marks a directory the server must never serve, whatever the read roots say. htmlclay's own config tree holds its log and settings, and a grant that happens to cover that directory must not turn into a read path. Denying on the serve path is structural; a grant-time guard can only ever cover the grants it happens to see.
func (*Server) SetSiteLabel ¶ added in v1.2.0
SetSiteLabel names this site in the permission dialog so the user knows which page is asking. Optional; the broker falls back to a generic label.
func (*Server) Shutdown ¶
Shutdown releases parked permission requests and closes every SSE stream before handing off to http.Server.Shutdown. Both otherwise hold graceful shutdown open until its timeout and are then force-closed. A server that shares an injected live-sync runtime leaves it running (the process shuts the shared runtime down once, before the per-site HTTP servers).