Reference · Tenants
tenant_from
tenant_from(str | fn) -> nullWhat it does
Says how a request's tenant is found, at the top of a program. With a domain,
tenant_from("example.com"), the tenant is the part of the host before it:
acme.example.com is acme. With a function, tenant_from((request) => ...), the
tenant is what the function gives for the request (a header, a path segment, a
lookup), a name or null. A name is lowercase letters, digits, - and _, at most 63,
starting with a letter or a digit; anything else is no tenant. It gives null. See
Many tenants.
Examples
tenant_from("example.com") // acme.example.com is tenant "acme"db.open("data/{tenant}.db") // a SQLite file per tenantdb.migrate()route GET / = <h1>Welcome, {tenant()}</h1>tenant_from((request) => request.headers["x-tenant"])let registry = db.connect("registry.db")db.open((tenant) => registry.one("select url from tenants where name = ?", tenant)?.url)print(tenant_from("example.com"))print(tenant())nullnullEdge cases
- The domain is read without case and without a leading dot:
".Example.COM"isexample.com. It is a bare domain, not a URL: no/or:in it. - Setting the rule gives no tenant to the code at the top of the program:
tenant()there is still null. The rule is applied to each request. - A request whose host does not fit (the bare domain, another domain, a subdomain
that is not a valid name) has no tenant:
tenant()is null anddb.*calls give an error value. A made-up subdomain opens no database. - A function is asked for every request; what it gives is checked as a name, so a value from a header cannot reach a file or database name unchecked.
- The last
tenant_fromcall wins.
print(tenant_from(".Example.COM"), tenant())print(tenant_from((req) => req.headers["x-tenant"]), tenant())null nullnull nullErrors
An empty domain, one with a / or a :, and an argument that is neither a string
nor a function are runtime errors, not error values.
tenant_from("https://example.com/")line 1: `tenant_from` needs a domain such as "example.com", got "https://example.com/"tenant_from(42)line 1: `tenant_from` expects a domain or a function of the request, got intChaining
It stands alone at the top of the program, before db.open. To sign a tenant up from
a request that has none yet, use with_tenant:
tenant_from("example.com")db.open("data/{tenant}.db")route POST /signup { form: { name: str } } { with_tenant(name, () => db.exec("insert into settings (plan) values ('free')")) // makes acme.db redirect(`https://${name}.example.com/`)}See also
tenant, with_tenant, db.open, db.tenants
Thread 0 posts
On tenant_from(): questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.
Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo