Escape state_dir in the db_url derived from it (closes #290)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The derived db_url put state_dir into a file: URL as it was, so SQLite decoded a %HH in the name and ended the path at a ? or #, and the journal mode parameter was lost. It is now built with net/url, which percent-encodes the directory name; SQLite decodes it back and opens state.sqlite3 in that directory. OmitHost keeps the usual form file:/var/lib/pixa/state.sqlite3 and a relative state_dir a path. Model: opus-5-5
This commit is contained in:
@@ -693,11 +693,13 @@ Key settings in more detail:
|
|||||||
- `signing_key` — HMAC secret for URL signatures
|
- `signing_key` — HMAC secret for URL signatures
|
||||||
- `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. pixa opens one connection to it, so its own reads and
|
database in WAL mode. `state_dir` is percent-encoded in it, so a `%`, `?` or
|
||||||
writes run one at a time. pixa adds `_pragma=busy_timeout(5000)` to any
|
`#` in the name is written as `%25`, `%3F` or `%23`. pixa opens one connection
|
||||||
`db_url`, so a write that finds another program writing to the file waits up
|
to it, so its own reads and writes run one at a time. pixa adds
|
||||||
to five seconds for it instead of failing. WAL mode comes only from the URL:
|
`_pragma=busy_timeout(5000)` to any `db_url`, so a write that finds another
|
||||||
keep `_pragma=journal_mode(WAL)` in one you set
|
program writing to the file waits up to five seconds for it instead of
|
||||||
|
failing. WAL mode comes only from the 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
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ 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`.
|
||||||
- 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
|
||||||
|
|||||||
@@ -338,8 +338,19 @@ func newFromSmartConfig(sc *smartconfig.Config) (*Config, error) {
|
|||||||
settingName(keyDBURL), errValueEmpty)
|
settingName(keyDBURL), errValueEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The driver sets the journal mode only through a _pragma parameter.
|
// The driver sets the journal mode only through a _pragma
|
||||||
c.DBURL = fmt.Sprintf("file:%s/state.sqlite3?_pragma=journal_mode(WAL)", c.StateDir)
|
// parameter. String() percent-encodes any %, ? or # in the
|
||||||
|
// directory name, which SQLite decodes back, so the URL names
|
||||||
|
// exactly this file. OmitHost writes file:/var/lib/pixa/...
|
||||||
|
// instead of file:///var/lib/pixa/..., and keeps a relative
|
||||||
|
// state_dir from being read as a host name.
|
||||||
|
dbURL := url.URL{
|
||||||
|
Scheme: "file",
|
||||||
|
OmitHost: true,
|
||||||
|
Path: c.StateDir + "/state.sqlite3",
|
||||||
|
RawQuery: "_pragma=journal_mode(WAL)",
|
||||||
|
}
|
||||||
|
c.DBURL = dbURL.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if loader.err != nil {
|
if loader.err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user