Repository navigation
Highlights
- About 6x faster redirects. SQLite now runs in WAL mode with
synchronous=NORMAL, as the database URL always intended; the old SQLite driver ignored those settings. The benchmark went from about 3.5k to 21k req/s with every click recorded, at 6 ms average latency and 32 MiB average memory (benchmark). - Security fixes. Crystal 1.21.1 fixes HTTP request smuggling and request body handling in the standard library server, and Kemal 1.14 fixes, among others, HEAD requests bypassing GET filters and route matching on malformed methods.
- Official multi-arch image. The image is built from the official Crystal 1.21.1 Alpine image for
linux/amd64andlinux/arm64. - Safer migrations. Micrate is replaced by a built-in migrator that keeps the same
micrate_db_versionhistory, stops the app when a migration fails, and addscli --migrate-downto roll back the newest migration. - Tested data updates. The scheduled GeoLite2 and user-agent regex update now runs the full test suite against the downloaded files before it opens a PR.
- Redirects keep visitor metadata out of caches, malformed API input gets controlled 400 responses, and repeated user-agent and GeoIP lookups are cached.
Upgrade notes
- Back up
sqlite/data.dbbefore upgrading. On first start the database switches to WAL mode, anddata.db-walanddata.db-shmfiles appear next to it. Mount the wholesqlite/directory, as the Docker Compose file does, not onlydata.db. - Foreign keys are now enforced. Deleting a user now also deletes their links and clicks, as the schema always declared.
- API errors are always JSON. A path with no route returns
404 {"error":"Resource not found"}instead of an HTML page, and a wrong method returns405with anAllowheader instead of404. - Rollback is limited.
cli --migrate-downrefuses20250319192003, which has no Down section. The image applies pending migrations again on its next start, so a rollback only sticks if you deploy an older image afterwards. - A database still older than March 2025 that holds clicks or links whose parent row is gone cannot run the
20250319192003migration, as before this release.
What's Changed
- Harden redirects, improve throughput, and add e2e coverage by @sjdonado in #21
- chore: Update UA regexes and GeoLite2 database by @github-actions[bot] in #22
- Upgrade Crystal 1.21.1, kemal 1.14, sqlite3 0.23, and fix parser CI by @sjdonado in #24
- Bump version to 1.7.0 and test parser updates by @sjdonado in #25
Full Changelog: 1.6.2...1.7.0