Resolve known link-shortener URLs (search.app / share.google) to their destination - #2934
Resolve known link-shortener URLs (search.app / share.google) to their destination#2934bcamarneiro wants to merge 1 commit into
Conversation
Greptile SummaryThis PR resolves known link-shortener URLs (
Confidence Score: 3/5Safe to merge for the core use-case, but video downloads will silently use the wrong URL for shortener-originated bookmarks. The URL helper and its tests are correct and conservative. The crawler integration also works correctly for the main bookmark-URL field. However, after
Important Files Changed
|
6192039 to
8acbef2
Compare
|
Good catch on the stale local One clarification on the stated impact, though: the runtime effect on video downloads is nil today. That said, passing a stale value is a smell worth removing, so |
431ace2 to
fea5114
Compare
|
@MohamedBassem any chance to get this merged? This feature is a game changer for using Karakeep with the Google Discovery feed |
When a bookmark is saved as a Google short/share link (search.app, share.google), the crawler already follows the redirect to fetch the real content, but the stored URL kept the opaque short link. Overwrite the stored URL with the resolved destination, scoped to a known-shortener allowlist and guarded by a safe-scheme check, so ordinary redirects (http->https, tracking-param strips) never rewrite the user's URL. Applied across all three crawl outcomes: - HTML pages: via the browser's final URL (Phase-1 bookmarkLinks write) - direct PDF/image links: the probe now returns its redirect target so the asset-bookmark path stores the resolved sourceUrl - downstream video jobs: crawlAndParseUrl returns the effective URL Covered by unit tests (packages/shared/utils/url.test.ts) and e2e tests that alias the nginx fixture as search.app and assert the resolved url and sourceUrl. Closes karakeep-app#2235
fea5114 to
d625706
Compare
|
Rebased onto current @MohamedBassem this is ready whenever you have a moment. |
Description
When a bookmark is saved as a Google short/share link (
https://search.app/...orhttps://share.google/...), the crawler already follows the redirect to fetch and archive the real page — but the stored bookmark URL keeps the opaque short link. This means the entry never reflects the actual destination, and if the shortener ever stops resolving, the real URL is lost.This PR overwrites the stored URL with the URL the crawler actually resolved to, but only when:
search.app,share.google), andhttp(s)URL.Scoping it to a small allowlist (rather than following every redirect) means ordinary redirects —
http→https, tracking-param strips, trailing-slash canonicalization — never silently rewrite the user's URL. The safe-scheme guard (reusing the existingisAllowedBookmarkUrl) ensures a shortener can never rewrite a bookmark to ajavascript:/data:/file:URL.The decision logic is extracted into a pure, unit-tested helper
resolveShortenedBookmarkUrl(originalUrl, crawledUrl)inpackages/shared/utils/url.ts. New shorteners can be added by extending theKNOWN_LINK_SHORTENERSlist.Resolution is applied consistently across all three outcomes of a crawl:
bookmarkLinksupdate (no new query, no DB migration), using the browser's final URL (robust to client-side redirects).sourceUrlinstead of the short link.crawlAndParseUrlreturns the effective (post-resolution) URL so the video-download queue receives the real destination, not the opaque short link.Fixes #2235
How Has This Been Tested?
isKnownLinkShortenerandresolveShortenedBookmarkUrlinpackages/shared/utils/url.test.ts, covering: known-shortener → resolved URL returned; non-shortener → unchanged; no-op redirect → unchanged; dangerous-scheme destination rejected; lookalike hosts (search.app.evil.com,notsearch.app,www.search.app) rejected. (18/18 passing.)packages/e2e_tests— the nginx fixture container is aliased assearch.app(allow-listed as a known shortener) with/shortlinkand/shortlink-imageredirects, asserting the storedurl(HTML path) andsourceUrl(asset path) are the resolved destinations, not the short link. Run locally against the full container stack: 7/7 crawler tests passing (http://search.app/shortlink→ stored.../hello.html;http://search.app/shortlink-image→sourceUrl .../image.png).pnpm typecheck,pnpm lint, andpnpm formatpass across the monorepo.Checklist:
Please describe to which degree, if any, an LLM was used in creating this pull request.
This PR was developed with the help of an AI coding assistant, following a test-driven approach (tests written and watched to fail before the implementation). All code was reviewed, run, and verified by me before submission.