Jak mogę sprawdzić, czy ciąg jest prawidłowym adresem URL?
Na przykład:
http://hello.it => yes
http:||bra.ziz, => no
Jeśli to jest prawidłowy adres URL, jak mogę sprawdzić, czy jest on powiązany z plikiem obrazu?
Jak mogę sprawdzić, czy ciąg jest prawidłowym adresem URL?
Na przykład:
http://hello.it => yes
http:||bra.ziz, => no
Jeśli to jest prawidłowy adres URL, jak mogę sprawdzić, czy jest on powiązany z plikiem obrazu?
Odpowiedzi:
Użyj URImodułu dystrybuowanego z Rubim:
require 'uri'
if url =~ URI::regexp
# Correct URL
end
Jak Alexander Günther powiedział w komentarzach, sprawdza, czy ciąg zawiera adres URL.
Aby sprawdzić, czy ciąg jest adresem URL, użyj:
url =~ /\A#{URI::regexp}\z/
Jeśli chcesz sprawdzić tylko adresy internetowe ( httplub https), użyj tego:
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
'http://:5984/asdf' =~ URI::regexpi 'http::5984/asdf' =~ URI::regexpoba zwracają 0. Spodziewałem się, że zwrócą nil, ponieważ żaden z nich nie jest prawidłowym identyfikatorem URI.
"http:"przechodzi to wyrażenie regularne.
Podobnie jak w przypadku powyższych odpowiedzi, uważam, że użycie tego wyrażenia regularnego jest nieco dokładniejsze:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Spowoduje to unieważnienie adresów URL ze spacjami, w przeciwieństwie do tego, URI.regexpco z jakiegoś powodu zezwala na spacje.
Niedawno znalazłem skrót, który jest dostępny dla różnych rgexps URI. Możesz uzyskać dostęp do dowolnego URI::DEFAULT_PARSER.regexp.keysbezpośrednio z URI::#{key}.
Na przykład do :ABS_URIwyrażenia regularnego można uzyskać dostęp z URI::ABS_URI.
/^#{URI.regexp}$/. Problem w tym, URI.regexpże nie zakotwicza. Łańcuch ze spacją nie weryfikuje spacji jako części identyfikatora URI, ale wszystko, co prowadzi do spacji. Jeśli ten fragment wygląda jak prawidłowy identyfikator URI, dopasowanie powiedzie się.
'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]daje 0, a nie zero; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]daje 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/daje 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/daje również 0. Żadne z powyższych wyrażeń regularnych nie jest w pełni poprawne, jednak zawodzą one tylko w bardzo dziwnych sytuacjach iw większości przypadków nie jest to wielka sprawa.
URI::DEFAULT_PARSER.regexp[:ABS_URI]jest identyczne z/\A\s*#{URI::regexp}\s*\z/
Problem z obecnymi odpowiedziami polega na tym, że identyfikator URI nie jest adresem URL .
Identyfikator URI można dalej sklasyfikować jako lokalizator, nazwę lub jedno i drugie. Termin „Uniform Resource Locator” (URL) odnosi się do podzbioru identyfikatorów URI, które oprócz identyfikowania zasobu, umożliwiają zlokalizowanie zasobu poprzez opisanie jego głównego mechanizmu dostępu (np. „Lokalizacji” w sieci).
Ponieważ adresy URL są podzbiorem identyfikatorów URI, jasne jest, że dopasowanie specyficzne dla identyfikatorów URI z powodzeniem dopasuje niepożądane wartości. Na przykład URN :
"urn:isbn:0451450523" =~ URI::regexp
=> 0
Biorąc to pod uwagę, o ile wiem, Ruby nie ma domyślnego sposobu analizowania adresów URL, więc najprawdopodobniej będziesz potrzebować klejnotu, aby to zrobić. Jeśli potrzebujesz dopasować adresy URL konkretnie w formacie HTTP lub HTTPS, możesz zrobić coś takiego:
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)wydaje się być wystarczający w obu przypadkach (http i https), przynajmniej w Rubim 1.9.3.
URI.parse(string_to_be_checked).kind_of?(URI::HTTP)działa dobrze.
http:///neopets.comco niestety jest również poprawne. Sprawdzanie obecności nazwy hosta rozwiązuje ten problem:uri = URI(str) ; %w[http https].include?(uri.scheme) && !uri.host.nil?
Wolę klejnot adresowalny . Odkryłem, że inteligentniej obsługuje adresy URL.
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.parsenie zwraca nil z nieprawidłowymi danymi wejściowymi.
To jest dość stary wpis, ale pomyślałem, że mogę się do tego przyczynić:
String.class_eval do
def is_valid_url?
uri = URI.parse self
uri.kind_of? URI::HTTP
rescue URI::InvalidURIError
false
end
end
Teraz możesz zrobić coś takiego:
if "http://www.omg.wtf".is_valid_url?
p "huzzah!"
end
http:/, co może nie być tym, czego chcesz.
W moim przypadku używam tego wyrażenia regularnego:
/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
Opcja:
i - bez rozróżniania wielkości literx - zignoruj białe znaki w wyrażeniu regularnymMożesz ustawić tę metodę, aby sprawdzić poprawność adresu URL:
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
Aby z niego skorzystać:
valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")
Testowanie z niewłaściwymi adresami URL:
http://ruby3arabi - wynik jest nieprawidłowyhttp://http://ruby3arabi.com - wynik jest nieprawidłowyhttp:// - wynik jest nieprawidłowyhttp://test.com\n<script src=\"nasty.js\"> (Po prostu zaznacz „<skrypt”)Przetestuj z poprawnymi adresami URL:
http://ruby3arabi.com - wynik jest ważnyhttp://www.ruby3arabi.com - wynik jest ważnyhttps://www.ruby3arabi.com - wynik jest ważnyhttps://www.ruby3arabi.com/article/1 - wynik jest ważnyhttps://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en - wynik jest ważny"http://test.com\n<script src=\"nasty.js\">"a każda domena, która używa jednej z 683 domen TLD dłuższych niż 5 znaków lub ma dwa lub więcej następujących po sobie myślników, jest oznaczana jako nieprawidłowa. Dozwolone są numery portów spoza zakresu 0-65535. Adresy FTP i IP są oczywiście niedozwolone, ale warto o tym pamiętać.
To jest trochę stare, ale oto jak to robię. Użyj modułu URI Ruby, aby przeanalizować adres URL. Jeśli można go przeanalizować, jest to prawidłowy adres URL. (Ale to nie znaczy, że jest dostępny).
URI obsługuje wiele schematów, a ponadto możesz samodzielnie dodawać schematy niestandardowe:
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}
Zobacz dokumentację, aby uzyskać więcej informacji o module URI.
URI.parsebyło właściwie przyczyną tego w Rubim 2.5.5 - przełączyłem się na odpowiedź @jonuts poniżej, jeśli nie masz nic przeciwko niektórym dziwnym przypadkom. Dla moich celów nie obchodziło mnie to, więc to było idealne.
Ogólnie,
/^#{URI::regexp}$/
będzie działać dobrze, ale jeśli chcesz tylko dopasować httplub httpsmożesz przekazać je jako opcje do metody:
/^#{URI::regexp(%w(http https))}$/
Zwykle działa to trochę lepiej, jeśli chcesz odrzucić protokoły takie jak ftp://.
Możesz również użyć wyrażenia regularnego, może coś takiego jak http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm zakładając, że to wyrażenie regularne jest poprawne (nie sprawdziłem go w pełni). pokazać ważność adresu 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
}
Powyższy przykład daje:
http://hello.it is valid
http:||bra.ziz not valid
URIw rzeczywistości wszystko, co można zrobić, jest zepsute. Zobacz komentarze pod tak wieloma pozytywnymi odpowiedziami powyżej. Nie jestem pewien, czy odpowiedź Janie jest prawidłowa, ale głosowanie za głosem, więc mam nadzieję, że ludzie rozważą to poważniej. TBH w końcu robię, url.start_with?("http://") || url.start_with?("https://")ponieważ potrzebuję tylko HTTP, a użytkownicy powinni być odpowiedzialni za używanie odpowiednich adresów URL.