quicsql

package module
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: Apache-2.0 Imports: 0 Imported by: 0

README

quicSQL

quicSQL

Docs  ·  Get started  ·  API reference  ·  Config

Go Reference

Network SQLite for every language. quicSQL takes a local SQLite database — a plain file, an in-memory database, or an encrypted-and-compressed vfs/vault container — and turns it into a networked, authenticated, multi-tenant service. It owns each database as one long-lived open handle and fans many network clients into it (the single-owner discipline that makes a vault file safely shareable), speaks two protocols over one handler — a dead-simple native JSON API and the libSQL Hrana pipeline — across the whole transport matrix (HTTP/1.1, cleartext h2c, HTTP/2 over TLS, HTTP/3 over QUIC, and Unix sockets), with authentication, per-database authorization, a control plane, and observability built in. Because it speaks the libSQL wire protocol, the official libSQL SDKs — TypeScript, Python, PHP, Ruby, Rust, Swift, Elixir — connect by URL alone (docs/clients/); anything else can use the plain JSON API. It's built on gosqlite and is pure Go — no CGo, one static binary.

// The SAME "sqlite" driver name opens a local file or a remote database —
// only the DSN scheme changes. Importing the driver registers "sqlite" too.
import _ "quicsql.net/client/sqldriver"

//   sql.Open("sqlite", "file:app.db")   → a local SQLite file
db, _ := sql.Open("sqlite", "quicsql://127.0.0.1:7775/users?transport=h1") // → SQLite via a quicSQL server
db.QueryRowContext(ctx, "SELECT count(*) FROM users").Scan(&n)

Or reach it with nothing but curl — the native JSON endpoint is that thin:

curl -s http://127.0.0.1:7775/users/query -d '{"sql":"SELECT * FROM users WHERE id = ?","args":[7]}'

Existing libSQL / Turso clients work as-is: quicSQL serves the Hrana v2/v3 pipeline and cursor (/<db>/v3/pipeline, /<db>/v3/cursor), including baton-pinned interactive transactions — the official SDKs for TypeScript, Python, PHP, Ruby, Rust, and more point at a quicSQL host by URL alone, verified in CI by examples/clients/.

Why quicSQL

  • 🔐 It networks the databases nothing else can — including encrypted vaults. gosqlite gives you a live, file-backed encrypted + compressed SQLite container (vfs/vault): multi-recipient keyslots, tamper-evident storage, crash-safe key rotation. But such a container is only safe under a single owner — you can't just hand the file to N machines. quicSQL is that owner: it opens the vault once and multiplexes every client through it, so an encrypted database becomes a shared network service without ever weakening what's written to disk. No other SQLite server does this in pure Go.

  • 📦 Batteries included — auth, authz, control plane, observability. Not "SQLite behind an HTTP handler you have to secure yourself." quicSQL ships a real access model: six authentication methods (no-auth, Unix peer credentials, bearer token, HTTP-basic password, mTLS, and an ed25519 challenge/response that reuses the same key that unlocks a vault), a principal → capability authorization layer with per-database grants and read-only enforced in the engine (not by parsing SQL), a /_admin control plane (create / detach / list databases, plus vault maintenance — compact, reclaim, trim, snapshot), a meta store with an audit log, an OpenMetrics /_metrics endpoint, a slow-query log, per-principal rate limits, per-database concurrency caps, and statement / transaction timeouts that interrupt a runaway query.

  • 🌐 Every transport, one handler — up to HTTP/3. The identical http.Handler serves HTTP/1.1, cleartext h2c, HTTP/2 over TLS, HTTP/3 over QUIC, and Unix domain sockets. Put credential methods behind TLS, keep an admin socket local with peer-credential auth, and let mobile/edge clients ride QUIC — same server, same semantics.

  • 🧩 Pure Go, CGo-free, one binary. Because it's built on gosqlite (SQLite transpiled to Go), quicSQL cross-compiles with plain GOOS=… go build, ships as a static distroless/alpine binary with no apk add, and passes go test -race cleanly. No C toolchain in your build or your container.

  • 🔌 Two protocols, both first-class. The native JSON API (POST /<db>/query) is trivial to call from any language, curl, or a shell script — one request, {sql, args} or a statements batch. The Hrana pipeline gives you baton-pinned interactive transactions, batches with step conditions, and compatibility with the existing libSQL client ecosystem. Pick per use case; the server speaks both at once.

Documentation

What you get

  • Every open mode gosqlite has, over the wire — plain files (with a recommended WAL pragma preset), read-only, private and shared in-memory, vfs/mvcc (snapshot isolation) and vfs/memdb, and vfs/vault in every shape: plain, compressed, encrypted, multi-recipient, and authenticated-writer. The server owns pragmas and pool tuning; clients can't reconfigure the connection.
  • Authentication, six ways — none (anonymous), Unix peer credentials (uid → principal), bearer token (hashed, constant-time compared), HTTP-basic password (bcrypt), mTLS client certificate (by subject CN or SPKI), and a stateless ed25519 challenge/response whose signature is bound to the request so a captured signature can't be replayed onto another. A present-but-invalid credential is a 401, never a silent downgrade to anonymous.
  • Authorization in depth — a none < read-only < read-write < admin capability model with per-database and wildcard (*) grants. Read-only isn't a suggestion: a read-only principal runs on a borrowed connection put in PRAGMA query_only plus a write-denying authorizer, so DML, DDL, header writes, and VACUUM are all refused at the engine.
  • The Hrana pipelineexecute / batch / interactive transactions over baton-pinned sessions (one server-side connection per baton), store_sql, and batch step conditions — the libSQL wire protocol, served natively.
  • A native JSON APIPOST /<db>/query with {sql, args} or a statements batch (one explicit transaction, all-or-nothing), integers exact on the wire, blobs boxed as {"base64": …}, results bounded by row/byte caps so a huge SELECT can't OOM the server.
  • A control plane at /_admin — runtime create / detach / list databases (persisted to a meta store and reconciled on restart), vault maintenance (offline compact, online reclaim, trim, encrypted snapshot), introspection (info / stats / sessions / kill), and an audit log — every route gated by a named server-admin (open mode never applies to the control plane).
  • Changesets & blobs over the wire — apply / invert / concat SQLite session changesets, and stream large objects into a blobstore (create / write / read / size / delete) with bounded memory.
  • A Go client + database/sql driverclient speaks every transport (H1 / H2C / H2TLS / H3 / Unix) with Query / Exec / Batch / OpenStream / changeset / blob / export; client/sqldriver registers a database/sql driver so ordinary Go code reaches a remote database by DSN alone. It dispatches under gosqlite's "sqlite" name (change file:app.db to quicsql://host/app and your existing code points at a server — no driver swap), and under an explicit "quicsql" name too.
  • Safety rails/_metrics (OpenMetrics), a params-redacted slow-query log, per-principal rate limiting, per-database concurrency admission caps, and statement / transaction timeouts that interrupt a runaway or disconnected query.

Declarative models over the network: LiteORM

Want an ORM on top? LiteORM — the declarative, CGo-free SQLite data layer built on gosqlite — runs over quicSQL unchanged. Its sqlite.Open selects local or remote by DSN shape, so the same models, migrations, and queries that hit a local file hit a quicSQL server the moment you point them at a quicsql:// URL:

import (
	"liteorm.org/dialect/sqlite"
	"liteorm.org/orm"
	_ "quicsql.net/client/sqldriver" // registers the quicsql:// scheme
)

// A local file in dev, a quicSQL server in prod — only the DSN changes:
db, _ := sqlite.Open("quicsql://127.0.0.1:7777/app?transport=h2&token=…")
defer db.Close()
orm.AutoMigrate[User](ctx, db) // runs the DDL on the server
  • Same models, local or remote. Declare once; the full ORM and query builder — statements, SAVEPOINT-nested transactions, schema introspection, additive AutoMigrate — execute as SQL on the server, and SQLite constraint violations come back as typed liteorm errors.
  • Native search, executed server-side. LiteORM's typed vector, full-text, and hybrid (RRF) search (search.For[T](db).Vector / .FullText / .Hybrid) run as SQL against the server's vec0 / fts5 sidecars — declarative model tags, ranked results, no hand-written KNN. (The server needs vec0 registered; fts5 is built in.)
  • Changesets & large objects over the wire. SQLite session changesets (capture / apply / invert / concat) drive the SESSION extension server-side; large objects transfer whole.
  • mTLS / keyring auth. For credentials a DSN can't carry, build a *client.Client, hand it to sqldriver.OpenConnectorClient, and sqlite.WrapDB the resulting *sql.DB.

LiteORM is a separate module (liteorm.org), so quicSQL's own dependencies stay lean.

How it compares

The "SQLite over a network" landscape is small, and each entry makes a different bet. Where quicSQL sits:

Capability quicSQL libSQL sqld rqlite ws4sql
Works with the existing libSQL SDKs (TS, Python, PHP, Ruby, Rust, …)
Pure Go, CGo-free, static binary ✗ (Rust) ✗ (CGo driver) ✗ (CGo driver)
libSQL Hrana protocol
Simple JSON-over-HTTP API
HTTP/3 (QUIC) transport
Unix socket + peer-credential auth
Built-in auth (mTLS, bearer, ed25519, password) partial (token) ✓ (basic/mTLS) partial
Per-database capability authz, read-only enforced in-engine partial
Encrypted + compressed database, served live in place ✓ (vfs/vault) encryption only
Multi-recipient / tamper-evident storage
Runtime control plane (create / detach / maintenance) + audit partial
Declarative ORM with native vector / FTS / hybrid search over the wire (via LiteORM)
Distributed replication / Raft consensus ✓ (Turso)

Better here: it's the only pure-Go option that speaks Hrana and a plain JSON API, serves the full transport matrix up to HTTP/3, bakes in a real auth + per-database authorization model with read-only enforced at the engine, and — uniquely — serves an encrypted, compressed, multi-recipient vault container live and in place, safe because the server enforces single-ownership. And because it's built on gosqlite, LiteORM runs over it: a declarative ORM with native vector / full-text / hybrid search over the wire, which no other SQLite server offers. One static binary carries all of it.

The trade-off is deliberate: quicSQL is a single-owner multiplexer, not a replicated cluster. If you need Raft consensus and multi-node failover, rqlite and Turso are built for that; quicSQL is built to make one powerful SQLite database — especially an encrypted vault — safely and richly network-accessible. (Nothing stops you from running it behind your own replication or failover; it just doesn't ship consensus in the box.)

Quick start

1. Run the daemon with a YAML config — one listener per transport, a few databases, auth optional:

# quicsql.yaml
server:
  data_dir: ./data
secrets:
  - {name: keys, type: file, dir: ./data/keys}     # a "keys:<name>" reference reads ./data/keys/<name>
tls:
  dev: {mode: self_signed, hosts: [localhost, 127.0.0.1]}   # use mode: files in production
listeners:
  - {name: h1,   transport: h1,   address: 127.0.0.1:7775}
  - {name: h2,   transport: h2,   address: 127.0.0.1:7777, tls: dev}
  - {name: h3,   transport: h3,   address: 127.0.0.1:7777, tls: dev}   # HTTP/3 over QUIC — shares the h2 port (UDP vs TCP)
  - {name: unix, transport: unix, address: ./data/quicsql.sock, socket_mode: "0600"}
databases:
  - {name: users,  backend: file, path: users.db, mode: rwc, pragmas_preset: recommended}
  - name: orders                                   # encrypted + compressed at rest
    backend: vault
    path: orders.vault
    vault: {compression: default, cipher: adiantum, key: keys:orders}
quicsql --config quicsql.yaml

With no principals or grants, the server is in open mode (every caller is read-write — bind to loopback). Add a principal, a grant, and a listener auth: list to lock it down; see auth & authz.

2. Talk to it — from Go, over any transport:

import "quicsql.net/client"

c := client.H1("127.0.0.1:7775")                       // or H2TLS / H3 / Unix, with client.WithBearer(…) etc.
defer c.Close()

res, _ := c.Query(ctx, "users", "SELECT name FROM users WHERE id = ?", 7)

// An interactive transaction over the Hrana pipeline (one pinned connection,
// driven by SQL — BEGIN/COMMIT are statements; args are passed as an []any):
tx := c.OpenStream("bank")
defer tx.Close(ctx)
tx.Exec(ctx, "BEGIN", nil)
tx.Exec(ctx, "UPDATE accounts SET balance = balance - ? WHERE id = ?", []any{100, 1})
tx.Exec(ctx, "UPDATE accounts SET balance = balance + ? WHERE id = ?", []any{100, 2})
tx.Exec(ctx, "COMMIT", nil)

...or through database/sql (import _ "quicsql.net/client/sqldriver"), or with curl, or with any libSQL SDK pointed at the Hrana endpoint.

3. Embed itserverd.Run assembles the whole pipeline in-process (custom SQL functions, tests, a bundled server):

import "quicsql.net/serverd"

inst, _ := serverd.Run(cfg, log)   // cfg is a *config.Config; returns an *Instance
defer inst.Shutdown(ctx)

Transports & protocols

One http.Handler is served on every wire; pick per listener.

Transport Config transport: Typical use
HTTP/1.1 h1 the simplest client, curl, loopback
Cleartext HTTP/2 h2c in-cluster, multiplexed, no TLS
HTTP/2 over TLS h2 the deployed shape for credentialed clients
HTTP/3 over QUIC h3 mobile / edge / lossy networks
Unix domain socket unix local admin, peer-credential auth

Endpoints on each: POST /<db>/query (native JSON), /<db>/v3/pipeline (Hrana), /<db>/export, /<db>/changeset/*, /<db>/blob/*, plus server-scoped /_health, /_metrics, /_admin/*, and /_auth/challenge. The canonical port is 7775 (h1); the sequence continues h2c 7776, h2 7777, and h3 shares 7777 (QUIC/UDP alongside h2's TLS/TCP, the way HTTPS shares :443 — set the h3 listener's advertise: true to emit Alt-Svc so clients auto-upgrade).

Packages

Import path What it gives you
quicsql.net/serverd serverd.Run(cfg, log) → *Instance — assemble the whole server in-process; Shutdown(ctx)
quicsql.net/config the YAML config surface — Load(path) + Validate() (one source of truth for the vocabulary)
quicsql.net/client the Go client: H1 / H2C / H2TLS / H3 / Unix + Query / Exec / Batch / OpenStream / changeset / blob / export
quicsql.net/client/sqldriver a database/sql driver for the quicsql:// DSN, under both the "sqlite" and "quicsql" names — a remote database opened like a local one
quicsql.net/backend maps a configured database to a concrete open (file / memory / vault / mvcc / memdb)
quicsql.net/auth · quicsql.net/authz authenticate a request → principal; principal → per-database capability
quicsql.net/registry the single-owner handle registry — one open *sqlite.DB per database, ref-counted
quicsql.net/httpapi the transport-neutral HTTP surface (native + Hrana + export/changeset/blob)
quicsql.net/admin the /_admin control plane (create / detach / list, vault maintenance, introspection)
cmd/quicsql the standalone daemon (quicsql --config quicsql.yaml)

Examples

Runnable, smoke-tested programs under examples/:

  • demo — one program that starts an in-process server with three databases (a WAL file, an encrypted+compressed vault, a shared in-memory database) across every transport, runs real operations against each, drives a Hrana interactive transaction, and benchmarks throughput per protocol (req/s, p50/p99). Zero setup: go run ./examples/demo.
  • auth — the full authentication + authorization matrix, every method and every level, with success and denial paths, exiting non-zero if any expectation fails (so it doubles as a smoke test). go run ./examples/auth (cleartext) or -tls.

just demo, just auth-demo, just auth-demo-tls, and just showcase run them; see the examples README.

Development

just recipes drive everything: just (build + test + lint), just test, just test-race, just lint, just demo, just ci. The underlying commands are vanilla go build ./... / go test ./.... Architecture, the fragile invariants (single-owner handles, baton binding, read-only-in-depth, open-mode rules), and conventions live in AGENTS.md.

quicSQL is co-developed with gosqlite: during development its go.mod resolves gosqlite.org (and vfs/vault, vfs/crypto, crypto/keyring, blobstore) from the sibling checkout via replace directives; a real release pins published versions.

Supported Go

The two most recent Go releases (the pin lives in go.mod). gopls modernize is enforced in CI, so modern idioms are expected.

Acknowledgements

  • gosqlite — the CGo-free SQLite engine quicSQL is built on; the vfs/vault container, crypto/keyring, and blobstore that make encrypted, multi-recipient, networked databases possible.
  • libSQL / Turso — the Hrana wire protocol quicSQL implements, so the existing libSQL client ecosystem works unchanged.

Documentation

Overview

Package quicsql is the quicSQL server: a SQLite network server / multiplexer that owns local databases (plain files, in-memory, and vfs/vault containers) and fans many network clients into ONE long-lived open handle per database — the single-owner discipline that makes a vault file safely shareable.

quicSQL is its own module, quicsql.net, built on gosqlite (gosqlite.org) — the CGo-free SQLite engine it embeds. During co-development it resolves gosqlite from the sibling checkout via the replaces in go.mod.

Live today (Phases 0-7): the config/backend/registry/engine core, the native-JSON and libSQL Hrana protocols (execute/batch/interactive transactions over baton sessions), the full transport matrix — HTTP/1.1, cleartext h2c, h2 over TLS, HTTP/3 over QUIC, and Unix sockets, all serving one http.Handler — authentication + authorization (a principal/capability model with per-database grants and read-only enforced in depth, across no-auth, Unix peer credentials, bearer token, HTTP-basic password, mTLS, and an ed25519 challenge/response reusing crypto/keyring), every open mode through config (plain file, read-only, private and shared in-memory, vfs/mvcc and vfs/memdb, and vfs/vault plain / compressed / encrypted / multi-recipient / authenticated-writer), a control plane at /_admin (runtime create / detach / list databases and vault maintenance — offline compact, online reclaim, trim, snapshot — with a meta store and audit log), and observability + safety rails: a /_metrics OpenMetrics endpoint, /_admin introspection (info / stats / sessions / kill), a slow-query log (driver TraceProfile, params redacted by default — logging.expand_params opts into expanded SQL), a per-principal rate limit and per-database concurrency cap, and statement / transaction timeouts that interrupt a runaway or disconnected query.

Directories

Path Synopsis
Package admin is the control plane: the /_admin HTTP surface for runtime database lifecycle (create / detach / list) and vault maintenance (offline compact, online reclaim, snapshot).
Package admin is the control plane: the /_admin HTTP surface for runtime database lifecycle (create / detach / list) and vault maintenance (offline compact, online reclaim, snapshot).
Package auth authenticates a request into an authz.Principal.
Package auth authenticates a request into an authz.Principal.
Package authz is the principal + capability model: it maps an authenticated principal to a per-database access Level.
Package authz is the principal + capability model: it maps an authenticated principal to a per-database access Level.
Package backend maps a configured database to a concrete open: each backend knows how to build a sqlite.Config (and, for vault, vault.Options) and open the single shared handle the registry fans clients through.
Package backend maps a configured database to a concrete open: each backend knows how to build a sqlite.Config (and, for vault, vault.Options) and open the single shared handle the registry fans clients through.
Package client is a small Go client for the quicSQL native-JSON API (POST /<db>/query).
Package client is a small Go client for the quicSQL native-JSON API (POST /<db>/query).
sqldriver
Package sqldriver registers a database/sql driver named "quicsql" that speaks to a quicSQL server, so ordinary database/sql code connects to a remote database the same way it opens a local one:
Package sqldriver registers a database/sql driver named "quicsql" that speaks to a quicSQL server, so ordinary database/sql code connects to a remote database the same way it opens a local one:
cmd
quicsql command
Command quicsql is the quicSQL server daemon.
Command quicsql is the quicSQL server daemon.
Package config is the typed, YAML-backed configuration surface for the quicSQL server.
Package config is the typed, YAML-backed configuration surface for the quicSQL server.
Package engine runs statements against a database handle and encodes results into the transport-agnostic Value/Result shape shared by every protocol.
Package engine runs statements against a database handle and encodes results into the transport-agnostic Value/Result shape shared by every protocol.
examples
auth command
Command auth is a runnable demonstration of every quicSQL authentication method and every authorization level.
Command auth is a runnable demonstration of every quicSQL authentication method and every authorization level.
charged-server command
Command quicsql-charged-server is a deployable, fully-charged quicSQL server: an encrypted + compressed vault database, a plain file DB and a shared in-memory DB; the standard extension bundle plus a custom server-registered SQL function; every auth method and authz level; TLS h2 + HTTP/3 as the primary secure transports (with cleartext h1/h2c and a Unix socket as dev extras); the control plane; rate/concurrency limits; a slow-query log; and a vault-backed meta store.
Command quicsql-charged-server is a deployable, fully-charged quicSQL server: an encrypted + compressed vault database, a plain file DB and a shared in-memory DB; the standard extension bundle plus a custom server-registered SQL function; every auth method and authz level; TLS h2 + HTTP/3 as the primary secure transports (with cleartext h1/h2c and a Unix socket as dev extras); the control plane; rate/concurrency limits; a slow-query log; and a vault-backed meta store.
demo command
Command demo is a fully self-contained, runnable quicSQL example: it starts an in-process server (via serverd) with several databases across every transport, runs real-life operations against each database through the Go client, shows a Hrana interactive transaction, and then benchmarks request throughput (RPS / RPM) on each protocol.
Command demo is a fully self-contained, runnable quicSQL example: it starts an in-process server (via serverd) with several databases across every transport, runs real-life operations against each database through the Go client, shows a Hrana interactive transaction, and then benchmarks request throughput (RPS / RPM) on each protocol.
internal/showcase
Package showcase holds the fixed DEV credentials shared by the charged-server and the remote-tour examples.
Package showcase holds the fixed DEV credentials shared by the charged-server and the remote-tour examples.
remote-tour command
Command remote-tour is a pure remote client that walks every quicSQL-reachable feature against a charged server, over TLS with mTLS.
Command remote-tour is a pure remote client that walks every quicSQL-reachable feature against a charged server, over TLS with mTLS.
Package extensions is the quicSQL server's standard extension bundle.
Package extensions is the quicSQL server's standard extension bundle.
Package httpapi is the transport-neutral HTTP surface for quicSQL.
Package httpapi is the transport-neutral HTTP surface for quicSQL.
internal
httpjson
Package httpjson writes the server's uniform JSON responses and error envelopes.
Package httpjson writes the server's uniform JSON responses and error envelopes.
raceskip
Package raceskip exposes a single Enabled bool constant whose value reflects whether the build was produced with -race.
Package raceskip exposes a single Enabled bool constant whose value reflects whether the build was produced with -race.
Package limits enforces the runtime safety rails that bound one client's or one database's share of the server: a per-principal request rate limit (token bucket) and a per-database concurrency cap (so one hot database can't starve the others).
Package limits enforces the runtime safety rails that bound one client's or one database's share of the server: a per-principal request rate limit (token bucket) and a per-database concurrency cap (so one hot database can't starve the others).
Package meta is the server-owned meta store: a small SQLite database (a vault container by default, so it can be encrypted at rest) under data_dir that records runtime state the YAML config cannot — the databases created through the control plane, and the admin audit log.
Package meta is the server-owned meta store: a small SQLite database (a vault container by default, so it can be encrypted at rest) under data_dir that records runtime state the YAML config cannot — the databases created through the control plane, and the admin audit log.
Package obs is the observability seam.
Package obs is the observability seam.
Package registry owns exactly ONE open handle per logical database and fans every session through it — the single-owner invariant that makes a vault file safely shareable.
Package registry owns exactly ONE open handle per logical database and fans every session through it — the single-owner invariant that makes a vault file safely shareable.
Package secret resolves "source:name" references to key material.
Package secret resolves "source:name" references to key material.
Package serverd assembles and runs a quicSQL server from a validated config: secrets → meta store → reconcile (config ∪ meta) → backends → registry (warm, fail-fast) → sessions → auth/authz → metrics + limiter → HTTP handler → transports.
Package serverd assembles and runs a quicSQL server from a validated config: secrets → meta store → reconcile (config ∪ meta) → backends → registry (warm, fail-fast) → sessions → auth/authz → metrics + limiter → HTTP handler → transports.
Package session implements Hrana's interactive-transaction streams: a Session pins one *sql.Conn for the life of a BEGIN…COMMIT spanning multiple pipeline requests, addressed by an unforgeable, server-signed *baton*.
Package session implements Hrana's interactive-transaction streams: a Session pins one *sql.Conn for the life of a BEGIN…COMMIT spanning multiple pipeline requests, addressed by an unforgeable, server-signed *baton*.
Package transport starts the quicSQL HTTP handler on every wire — HTTP/1.1, cleartext HTTP/2 (h2c), HTTP/2 over TLS, HTTP/3 over QUIC, and Unix sockets — all serving the identical http.Handler.
Package transport starts the quicSQL HTTP handler on every wire — HTTP/1.1, cleartext HTTP/2 (h2c), HTTP/2 over TLS, HTTP/3 over QUIC, and Unix sockets — all serving the identical http.Handler.

Jump to

Keyboard shortcuts

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