Vérifiez si l’URL existe dans Ruby

Comment pourrais-je vérifier si une URL existe en utilisant Ruby?

Par exemple, pour l’URL

https://google.com 

le résultat devrait être véridique , mais pour les URL

 https://no.such.domain 

ou

 https://stackoverflow.com/no/such/path 

le résultat devrait être falsey

Utilisez la bibliothèque Net :: HTTP .

 require "net/http" url = URI.parse("http://www.google.com/") req = Net::HTTP.new(url.host, url.port) res = req.request_head(url.path) 

À ce stade, res est un object Net :: HTTPResponse contenant le résultat de la requête. Vous pouvez alors vérifier le code de réponse:

 do_something_with_it(url) if res.code == "200" 

Remarque : Pour rechercher une URL basée sur https , l’atsortingbut use_ssl doit être true comme use_ssl :

 require "net/http" url = URI.parse("https://www.google.com/") req = Net::HTTP.new(url.host, url.port) req.use_ssl = true res = req.request_head(url.path) 

Désolé pour la réponse tardive à ce sujet, mais je pense que cela mérite une meilleure réponse.

Il y a trois façons de regarder cette question:

  1. Vérification ssortingcte si l’URL existe
  2. Vérifiez si vous demandez la correction de l’URL
  3. Vérifiez si vous pouvez le demander correctement et que le serveur peut y répondre correctement

1. Contrôle ssortingct si l’URL existe

Alors que 200 signifie que le serveur répond à cette URL (l’URL existe donc), répondre à un autre code d’état ne signifie pas que l’URL n’existe pas. Par exemple, répondre à 302 - redirected signifie que l’URL existe et redirige vers un autre. Lors de la navigation, 302 fois, l’utilisateur se comporte de la même manière que 200 . Un autre code de statut pouvant être renvoyé si une URL existe est 500 - internal server error . Après tout, si l’URL n’existe pas, comment se fait-il que le serveur d’application ait traité votre requête plutôt que de retourner simplement 404 - not found ?

Il n’y a donc en réalité qu’un seul cas où une URL n’existe pas: Lorsque le serveur n’existe pas ou lorsque le serveur existe mais ne peut pas trouver le chemin de l’URL donné n’existe pas. Ainsi, la seule façon de vérifier si l’URL existe est de vérifier si le serveur répond et si le code de retour n’est pas 404. Le code suivant ne fait que cela.

 require "net/http" def url_exist?(url_ssortingng) url = URI.parse(url_ssortingng) req = Net::HTTP.new(url.host, url.port) req.use_ssl = (url.scheme == 'https') path = url.path if url.path.present? res = req.request_head(path || '/') res.code != "404" # false if returns 404 - not found rescue Errno::ENOENT false # false if can't find the server end 

2. Vérifiez si vous demandez l’URL correclty

Cependant, la plupart du temps, nous ne sums pas intéressés à voir si une URL existe, mais si nous pouvons y accéder . Heureusement, pour les familles de codes d’état HTTP , il s’agit de la famille 4xx , qui indique les erreurs client (donc, une erreur de votre côté, ce qui signifie que vous ne demandez pas la page correctement, n’a pas de permission). C’est une bonne erreur pour vérifier si vous pouvez accéder à cette page. De wiki:

La classe de code de statut 4xx est destinée aux cas où le client semble avoir commis une erreur. Sauf en cas de réponse à une demande HEAD, le serveur doit inclure une entité contenant une explication de la situation d’erreur et indiquer s’il s’agit d’une condition temporaire ou permanente. Ces codes d’état sont applicables à toute méthode de demande. Les agents utilisateurs doivent afficher toute entité incluse à l’utilisateur.

Donc, le code suivant s’assure que l’URL existe et que vous pouvez y accéder :

 require "net/http" def url_exist?(url_ssortingng) url = URI.parse(url_ssortingng) req = Net::HTTP.new(url.host, url.port) req.use_ssl = (url.scheme == 'https') path = url.path if url.path.present? res = req.request_head(path || '/') if res.kind_of?(Net::HTTPRedirection) url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL else res.code[0] != "4" #false if http code starts with 4 - error on your side. end rescue Errno::ENOENT false #false if can't find the server end 

3. Vérifiez si vous pouvez le demander correctement et si le serveur peut y répondre correctement

Tout comme la famille 4xx vérifie si vous pouvez accéder à l’URL, la famille 5xx vérifie si le serveur a rencontré un problème pour répondre à votre demande. Une erreur sur cette famille la plupart du temps est due à des problèmes sur le serveur lui-même, et j’espère qu’ils travaillent à le résoudre. Si vous devez pouvoir accéder à la page et obtenir une réponse correcte maintenant , vous devez vous assurer que la réponse ne provient pas de la famille 4xx ou 5xx , et si vous avez été redirigé, la page redirigée répond correctement. Si semblable à (2), vous pouvez simplement utiliser le code suivant:

 require "net/http" def url_exist?(url_ssortingng) url = URI.parse(url_ssortingng) req = Net::HTTP.new(url.host, url.port) req.use_ssl = (url.scheme == 'https') path = url.path if url.path.present? res = req.request_head(path || '/') if res.kind_of?(Net::HTTPRedirection) url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL else ! %W(4 5).include?(res.code[0]) # Not from 4xx or 5xx families end rescue Errno::ENOENT false #false if can't find the server end 

Net::HTTP fonctionne mais si vous pouvez travailler en dehors de stdlib, Faraday est préférable.

 Faraday.head(the_url).status == 200 

(200 est un code de réussite, en supposant que ce que vous entendiez par “existe”.)

Vous devriez lire cet article:

Validation de l’URL / URI dans Ruby on Rails

La réponse de Simone m’a été très utile.

Voici une version qui renvoie true / false en fonction de la validité de l’URL et qui gère les redirections:

 require 'net/http' require 'set' def working_url?(url, max_redirects=6) response = nil seen = Set.new loop do url = URI.parse(url) break if seen.include? url.to_s break if seen.size > max_redirects seen.add(url.to_s) response = Net::HTTP.new(url.host, url.port).request_head(url.path) if response.kind_of?(Net::HTTPRedirection) url = response['location'] else break end end response.kind_of?(Net::HTTPSuccess) && url.to_s end