Bir URL'nin geçerli olup olmadığı nasıl kontrol edilir


95

Bir dizenin geçerli bir URL olup olmadığını nasıl kontrol edebilirim?

Örneğin:

http://hello.it => yes
http:||bra.ziz, => no

Bu geçerli bir URL ise, bunun bir resim dosyasına göre olup olmadığını nasıl kontrol edebilirim?


Sağladığınız url mutlak bir url gibi görünüyor, bir resim dosyasına göre ne demek istiyorsunuz
johannes

Yanıtlar:


179

URIRuby ile dağıtılan modülü kullanın :

require 'uri'

if url =~ URI::regexp
    # Correct URL
end

Gibi Alexander Günther yorumlar dedi bir dize, eğer denetler içeren bir URL.

Dize olmadığını kontrol etmek olduğunu URL kullanın:

url =~ /\A#{URI::regexp}\z/

Yalnızca web URL'lerini ( httpveya https) kontrol etmek istiyorsanız , şunu kullanın:

url =~ /\A#{URI::regexp(['http', 'https'])}\z/

25
Bu işe yaramıyor gibi görünüyor: 'http://:5984/asdf' =~ URI::regexpve 'http::5984/asdf' =~ URI::regexpher ikisi de 0 döndürüyor. Hiçbiri geçerli URI olmadığından sıfır dönmelerini bekliyordum.
awendt

4
Değil mi: localhost'ta 5984 bağlantı noktası 5984?
mxcl

3
Aslında bir değişkenin geçerli bir url içerip içermediğini kontrol eder. " Örnek com" adresini geçerli bir URL olarak kabul eder . Çünkü bir tane içeriyor. Ancak her şeyin URL olmasını beklemeniz yararlı değildir.
Alexander Günther

2
gotqn: RFC 1738'e göre bu geçerli bir URL değil.
Mikael S

12
Bunu kullanmayın, "http:"bu regexp'in geçmesi o kadar kötü ki .
2016

43

Yukarıdaki yanıtlara benzer şekilde, bu normal ifadeyi kullanmayı biraz daha doğru buluyorum:

URI::DEFAULT_PARSER.regexp[:ABS_URI]

Bu, URI.regexpherhangi bir nedenle boşluklara izin veren URL'lerin aksine boşluklu URL'leri geçersiz kılar .

Yakın zamanda farklı URI rgexps için sağlanan bir kısayol buldum. Herhangi birinden URI::DEFAULT_PARSER.regexp.keysdoğrudan erişebilirsiniz URI::#{key}.

Örneğin, :ABS_URIregexp'e adresinden erişilebilir URI::ABS_URI.


3
URI.parse'ı herhangi bir noktada kullanmayı planlıyorsanız, kesinlikle gitmenin yolu budur. URI :: regexp, daha sonra URI.parse kullanıldığında başarısız olacak belirli URL'lerle eşleşir. Bahşiş için teşekkürler.
markquezada

Ne yazık ki bu sadece Ruby 1.9'da mevcut, 1.8'de değil.
Steve Madsen

1
Ama, bu çalışır: /^#{URI.regexp}$/. Sorun şu ki URI.regexp, bu çapa değil. Boşluk içeren bir dize, alanı URI'nin bir parçası olarak doğrulamaz, ancak boşluğa giden her şey. Bu parça geçerli bir URI gibi görünüyorsa, eşleşme başarılı olur.
Steve Madsen

3
Önerilerinize awendt'in yorumunu uygulamak: 'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]sıfır değil, 0 verir; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]0 verir; 'http://:5984/asdf' =~ /^#{URI.regexp}$/0 verir; 'http::5984/asdf' =~ /^#{URI.regexp}$/0 da verir. Yukarıdaki normal ifadelerin hiçbiri tam olarak doğru değildir, ancak yalnızca çok garip durumlarda başarısız olurlar ve bu çoğu durumda büyük bir sorun değildir.
skalee

1
Bilginize, URI::DEFAULT_PARSER.regexp[:ABS_URI]aynı/\A\s*#{URI::regexp}\s*\z/
aidan

36

Mevcut cevaplarla ilgili sorun, bir URI'nin bir URL olmamasıdır .

Bir URI ayrıca bir konum belirleyici, bir ad veya her ikisi olarak sınıflandırılabilir. "Tekdüzen Kaynak Konum Belirleyicisi" (URL) terimi, bir kaynağın tanımlanmasına ek olarak, birincil erişim mekanizmasını (örneğin, ağ "konumu") açıklayarak kaynağın konumlandırılması için bir araç sağlayan URI'lerin alt kümesine karşılık gelir.

URL'ler URI'lerin bir alt kümesi olduğundan, özellikle URI'ler için eşleşmenin istenmeyen değerlerle başarılı bir şekilde eşleşeceği açıktır. Örneğin, URN'ler :

 "urn:isbn:0451450523" =~ URI::regexp
 => 0 

Bununla birlikte, bildiğim kadarıyla Ruby'nin URL'leri ayrıştırmak için varsayılan bir yolu yok, bu yüzden bunu yapmak için büyük olasılıkla bir cevher ihtiyacınız olacak. URL'leri özellikle HTTP veya HTTPS biçiminde eşleştirmeniz gerekiyorsa, aşağıdaki gibi bir şey yapabilirsiniz:

uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
  # do your stuff
end

@Philip hem yardımcı hem de uygundu. Çok teşekkür ederim!
fotanus

2
uri.kind_of?(URI::HTTP)En azından Ruby 1.9.3'te her iki durum için de (http ve https) yeterli görünmektedir.
Andrea Salicetti

@skalee tarafından jonuts'un cevabı altında açıklanan sorunlardan hala muzdarip
akostadinov

1
Özet, URI.parse(string_to_be_checked).kind_of?(URI::HTTP)işi iyi yapıyor.
ben

Ek olarak, veritabanımızdaki çok yaygın bir yanlış yazım, insanların birçok eğik çizgi koyma eğiliminde olduğunu gösteriyor: http:///neopets.comki bu da maalesef geçerli. Bir ana bilgisayar adının varlığını kontrol etmek bunu düzeltir:uri = URI(str) ; %w[http https].include?(uri.scheme) && !uri.host.nil?
Shane

19

Adreslenebilir mücevheri tercih ederim . URL'leri daha akıllıca işlediğini buldum.

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

3
Neyi reddettiğini görmek için Addressable :: URI.parse () 'yi en tuhaf dizelerle besledim. Çılgınca şeyleri kabul etti. Ancak kabul etmediği ilk dize ":-)" idi. Hmm.
mvw

1
Bu nasıl bu kadar çok olumlu oy alıyor? Addressable::URI.parsegeçersiz girdi ile nil döndürmez.
garbagecollector

11

Bu oldukça eski bir giriş, ancak devam edip katkıda bulunacağımı düşündüm:

String.class_eval do
    def is_valid_url?
        uri = URI.parse self
        uri.kind_of? URI::HTTP
    rescue URI::InvalidURIError
        false
    end
end

Şimdi şöyle bir şey yapabilirsiniz:

if "http://www.omg.wtf".is_valid_url?
    p "huzzah!"
end

2
Bu , yukarıdaki çözümlerden çok daha iyi çalışıyor . Yukarıda listelenen uyarılara sahip değildir ve javascript: alert ('spam') gibi uris'leri de kabul etmez.
bchurchill

2
ama aynı zamanda eşleşiyor http:/, ki bu istediğin şey olmayabilir.
Bo Jeanes

11

Benim için şu normal ifadeyi kullanıyorum:

/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix

Seçenek:

  • i - büyük / küçük harfe duyarlı değil
  • x - normal ifadede boşlukları yoksay

URL doğrulamasını kontrol etmek için bu yöntemi ayarlayabilirsiniz:

def valid_url?(url)
  return false if url.include?("<script")
  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

Kullanmak için:

valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")

Yanlış URL'lerle test etme:

  • http://ruby3arabi - sonuç geçersiz
  • http://http://ruby3arabi.com - sonuç geçersiz
  • http:// - sonuç geçersiz
  • http://test.com\n<script src=\"nasty.js\"> (Sadece "<script" i kontrol edin)

Doğru URL'lerle test edin:

  • http://ruby3arabi.com - sonuç geçerlidir
  • http://www.ruby3arabi.com - sonuç geçerlidir
  • https://www.ruby3arabi.com - sonuç geçerlidir
  • https://www.ruby3arabi.com/article/1 - sonuç geçerlidir
  • https://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en - sonuç geçerlidir

Aşağıdakiler geçerli olarak işaretlenmiştir: "http://test.com\n<script src=\"nasty.js\">"ve 5 karakterden uzun olan 683 TLD'lerden birini kullanan veya iki veya daha fazla art arda tire içeren herhangi bir etki alanı geçersiz olarak işaretlenir. 0-65535 aralığının dışındaki bağlantı noktası numaralarına izin verilir. FTP ve IP adreslerine açıkça izin verilmiyor, ancak kayda değer.
aidan

1
hızlı url denetimi için burada kolayca en uygun çözüm. teşekkürler
somedirection

4

Bu biraz eski ama işte bunu nasıl yapıyorum. URL'yi ayrıştırmak için Ruby'nin URI modülünü kullanın. Ayrıştırılabiliyorsa, geçerli bir URL'dir. (Ancak bu erişilebilir anlamına gelmez.)

URI birçok şemayı destekler, ayrıca özel şemaları kendiniz ekleyebilirsiniz:

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}

URI modülü hakkında daha fazla bilgi için belgelere bakın .


Bir segfault'u düzeltmeye çalışırken bununla karşılaştım. URI.parseRuby 2.5.5'te bunu kullanmak aslında bunun sebebiydi - Bazı garip durumların düşmesi sizin için bir sakıncası yoksa aşağıdaki @jonuts cevabına geçtim. Benim amacım için umursamadım, bu yüzden idealdi.
el n00b

3

Genel olarak,

/^#{URI::regexp}$/

iyi çalışacaktır, ancak yalnızca eşleştirmek istiyorsanız httpveya httpsbunları seçenek olarak yönteme aktarabilirsiniz:

/^#{URI::regexp(%w(http https))}$/

Şu gibi protokolleri reddetmek istiyorsanız, bu biraz daha iyi çalışma eğilimindedir. ftp:// .


-2

Ayrıca bir normal ifade de kullanabilirsiniz, belki http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm gibi bir şey, bu normal ifadenin doğru olduğunu varsayarak (tam olarak kontrol etmedim) aşağıdakiler url'nin geçerliliğini gösterin.

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
}

Yukarıdaki örnek çıktılar:

http://hello.it is valid
http:||bra.ziz not valid

5
Mailto planı ne olacak? Veya telnet, gopher, nntp, rsync, ssh veya diğer şemalardan herhangi biri? URL'ler, HTTP ve FTP'den biraz daha karmaşıktır.
mu çok kısa

URL'leri doğrulamak için normal ifade yazmak zordur. Neden uğraşıyorsun?
Rimian

@Rimian, zahmet etmelisin çünkü URIyapabileceğin her şey aslında bozuk. Yukarıdaki pek çok olumlu oylu yanıtın altındaki yorumlara bakın. Janie'nin cevabının doğru olup olmadığından emin değilim, ancak olumlu oy veriyor, bu yüzden umarız insanlar bunu daha ciddiye alır. TBH Yapıyorum url.start_with?("http://") || url.start_with?("https://")çünkü sadece HTTP'ye ihtiyacım var ve kullanıcılar doğru URL'leri kullanmaktan sorumlu olmalı.
akostadinov
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.