Keep the empty host when the db_url path starts with //
check / check (push) Waiting to run

defaultDBURL kept the empty host only when state_dir started with //,
but SQLite reads the path written into the URL, state_dir followed by
/state.sqlite3. For a state_dir of / that path is //state.sqlite3, the
URL started file:// and SQLite read state.sqlite3 as a host, so pixa
failed to start. The decision now looks at that path: a state_dir of
/ gives file:////state.sqlite3. Every other state_dir gives the same
URL as before.

Model: opus-5-5
This commit is contained in:
2026-10-16 02:28:59 +00:00
parent 339c149a4e
commit 78fe6957de
3 changed files with 24 additions and 20 deletions
+7 -7
View File
@@ -726,13 +726,13 @@ Key settings in more detail:
- `db_url` — the SQLite database to open; omitted, it is - `db_url` — the SQLite database to open; omitted, it is
`file:<state_dir>/state.sqlite3?_pragma=journal_mode(WAL)`, which keeps the `file:<state_dir>/state.sqlite3?_pragma=journal_mode(WAL)`, which keeps the
database in WAL mode. `state_dir` is percent-encoded in it, so a `%`, `?` or database in WAL mode. `state_dir` is percent-encoded in it, so a `%`, `?` or
`#` in the name is written as `%25`, `%3F` or `%23`. For a `state_dir` `#` in the name is written as `%25`, `%3F` or `%23`. For a `state_dir` of `/`
starting with `//` it starts `file:////`, so SQLite does not read the first or one starting with `//` it starts `file:////`, so SQLite does not read the
directory name as a host. pixa opens one connection to it, so its own reads first name in the path as a host. pixa opens one connection to it, so its own
and writes run one at a time. pixa adds `_pragma=busy_timeout(5000)` to any reads and writes run one at a time. pixa adds `_pragma=busy_timeout(5000)` to
`db_url`, so a write that finds another program writing to the file waits up any `db_url`, so a write that finds another program writing to the file waits
to five seconds for it instead of failing. WAL mode comes only from the URL: up to five seconds for it instead of failing. WAL mode comes only from the
keep `_pragma=journal_mode(WAL)` in one you set URL: keep `_pragma=journal_mode(WAL)` in one you set
- `cache_max_bytes` — disk cache size limit in bytes; `0` disables the disk - `cache_max_bytes` — disk cache size limit in bytes; `0` disables the disk
cache entirely; omitted defaults to 75% of the sum of the free space on the cache entirely; omitted defaults to 75% of the sum of the free space on the
filesystem containing `<state_dir>/cache/` and the bytes of source and filesystem containing `<state_dir>/cache/` and the bytes of source and
+8 -8
View File
@@ -30,6 +30,14 @@ P2: security: per-origin rate limiting
# Completed Steps # Completed Steps
- 2026-10-16 a `state_dir` whose name holds `%`, `?` or `#` keeps its database
at `state.sqlite3` in that directory (closes #290): the `db_url` derived from
it put the name into a `file:` URL as it was, so SQLite read `%41` as `A`, a
`?` or `#` ended the path early, and the journal mode parameter was lost. The
derived `db_url` is now built with Go's `net/url`, which writes those
characters as `%25`, `%3F` and `%23`. For a `state_dir` of `/` or one starting
with `//` it starts `file:////`, so SQLite no longer reads the first name in
the path as a host.
- 2026-10-16 a size with one side `0` keeps the side computed from the source's - 2026-10-16 a size with one side `0` keeps the side computed from the source's
proportions at 1 or more (closes #283): it was rounded down, so for a thin proportions at 1 or more (closes #283): it was rounded down, so for a thin
source it came out at 0, and libvips then made the size square. An 8192x1 source it came out at 0, and libvips then made the size square. An 8192x1
@@ -62,14 +70,6 @@ P2: security: per-origin rate limiting
another way, such as with `%2F` in the path, whatever else the path holds, or another way, such as with `%2F` in the path, whatever else the path holds, or
with a user name and password. It also answers 400 for a source path holding a with a user name and password. It also answers 400 for a source path holding a
`..` segment, as `/v1/image/` refuses one. `..` segment, as `/v1/image/` refuses one.
- 2026-10-16 a `state_dir` whose name holds `%`, `?` or `#` keeps its database
at `state.sqlite3` in that directory (closes #290): the `db_url` derived from
it put the name into a `file:` URL as it was, so SQLite read `%41` as `A`, a
`?` or `#` ended the path early, and the journal mode parameter was lost. The
derived `db_url` is now built with Go's `net/url`, which writes those
characters as `%25`, `%3F` and `%23`. For a `state_dir` starting with `//` it
starts `file:////`, so SQLite no longer reads the first directory name as a
host.
- 2026-10-15 a thin source requested with `fit=cover` no longer makes libvips - 2026-10-15 a thin source requested with `fit=cover` no longer makes libvips
build a huge image (closes #282): libvips' thumbnail scaled the whole source build a huge image (closes #282): libvips' thumbnail scaled the whole source
to cover the requested size and copied that into memory before it cut out the to cover the requested size and copied that into memory before it cut out the
+9 -5
View File
@@ -359,14 +359,18 @@ func newFromSmartConfig(sc *smartconfig.Config) (*Config, error) {
// the directory name, which SQLite decodes back, so the URL names exactly // the directory name, which SQLite decodes back, so the URL names exactly
// this file. OmitHost writes file:/var/lib/pixa/... instead of // this file. OmitHost writes file:/var/lib/pixa/... instead of
// file:///var/lib/pixa/..., and keeps a relative stateDir from being read // file:///var/lib/pixa/..., and keeps a relative stateDir from being read
// as a host name. A stateDir starting with // keeps the empty host, so the // as a host name. The path written into the URL is stateDir followed by
// URL starts file://// and SQLite does not read the first directory name // /state.sqlite3; when it starts with //, as it does for a stateDir of /
// as a host. // or one starting with //, the empty host is kept, so the URL starts
// file://// and SQLite does not read the first name in the path as a
// host.
func defaultDBURL(stateDir string) string { func defaultDBURL(stateDir string) string {
dbPath := stateDir + "/state.sqlite3"
dbURL := url.URL{ dbURL := url.URL{
Scheme: "file", Scheme: "file",
OmitHost: !strings.HasPrefix(stateDir, "//"), OmitHost: !strings.HasPrefix(dbPath, "//"),
Path: stateDir + "/state.sqlite3", Path: dbPath,
RawQuery: "_pragma=journal_mode(WAL)", RawQuery: "_pragma=journal_mode(WAL)",
} }