Documentation
¶
Overview ¶
Package basepath serves filex under a path prefix — a "sub-path deployment", `https://example.com/filex/` behind a reverse proxy — and answers, for the code that builds browser-facing URLs, "what is this install's base?".
The contract (docs/DEPLOYMENT.md, "Serving filex under a sub-path") ¶
The reverse proxy passes the FULL path. A browser asks for `/filex/api/files/manager`, filex receives `/filex/api/files/manager`, and this package takes `/filex` off before the router sees the request, so every route, middleware and handler keeps reading the paths it always read (`/api/...`, `/admin/...`, `/dav/...`). A proxy that strips the prefix (Caddy's `handle_path`, nginx `proxy_pass http://filex/;` with a trailing slash) is NOT supported: filex could not tell a stripped `/api/x` from a request that never went through the proxy, which is exactly the path confusion a prefix must not open.
What stays outside the base ¶
Nothing reaches a handler from outside the base, with one exception: `/healthz`. It answers both at `<base>/healthz` and at the root, because the container images bake `wget http://127.0.0.1:5212/healthz` into their HEALTHCHECK and an orchestrator probes the pod directly, without the proxy. It carries no data and no credential, so answering it twice opens nothing.
Where the base lives at request time ¶
On the request's context (With / From). The router's first own middleware puts it there, so a handler that builds a redirect, an HTML link or a cookie path reads it with no wiring of its own — and a handler test that builds a request without it gets the root deployment, which is what it always measured.
Index ¶
- func CookiePath(ctx context.Context) string
- func From(ctx context.Context) string
- func FromURL(raw string) (string, error)
- func Middleware(base string) func(http.Handler) http.Handler
- func Normalize(raw string) (string, error)
- func Path(ctx context.Context, p string) string
- func Strip(base, p string) (string, bool)
- func With(ctx context.Context, base string) context.Context
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CookiePath ¶
CookiePath is the Path attribute for a cookie filex sets: the base, or "/" at the root. A cookie scoped to the base is not sent to the other applications on the same host.
func FromURL ¶
FromURL returns the normalized path of an absolute URL, "" when it has none.
A trailing slash is forgiven here and not in Normalize: `FILEX_PUBLIC_URL` has always been accepted as `https://example.com/` and trimmed, and the same URL with a path (`https://example.com/filex/`) is the same address. A string that is not an absolute URL has no path to offer and yields "".
func Middleware ¶
Middleware serves the router under base. With base "" it returns next itself: the root deployment runs exactly the code it ran before this package existed.
Under a base:
- `<base>/…` has the base taken off the path (and the escaped path) and the base put on the context, then goes on;
- `<base>` itself is a directory, like `/admin`: a 301 to `<base>/`;
- `/healthz` goes on unchanged (see the package comment);
- anything else is a plain 404, before any handler, cookie or auth chain.
⚠ When the escaped path is set (the client percent-encoded something), it has to carry the base LITERALLY as well. The router routes on the escaped path when there is one, so a request whose decoded path starts with the base while its escaped path does not (`/fil%65x/…`, `/filex%2Fapi/…`) would have the two halves disagree about where the prefix ends. Such a request is refused rather than guessed at.
func Normalize ¶
Normalize validates a configured base path and returns it in canonical form: "" for the root, otherwise "/seg[/seg…]" with no trailing slash.
⚠ Deliberately strict, because the value ends up in every redirect, cookie path and link filex hands out:
- it must start with "/" (a relative base has nothing to be relative to);
- it must NOT end with "/" — `/filex/` and `/filex` would otherwise be two spellings of one base, and a cookie scoped to one does not always match the other;
- no empty, "." or ".." segment — a base that climbs out of itself is a path-confusion hole, not a prefix;
- segments use only the URL's unreserved characters (letters, digits and `- . _ ~`). Anything else would need percent-encoding, and then the escaped path the browser sends and the decoded path the router reads start differently, which is where a prefix check can be talked past.
"" and "/" both mean the root.
func Path ¶
Path returns p (an absolute application path such as "/admin/") as the browser has to ask for it: with the base in front.
⚠ For what the BROWSER resolves — a Location header, a link or a form in a page the server renders, the target of a bounce. A relative URL inside a JSON answer (`thumb_url`, a `/z/` ticket) stays relative to the server root: its reader joins it with its own API base, which already carries the prefix and which a proxying embed may have mapped somewhere else entirely.
Types ¶
This section is empty.