Il est fréquent de devoir vérifier la validité d’une adresse e-mail ou bien d’un nom de domaine, fréquemment, les développeurs font la même erreur, utiliser une Regex pour valider et bien souvent cette regex n’est plus à jour et c’est la que se produisent des drames alors comment valider correctement un nom de domaine ou bien une adresse e-mail ?
Décomposons un nom de domaine / une adresse e-mail
Une adresse e-mail contient un nom de domaine, dans cette logique, si nous validons le nom de domaine, nous validons une partie de l’adresse e-mail alors comment valider le nom de domaine ?
Un nom de domaine est composée d’une extension (.fr, .com, .be, .net, .biz …), on appelle ça un TLD dans le jargon technique informatique et un nom (par exemple le nom de votre entreprise).
Par chance, cette liste de TLD est publiée par l’IANA et est maintenue à jour alors pourquoi ne pas ce servir de cette source de vérité ? (Source of Truth) pour justement valider que ce que l’utilisateur nous donne à manger est bien digérable … (acceptable) Si vous voulez la liste, voici l’adresse de celle-ci : https://data.iana.org/TLD/tlds-alpha-by-domain.txt
Donc l’idée est simple : utiliser la liste pour vérifier ce que nous indique l’utilisateur. De cette façon, non seulement on valide que le TLD indiqué existe bien et on n’a pas une regex qui n’est potentiellement pas à jour. On pourrait également faire une requête DNS et vérifier que le nom de domaine existe bien mais cela consomme plus de ressources que d’aller chercher des données dans une liste et de faire de la manipulation sur un texte qu’on nous donne
Un peu de code
Dans notre cas, nous utilisons cela dans du code en Kotlin, c’est notamment cela qui sert dans la gestion des enregistrements DNS sur notre plateforme.
Concrètement, notre application contient un client HTTP qui va récupérer le fichier texte de l’Iana et le met en cache pour une durée d’une heure par exemple. Au bout d’une heure, une nouvelle lecture du fichier est faite.
@Cacheable(value = ["tlds"], cacheManager = "tldsCacheManager")
fun getTlds(): List<String> {
return iana.getTldsListAsString().split("\n").toImmutableList().drop(1).map { s -> s.lowercase() }
}
Une fois ce fichier récupéré, on a un Service Technique qui s’occupe de le mettre en forme comme on veut et récupère une liste de TLD, on peut lui passer le nom de domaine et il nous donne alors le TLD qu’il a trouvé ou non.
fun tld(domainName: String): String {
return applicationContext.getBean(DomainsAndTldsService::class.java).getTlds().stream().filter {
domainName.contains("\\.$it\$".toRegex())
}.findFirst().orElseThrow()
}
Et si on veut récupérer le nom de domaine sans le TLD
fun nomDomaine(name: String): NomDomaine {
val tld = tld(name)
return NomDomaine(name.substringBeforeLast(".$tld").substringAfterLast("."), Tld(tld))
}
C’est une implémentation que nous utilisons, libre à vous de voir comment faire. Dans notre cas, nous aimons bien utiliser les Value Object. En utilisant une factory qui s’occupe de construire un Value Object et qui utilise un service externe pour récupérer les données de l’Iana, vous êtes capable de gérer la validation du nom de domaine et par exemple de l’adresse e-mail. Pour rappel, un Value Object ne doit avoir aucune dépendance externe à un service quelconque, donc pour pallier à cela, il faut créer un service qui soit capable de créer un Value Object valide et dans le cas contraire, il ne peut le créer, mais c’est une façon de faire, libre à vous de voir comment vous implémentez cela. Vous pourriez tout à fait générer une librairie en Java que vous mettez dans vos dépendances et qui contient la liste en dur de ces TLD, plutôt que de les récupérer sur internet … mais cela vous obligera à re-livrer votre application à chaque fois qu’un nouveau TLD sera connu … et généralement, on aime bien laisser l’applicatif tourner le plus longtemps possible sans redéployer systématiquement pour le moindre petit changement …
Dans le cas d’application développée en JavaScript / TypeScript, on peut compter sur une librairie nommée tldts (https://www.npmjs.com/package/tldts).
En tout cas de notre côté, les Regex s’utilisent avec parcimonie et au cas par cas et dans tous les cas, c’est Tests Unitaires obligatoires, pour vérifier qu’on respecte le contrat et qu’on introduit pas de regression




