DBDelve
Dive deep into your data. A fast, native, multi-engine database client written in Rust. Free and open source, no telemetry.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
Velerion: a URL shortener built on a hand-written hash table
翻訳待ち
Loading the full README.
Read the full README ↗A free, working URL shortener built on a hand-written hash table, with a linked-list baseline, live comparison counts, and a visual walk-through of every hash and collision.
Live: https://velerion.github.io · short links look like velerion.github.io/aZ3kQ
| Requirement | Where |
|---|---|
| Hash table mapping short codes → long URLs, collisions handled explicitly | ChainingHashTable (separate chaining) and OpenAddressingHashTable (linear probing with tombstones) in js/structures.js |
| At least 30 entries | node cli/demo.js loads 32 sample URLs (cli/seed.js) into the same structures: 37 buckets, about a dozen collisions. The website itself holds only links people create. |
| Linked-list sequential-search baseline | LinkedList.search in js/structures.js |
| Shorten / retrieve / delete | The shortener at the top, Find or delete a link, and real redirects for every short link |
| Visible collision being resolved | How it works → Separate chaining → Force a collision, the result chips, and the highlighted chain |
| Printed comparison of retrieval comparisons | node cli/demo.js prints the full per-link comparison table; on the site, every Find shows the comparison count of all three structures |
node cli/demo.js prints average and per-link comparisons for 32 links (about 1.5 for the hash table vs 16.5 for the linked list).h = 0
for each character c in the code:
h = (h × 31 + charCode(c)) mod tableSize
bucket = h
Taking the remainder at each step keeps every number below the table size, so you can check it by hand. For example, vnrlK in a 37-bucket table: 0×31+118=118 → 7, 7×31+110=327 → 31, … and the last value is the bucket. The How it works → Hashing tab shows this table for any code you type.
Both tables follow one rule: when too full, about double the size (the next prime after 2 × size) and re-insert every link. Each link must be re-inserted because its bucket depends on the table size.
Velerion/Velerion.github.io). 404.html + js/route.js turn /aZ3kQ into /#/aZ3kQ, and the app resolves it.Map, Set or plain-object dictionaries are used for storage anywhere.| Threat | Protection |
|---|---|
| Seeing other people's links | Links are private. Nobody can list links. Your browser loads only the links it created, proving ownership with their secret tokens (my_links). Any other link opens only through resolve_link(exact code); there is no listing, searching or partial matching. |
| Guessing someone's link | New codes are 7 random characters from a cryptographic generator (62⁷ ≈ 3.5 trillion), and lookups are limited to 120 per minute per network. New links are created only through create_link, whose rate limit also counts attempts on codes that are already taken, so creating links can't be used to probe which codes exist. Finding one link by guessing would take centuries. |
| Deleting someone else's link | Each link gets a random delete token kept only in its creator's browser. Deletes go through delete_link(code, token), and the token can be written but never read. |
| Editing or hijacking a link | The public role has no UPDATE or DELETE rights. The server sets clicks, created_at and is_public itself. |
| Spam / flooding | 20 new links per minute per network and 300 in total, enforced in the database. The limiter uses the IP that Supabase's proxy appends, so a forged X-Forwarded-For header doesn't bypass it. IPv6 clients are counted per /64. my_links and delete_link are rate limited too. IPs are stored only as MD5 hashes and kept for 5 minutes. |
| Malicious URLs | http(s) only, ≤ 2048 characters, checked by the database and the app. Links with credentials (refused by both), to private/local addresses, or back to Velerion are refused, and the redirect screen shows the destination first. |
| Script injection (XSS) | All text is rendered with textContent. There is no innerHTML, eval or inline script, and a strict Content-Security-Policy allows scripts only from this site and network calls only to the database. |
| SQL injection | Only parameterised functions and PostgREST filters on permitted columns. Codes are validated against ^[A-Za-z0-9_-]{1,24}$ before any lookup. |
node security/pentest.mjs
This is the beginning of the README. Read the rest at the original. Read the full README ↗