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:
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
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
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