Como posso verificar se uma string é um URL válido?
Por exemplo:
http://hello.it => yes
http:||bra.ziz, => no
Se este for um URL válido, como posso verificar se ele é relativo a um arquivo de imagem?
Como posso verificar se uma string é um URL válido?
Por exemplo:
http://hello.it => yes
http:||bra.ziz, => no
Se este for um URL válido, como posso verificar se ele é relativo a um arquivo de imagem?
Respostas:
Use o URI
módulo distribuído com Ruby:
require 'uri'
if url =~ URI::regexp
# Correct URL
end
Como Alexander Günther disse nos comentários, ele verifica se uma string contém um URL.
Para verificar se a string é um URL, use:
url =~ /\A#{URI::regexp}\z/
Se você deseja verificar apenas URLs da web ( http
ou https
), use:
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
'http://:5984/asdf' =~ URI::regexp
e 'http::5984/asdf' =~ URI::regexp
ambos retornam 0. Eu esperava que eles retornassem nil porque nenhum deles é URIs válidos.
"http:"
passa esse regexp.
Semelhante às respostas acima, acho que usar esta regex é um pouco mais preciso:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Isso invalidará URLs com espaços, em vez de URI.regexp
permitir espaços por algum motivo.
Recentemente encontrei um atalho fornecido para os diferentes rgexps de URI. Você pode acessar qualquer um URI::DEFAULT_PARSER.regexp.keys
diretamente de URI::#{key}
.
Por exemplo, o :ABS_URI
regexp pode ser acessado de URI::ABS_URI
.
/^#{URI.regexp}$/
. O problema é que URI.regexp
isso não ancora. Uma string com um espaço não está validando o espaço como parte do URI, mas tudo que leva ao espaço. Se esse fragmento parecer um URI válido, a correspondência será bem-sucedida.
'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
dá 0, não nulo; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
dá 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/
dá 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/
dá 0 também. Nenhuma das expressões regulares acima está totalmente correta, no entanto, elas falham apenas em situações muito estranhas e isso não é um grande problema na maioria dos casos.
URI::DEFAULT_PARSER.regexp[:ABS_URI]
é idêntico a/\A\s*#{URI::regexp}\s*\z/
O problema com as respostas atuais é que um URI não é um URL .
Um URI pode ser classificado como um localizador, um nome ou ambos. O termo "Uniform Resource Locator" (URL) refere-se ao subconjunto de URIs que, além de identificar um recurso, fornecem um meio de localizar o recurso, descrevendo seu mecanismo de acesso primário (por exemplo, sua "localização" de rede).
Como os URLs são um subconjunto de URIs, está claro que a correspondência específica para URIs corresponderá com êxito a valores indesejados. Por exemplo, URNs :
"urn:isbn:0451450523" =~ URI::regexp
=> 0
Dito isso, até onde eu sei, Ruby não tem uma maneira padrão de analisar URLs, então você provavelmente precisará de uma gema para fazer isso. Se precisar corresponder URLs especificamente no formato HTTP ou HTTPS, você pode fazer algo assim:
uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
# do your stuff
end
uri.kind_of?(URI::HTTP)
parece ser suficiente para ambos os casos (http e https), pelo menos em ruby 1.9.3.
URI.parse(string_to_be_checked).kind_of?(URI::HTTP)
faz bem o trabalho.
Eu prefiro a gema endereçável . Eu descobri que ele lida com URLs de forma mais inteligente.
require 'addressable/uri'
SCHEMES = %w(http https)
def valid_url?(url)
parsed = Addressable::URI.parse(url) or return false
SCHEMES.include?(parsed.scheme)
rescue Addressable::URI::InvalidURIError
false
end
Addressable::URI.parse
não retorna nulo com entrada inválida.
Esta é uma entrada bastante antiga, mas pensei em prosseguir e contribuir:
String.class_eval do
def is_valid_url?
uri = URI.parse self
uri.kind_of? URI::HTTP
rescue URI::InvalidURIError
false
end
end
Agora você pode fazer algo como:
if "http://www.omg.wtf".is_valid_url?
p "huzzah!"
end
http:/
, o que pode não ser o que você deseja.
Para mim, uso esta expressão regular:
/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
Opção:
i
- não diferencia maiúsculas de minúsculasx
- ignorar espaços em branco no regexVocê pode definir este método para verificar a validação de URL:
def valid_url?(url)
url_regexp = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
url =~ url_regexp ? true : false
end
Para usá-lo:
valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")
Testando com URLs errados:
http://ruby3arabi
- o resultado é inválidohttp://http://ruby3arabi.com
- o resultado é inválidohttp://
- o resultado é inválidoTeste com URLs corretos:
http://ruby3arabi.com
- o resultado é válidohttp://www.ruby3arabi.com
- o resultado é válidohttps://www.ruby3arabi.com
- o resultado é válidohttps://www.ruby3arabi.com/article/1
- o resultado é válidohttps://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en
- o resultado é válido"http://test.com\n<script src=\"nasty.js\">"
e qualquer domínio que use um dos 683 TLDs com mais de 5 caracteres ou dois ou mais hifens consecutivos é marcado como inválido. Números de porta fora do intervalo 0-65535 são permitidos. Os endereços FTP e IP obviamente não são permitidos, mas vale a pena observar.
Isso é um pouco antigo, mas aqui está como eu faço. Use o módulo URI do Ruby para analisar a URL. Se puder ser analisado, é um URL válido. (Mas isso não significa acessível.)
O URI suporta muitos esquemas, além disso, você mesmo pode adicionar esquemas personalizados:
irb> uri = URI.parse "http://hello.it" rescue nil
=> #<URI::HTTP:0x10755c50 URL:http://hello.it>
irb> uri.instance_values
=> {"fragment"=>nil,
"registry"=>nil,
"scheme"=>"http",
"query"=>nil,
"port"=>80,
"path"=>"",
"host"=>"hello.it",
"password"=>nil,
"user"=>nil,
"opaque"=>nil}
irb> uri = URI.parse "http:||bra.ziz" rescue nil
=> nil
irb> uri = URI.parse "ssh://hello.it:5888" rescue nil
=> #<URI::Generic:0x105fe938 URL:ssh://hello.it:5888>
[26] pry(main)> uri.instance_values
=> {"fragment"=>nil,
"registry"=>nil,
"scheme"=>"ssh",
"query"=>nil,
"port"=>5888,
"path"=>"",
"host"=>"hello.it",
"password"=>nil,
"user"=>nil,
"opaque"=>nil}
Consulte a documentação para obter mais informações sobre o módulo URI.
URI.parse
foi na verdade a causa disso no Ruby 2.5.5 - eu mudei para a resposta @jonuts abaixo se você não se importa com alguns casos estranhos que não aparecem. Para meus propósitos, não me importava, então isso era o ideal.
Em geral,
/^#{URI::regexp}$/
funcionará bem, mas se você quiser apenas fazer a correspondência http
ou https
, poderá passá-los como opções para o método:
/^#{URI::regexp(%w(http https))}$/
Isso tende a funcionar um pouco melhor, se você quiser rejeitar protocolos como ftp://
.
Você também pode usar um regex, talvez algo como http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm presumindo que este regex esteja correto (eu não verifiquei totalmente) o seguinte irá mostrar a validade do url.
url_regex = Regexp.new("((https?|ftp|file):((//)|(\\\\))+[\w\d:\#@%/;$()~_?\+-=\\\\.&]*)")
urls = [
"http://hello.it",
"http:||bra.ziz"
]
urls.each { |url|
if url =~ url_regex then
puts "%s is valid" % url
else
puts "%s not valid" % url
end
}
O exemplo acima resulta:
http://hello.it is valid
http:||bra.ziz not valid
URI
posso fazer está de fato quebrado. Veja os comentários nas tantas respostas votadas acima. Não tenho certeza se a resposta de Janie está certa, mas estou votando, então espero que as pessoas considerem isso mais seriamente. Acabo fazendo TBH url.start_with?("http://") || url.start_with?("https://")
porque preciso apenas de HTTP e os usuários devem ser responsáveis por usar URLs adequados.