8 min de lectureIngénierie

Lancement de la migration TinyURL : REST Pro/Bulk, pas de chemin pour la version gratuite

Comment nous avons intégré les importations TinyURL Pro/Bulk en un clic pour Elido — pourquoi TinyURL public n'a pas d'API, la terminologie alias vs slug, et la limite que nous avons implémentée volontairement.

Marius Voß
DevRel · edge infra
Diagramme de pipeline : API TinyURL Pro/Bulk à gauche passant par le worker d'importation Elido vers la table des liens, avec un panneau latéral listant les garanties numériques (limite de 50k, budget de 30 min, 100 par page, plans Pro/Bulk uniquement)

La quatrième source de migration de notre déploiement Tier-3 est disponible aujourd'hui. Collez un token d'API TinyURL Pro ou Bulk, choisissez un domaine Elido cible, cliquez sur Démarrer. Quatre à sept minutes plus tard, chaque alias TinyURL se trouve sur votre domaine Elido avec l'alias conservé là où il n'y a pas eu de collision.

Cet article est la documentation technique — ce qui est spécifique à TinyURL, la limite délibérée que nous avons implémentée, et pourquoi la « migration TinyURL de la version gratuite » est quelque chose que nous ne pouvons pas construire.

Le problème de la version gratuite#

TinyURL public n'a pas d'API et n'en a jamais eu. Le tinyurl.com/<slug> classique que vous créez sans compte est une redirection « fire-and-forget » — l'utilisateur le crée via le formulaire de la page d'accueil, obtient un slug en retour, et ce slug n'apparaît jamais dans aucun tableau de bord de compte. Il n'y a pas de listing par utilisateur car il n'y a pas de liaison par utilisateur.

Ceci est bien connu, mais il vaut la peine de le mettre en avant sur la page de destination /migrate-from/tinyurl car la requête de recherche « migrate from TinyURL » ne permet pas de distinguer Pro de gratuit. Nous avons mis en place :

  • Une mention claire « Pro/Bulk uniquement » sur le héros de la page de destination.
  • Une entrée FAQ qui oriente les utilisateurs de la version gratuite vers le formulaire /docs/guides/bulk-create pour le raccourcissement en masse par collage de liste de destinations.
  • Une étape de validation du token dans le lanceur qui échoue rapidement avec « ce token n'est pas sur un plan Pro ou Bulk » au lieu de laisser l'exécution échouer silencieusement en 401 au milieu de la pagination.

Le raisonnement : toutes les autres sources de migration que nous déployons ont un chemin heureux pour « chaque utilisateur qui les recherche ». TinyURL est l'exception — les utilisateurs de la version gratuite ont besoin d'un modèle mental différent et nous devrions définir cette attente avant qu'ils ne collent quoi que ce soit.

Structure de l'API REST Pro/Bulk#

L'API TinyURL Pro est simple : token bearer, réponses JSON, 100 alias par page. La pagination utilise un paramètre de chaîne de requête page qui est indexé à 1 ; la réponse inclut data.aliases (le tableau de liens) et meta.has_more (le signal de continuation).

const tinyurlPageSize = 100

page := 1
for {
    resp, err := w.fetchPage(ctx, opts.Token, page)
    if err != nil { /* mark failed */ return }
    if len(resp.Data.Aliases) == 0 { break }
    for _, alias := range resp.Data.Aliases { /* import */ }
    if !resp.Meta.HasMore { break }
    page++
}

Chaque alias transporte url (la destination longue), alias (le slug personnalisé ou le code court auto-généré), description (un champ TinyURL optionnel que nous préservons en tant que titre de lien Elido), et un domain (TinyURL autorise les domaines personnalisés sur les plans Bulk).

Terminologie — alias vs slug#

TinyURL les appelle des « alias ». Nous les appelons des « slugs ». C'est la même chose — la séquence de caractères après l'hôte dans l'URL de redirection. La migration préserve l'alias 1:1 là où le domaine Elido cible n'a pas de collision ; s'il y a une collision, la stratégie de conflit standard suffixe/ignorer/échouer s'applique.

Nous avons envisagé de renommer « slug » en « alias » dans le lanceur pour correspondre à la terminologie du vendeur source et l'avons rejeté pour des raisons de cohérence. Toute autre surface Elido — liste de liens, API, SDK, tableau de bord — utilise « slug ». Importer une asymétrie de terminologie dans un lanceur rendrait l'expérience post-importation confuse.

Le lanceur affiche tout de même une étiquette d'une ligne disant « TinyURL appelle ceci des alias » au-dessus du bouton radio de stratégie de conflit, afin que les utilisateurs recherchant « alias » sur la page de la recette trouvent le bon contrôle sans avoir à lire chaque mot.

Domaines personnalisés et transfert DNS#

Les plans TinyURL Bulk prennent en charge les domaines personnalisés — votre propre nom d'hôte routant via l'infrastructure de TinyURL. Lorsque vous migrez vers Elido, le slug s'importe proprement, et le côté DNS est un changement de CNAME.

Le cas intéressant est « J'ai un domaine personnalisé sur TinyURL Bulk et je veux garder le même nom d'hôte après la migration ». Nous gérons cela de la même manière que la migration Short.io :

  • La migration est terminée. Les liens importés se trouvent sur s.elido.me/<alias> par défaut (ou votre domaine personnalisé Elido existant).
  • Vous ajoutez le domaine personnalisé TinyURL comme domaine personnalisé Elido via /docs/guides/custom-domains.
  • Vous pointez le CNAME vers Elido. Le TLS à la demande de Caddy émet un certificat lors de la première requête ; domain-manager est la source de vérité pour la liste blanche, donc les noms d'hôtes non autorisés sont rejetés.
  • La surface de TinyURL cesse de résoudre pour ce nom d'hôte ; celle d'Elido prend le relais.

Vous pouvez maintenir les deux surfaces actives en parallèle jusqu'à ce que votre abonnement TinyURL se termine, puis le basculement consiste simplement à laisser expirer le nom d'hôte TinyURL. Aucune urgence, aucun risque le jour du basculement.

Ce que nous ne migrons pas#

L'historique des clics. Les analyses de TinyURL Pro/Bulk sont des points de terminaison de rapport séparés qui ne sont pas structurés pour l'exportation. Le plan Bulk expose les nombres de clics par lien dans le tableau de bord mais ne les expose pas via l'API adaptée à la migration ; les nouveaux clics atterrissent dans les analyses Elido à partir du basculement.

Le style QR et les modèles UTM du plan Bulk. Même histoire que pour toute autre source de migration — le slug s'importe, la couche de présentation environnante est reconstruite dans Elido. Tagué imported:tinyurl pour un suivi en masse via campagnes.

Les liens TinyURL de la version gratuite. Comme discuté ci-dessus, TinyURL public n'a pas d'API. L'atténuation est le formulaire de création en masse, pas un travail de migration.

Gestion du token#

Mêmes sémantiques « one-shot » que Bitly, Rebrandly et Short.io :

bgCtx := context.WithoutCancel(r.Context())
go h.tinyurl.Run(bgCtx, job.ID, imports.TinyURLJobOptions{
    Token: req.Token,
})

source_token_id reste NULL. Le token vit dans la mémoire du processus api-core pour l'exécution du worker et est supprimé à la fin. Pas de persistance, pas de ligne service_tokens, pas de chiffrement d'enveloppe ADR-0036 — ceux-ci sont pour les intégrations Tier-2 où l'utilisateur veut des appels récurrents au vendeur.

L'étape de validation du token au démarrage du job atteint le /account/domains endpoint de TinyURL — appel peu coûteux, renvoie une liste de domaines que le token peut voir. S'il répond 401, nous échouons rapidement avec « le token est invalide ou n'est pas sur un plan Pro/Bulk » plutôt que de laisser l'utilisateur attendre deux minutes pour un 401 au milieu de la pagination et un message d'erreur moins utile.

Résolution de conflit#

Identique à tout autre fournisseur de migration — le suffixe parcourt myalias-2, myalias-3, … en cas de collision ; ignorer laisse le lien Elido existant tranquille et enregistre la ligne source ; échouer abandonne au premier conflit.

func (w *TinyURLWorker) resolveSlug(ctx context.Context, domainID int64, desired, strategy string) (string, error) {
    if _, err := w.links.GetByDomainSlug(ctx, domainID, desired); err != nil {
        if errors.Is(err, pgx.ErrNoRows) { return desired, nil }
        return "", fmt.Errorf("slug lookup: %w", err)
    }
    // suffix/skip/fail branching identical to bitly.go
}

La recherche est une lecture indexée par ligne. Nous payons une lecture supplémentaire mais obtenons des parcours de suffixes déterministes et des messages d'erreur plus conviviaux que de pêcher les violations d'unicité.

Le contrat du worker#

MaxLinksPerImport=50_000, ImportRunBudget=30*time.Minute, progressEvery=50, errorLogCap=1_000. Partagé entre les cinq fournisseurs de migration. Ces constantes sont le contrat que l'interface utilisateur de sondage du tableau de bord suppose.

Un compte TinyURL Pro de 2 000 alias atteint l'API 20 fois et termine en 3–5 minutes. Un compte Bulk de 20 000 alias prend 200 allers-retours et termine en 15–20 minutes. Au-dessus de 50 000 alias, le worker échoue brutalement avec une instruction d'envoyer un e-mail à [email protected] pour une migration par blocs ; le chemin migration par blocs est uniquement sur demande (concierge) dans la v1.

Reprenabilité et problème de déploiement#

Même compromis que pour les trois premières migrations. Le worker est en cours de processus ; un déploiement au milieu de l'importation tue la goroutine. Le cron de balayage des tâches bloquées bascule toute ligne running sans progression en 30 minutes vers failed. La réexécution est idempotente sous suffixe et ignorer.

Pour les comptes au-delà de 10 000 alias, la reprenabilité vaudrait le coup — nous enregistrerions le curseur de page TinyURL dans import_jobs.source_filter et reprendrions à partir de la dernière page terminée. Les quatre autres fournisseurs de migration bénéficieront du même changement une fois que nous l'aurons déployé ; la conception est partagée.

Repli CSV#

Pour les utilisateurs sur des plans Bulk avec un CSV exporté qui n'ont plus de token d'API actif, nous exécutons des travaux CSV uniques depuis la boîte de réception — e-mail [email protected]. Nous n'avons pas déployé de formulaire de téléchargement CSV en libre-service car le chemin REST couvre le cas courant et le chemin CSV nécessite un massage de schéma par compte qui est mieux fait à la main que par un analyseur générique fragile.

Et ensuite#

Encore un fournisseur à intégrer :

  • Dub.coGET /api/links?projectSlug=…&limit=100. Les dossiers s'aplatissent en tags. L'API la plus propre des cinq.

Après Dub, le déploiement Tier-3 est terminé. Cinq atterrissages de migration, cinq articles de blog d'ingénierie, une structure de worker partagée, une interface utilisateur de sondage de tableau de bord partagée.

Si vous avez attendu parce que la migration TinyURL n'était pas documentée, c'est maintenant le cas. Essayez-le — du token Pro/Bulk au dernier lien importé en moins de sept minutes pour les comptes typiques.

Sur le blog#

Essayer Elido

Raccourcisseur d'URL hébergé en UE : domaines personnalisés, analyses approfondies et API ouverte. Forfait gratuit — sans carte bancaire.

Tags
tinyurl migration
url shortener
go worker
data migration
engineering
tier 3 integrations

Lire la suite