Skip to content

fix: normalize trailing slashes in standardizeURL#3950

Merged
rebelchris merged 3 commits into
mainfrom
fix/normalize-trailing-slash-urls
Jul 10, 2026
Merged

fix: normalize trailing slashes in standardizeURL#3950
rebelchris merged 3 commits into
mainfrom
fix/normalize-trailing-slash-urls

Conversation

@rebelchris

@rebelchris rebelchris commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Problem

https://github.com/versity/versitygw and https://github.com/versity/versitygw/ (trailing slash) are treated as two separate articles, producing two distinct posts / sharedPostIds. standardizeURL cleaned query params but never normalized the path's trailing slash, and findPostByUrl matches on the exact string.

Fix

Trim trailing slashes from non-root paths in standardizeURL (root slash preserved). This flows automatically into both post creation (submitExternalLink) and dedup lookup (findPostByUrl).

The behavior intentionally matches yggdrasil's WithTrimTrailingSlash normalization (already on yggdrasil main), so both services agree on the canonical form — including preserving a bare root slash (https://host/ stays as-is) while collapsing single/multiple trailing slashes on real paths.

Notes

  • Forward-looking only — existing duplicate pairs are not merged by this change; that would need a separate backfill.
  • Added unit tests: single/multiple trailing slashes, root-slash preservation, and trailing slash before query params.

🤖 Generated with Claude Code

@pulumi

pulumi Bot commented Jun 19, 2026

Copy link
Copy Markdown

🍹 The Update (preview) for dailydotdev/api/prod (at 681e850) was successful.

Resource Changes

    Name                                                       Type                           Operation
~   vpc-native-clean-zombie-opportunities-cron                 kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-channel-highlights-cron                   kubernetes:batch/v1:CronJob    update
~   vpc-native-user-profile-updated-sync-cron                  kubernetes:batch/v1:CronJob    update
~   vpc-native-personalized-digest-deployment                  kubernetes:apps/v1:Deployment  update
~   vpc-native-post-lifecycle-state-clickhouse-cron            kubernetes:batch/v1:CronJob    update
~   vpc-native-subscription-anniversary-achievements-cron      kubernetes:batch/v1:CronJob    update
~   vpc-native-post-analytics-clickhouse-cron                  kubernetes:batch/v1:CronJob    update
~   vpc-native-bg-deployment                                   kubernetes:apps/v1:Deployment  update
~   vpc-native-squad-posts-analytics-refresh-cron              kubernetes:batch/v1:CronJob    update
~   vpc-native-validate-active-users-cron                      kubernetes:batch/v1:CronJob    update
~   vpc-native-private-deployment                              kubernetes:apps/v1:Deployment  update
~   vpc-native-check-analytics-report-cron                     kubernetes:batch/v1:CronJob    update
~   vpc-native-rotate-weekly-quests-cron                       kubernetes:batch/v1:CronJob    update
~   vpc-native-sync-subscription-with-cio-cron                 kubernetes:batch/v1:CronJob    update
~   vpc-native-update-tag-materialized-views-cron              kubernetes:batch/v1:CronJob    update
~   vpc-native-channel-digests-cron                            kubernetes:batch/v1:CronJob    update
-   vpc-native-api-clickhouse-migration-8e21f9db               kubernetes:batch/v1:Job        delete
~   vpc-native-rotate-daily-quests-cron                        kubernetes:batch/v1:CronJob    update
~   vpc-native-user-posts-analytics-refresh-cron               kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-old-notifications-cron                    kubernetes:batch/v1:CronJob    update
~   vpc-native-personalized-digest-cron                        kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-stale-user-transactions-cron              kubernetes:batch/v1:CronJob    update
~   vpc-native-materialize-yearly-best-post-archives-cron      kubernetes:batch/v1:CronJob    update
~   vpc-native-materialize-monthly-best-post-archives-cron     kubernetes:batch/v1:CronJob    update
-   vpc-native-api-db-migration-8e21f9db                       kubernetes:batch/v1:Job        delete
~   vpc-native-clean-zombie-images-cron                        kubernetes:batch/v1:CronJob    update
~   vpc-native-update-achievement-rarity-cron                  kubernetes:batch/v1:CronJob    update
~   vpc-native-channel-highlights-cron                         kubernetes:batch/v1:CronJob    update
~   vpc-native-hourly-notification-cron                        kubernetes:batch/v1:CronJob    update
~   vpc-native-calculate-top-readers-cron                      kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-zombie-users-cron                         kubernetes:batch/v1:CronJob    update
~   vpc-native-generate-search-invites-cron                    kubernetes:batch/v1:CronJob    update
~   vpc-native-update-highlighted-views-cron                   kubernetes:batch/v1:CronJob    update
~   vpc-native-worker-job-deployment                           kubernetes:apps/v1:Deployment  update
~   vpc-native-user-profile-analytics-history-clickhouse-cron  kubernetes:batch/v1:CronJob    update
~   vpc-native-update-views-cron                               kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-zombie-user-companies-cron                kubernetes:batch/v1:CronJob    update
~   vpc-native-update-trending-cron                            kubernetes:batch/v1:CronJob    update
+   vpc-native-api-db-migration-9053876d                       kubernetes:batch/v1:Job        create
~   vpc-native-daily-digest-cron                               kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-gifted-plus-cron                          kubernetes:batch/v1:CronJob    update
... and 15 other changes

Treat `.../foo` and `.../foo/` as the same article so they no longer
create separate posts. Trims trailing slashes from non-root paths,
matching yggdrasil's trailing-slash normalization (root slash preserved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rebelchris rebelchris force-pushed the fix/normalize-trailing-slash-urls branch from 66cb96b to eb844bd Compare June 19, 2026 12:00
@rebelchris rebelchris requested a review from capJavert June 19, 2026 12:12
@capJavert

capJavert commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

@rebelchris it is the same discussion as www vs non www, we should dedup but not change the URLs https://dailydotdev.slack.com/archives/C048P634WP7/p1781597733896869, so just check please with Ido how he wants it

Revert the standardizeURL trailing-slash trimming so the submitted url is
persisted verbatim. Instead, dedup at lookup time: getUrlTrailingSlashVariants
crosses with the existing www variants (getUrlDedupVariants), so a single
lookup matches both slash and no-slash forms without changing what we store.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rebelchris

Copy link
Copy Markdown
Contributor Author

@capJavert added onto the www one now

@rebelchris rebelchris merged commit 775f0a4 into main Jul 10, 2026
9 checks passed
@rebelchris rebelchris deleted the fix/normalize-trailing-slash-urls branch July 10, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants