URL이 유효한지 확인하는 방법


93

문자열이 유효한 URL인지 어떻게 확인할 수 있습니까?

예를 들면 :

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

이것이 유효한 URL이라면 이것이 이미지 파일과 관련된 것인지 어떻게 확인할 수 있습니까?


제공 한 URL은 절대 URL 인 것 같습니다. 이미지 파일과 관련하여 의미하는 바는 무엇입니까
-johannes

사양과 함께 UriValidator를 게시했습니다 .
JJD

답변:


177

URIRuby와 함께 배포 된 모듈을 사용하십시오 .

require 'uri'

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

마찬가지로 알렉산더 귄터는 의견을 밝혔다 문자열이 경우, 그것은 검사 포함 URL을.

문자열 URL 인지 확인하려면 다음을 사용하십시오.

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

웹 URL ( http또는 https) 만 확인하려면 다음을 사용하십시오.

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

24
그것은 작동하지 않습니다 'http://:5984/asdf' =~ URI::regexp'http::5984/asdf' =~ URI::regexp모두 0을 반환 나는 그들 중 누구도 유효한 URI가 없기 때문에 전무를 반환하도록 기대했다.
awendt 2011

4
localhost의 : 5984 포트 5984가 아닌가요?
mxcl

3
실제로 변수에 유효한 URL이 포함되어 있는지 확인합니다. " example com"을 유효한 URL로 허용합니다. 하나가 포함되어 있기 때문입니다. 그러나 모든 것이 URL이 될 것으로 예상하면 도움이되지 않습니다.
Alexander Günther

2
gotqn : RFC 1738에 따르면 유효한 URL이 아닙니다.
Mikael S

12
이것을 사용하지 마십시오 "http:".이 정규식 을 통과하는 것은 너무 나쁩니다 .
smathy apr

43

위의 답변과 유사하게이 정규식을 사용하면 약간 더 정확하다는 것을 알 수 있습니다.

URI::DEFAULT_PARSER.regexp[:ABS_URI]

URI.regexp어떤 이유로 공백을 허용하는 것과 반대로 공백이있는 URL은 무효화됩니다 .

최근에 다른 URI rgexp에 대해 제공되는 바로 가기를 찾았습니다. 에서 URI::DEFAULT_PARSER.regexp.keys직접 액세스 할 수 있습니다 URI::#{key}.

예를 들어 :ABS_URI정규 표현식은에서 액세스 할 수 있습니다 URI::ABS_URI.


3
언제든지 URI.parse를 사용할 계획이라면 이것이 확실히 갈 길입니다. URI :: regexp는 나중에 URI.parse를 사용할 때 실패 할 특정 URL과 일치합니다. 팁 고마워.
markquezada

안타깝게도 이것은 1.8이 아닌 Ruby 1.9에서만 사용할 수 있습니다.
Steve Madsen 2011 년

1
그러나 이것은 작동합니다 /^#{URI.regexp}$/. 문제는 URI.regexp고정되지 않는다는 것입니다. 공백이있는 문자열은 URI의 일부로 공백을 확인하는 것이 아니라 공백으로 이어지는 모든 것을 확인합니다. 해당 조각이 유효한 URI처럼 보이면 일치가 성공합니다.
Steve Madsen 2011 년

3
제안에 awendt의 의견을 적용하면 : 'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]nil이 아닌 0을 제공합니다. 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]0을 제공합니다. 'http://:5984/asdf' =~ /^#{URI.regexp}$/0을 제공합니다. 'http::5984/asdf' =~ /^#{URI.regexp}$/0도 제공합니다. 위의 정규 표현식 중 어느 것도 완전히 정확하지 않지만 매우 이상한 상황에서만 실패하며 대부분의 경우 큰 문제가 아닙니다.
skalee 2012 년

1
참고로, 다음 URI::DEFAULT_PARSER.regexp[:ABS_URI]과 동일합니다/\A\s*#{URI::regexp}\s*\z/
aidan

34

현재 답변의 문제점 은 URI가 URL이 아니라는 것 입니다.

URI는 로케이터, 이름 또는 둘 다로 추가로 분류 될 수 있습니다. "Uniform Resource Locator"(URL)라는 용어는 리소스를 식별하는 것 외에도 기본 액세스 메커니즘 (예 : 네트워크 "위치")을 설명하여 리소스를 찾는 수단을 제공하는 URI의 하위 집합을 의미합니다.

URL은 URI의 하위 집합이므로 특히 URI에 대한 일치는 원하지 않는 값과 성공적으로 일치한다는 것이 분명합니다. 예를 들어 URN은 다음과 같습니다.

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

즉, 내가 아는 한 Ruby에는 URL을 구문 분석하는 기본 방법이 없으므로 그렇게하려면 gem이 필요할 것입니다. 특별히 HTTP 또는 HTTPS 형식의 URL을 일치시켜야하는 경우 다음과 같이 할 수 있습니다.

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

@Philip 도움이되고 적절했습니다. 대단히 감사합니다!
fotanus 2013-08-09

2
uri.kind_of?(URI::HTTP)적어도 루비 1.9.3에서는 두 경우 모두 (http 및 https)에 충분합니다.
Andrea Salicetti 2014

여전히 jonuts의 대답에 따라 @skalee에 의해 설명하는 문제 고통
akostadinov

1
요약하면 URI.parse(string_to_be_checked).kind_of?(URI::HTTP), 일을 잘 수행합니다.
ben

19

나는 Addressable gem을 선호합니다 . 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

3
방금 Addressable :: URI.parse ()에 가장 이상한 문자열을 제공하여 거부하는 것을 확인했습니다. 그것은 미친 것들을 받아 들였습니다. 그러나 수락하지 않은 첫 번째 문자열은 ":-)"입니다. 흠.
mvw

1
어떻게 이렇게 많은 찬성표를 얻습니까? Addressable::URI.parse잘못된 입력으로 nil을 반환하지 않습니다.
garbagecollector

11

이것은 상당히 오래된 항목이지만 계속해서 기여할 것이라고 생각했습니다.

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

이제 다음과 같이 할 수 있습니다.

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

2
이것은 위의 솔루션보다 훨씬 잘 작동 합니다. 위에 나열된주의 사항이 없으며 javascript : alert ( 'spam')과 같은 URI도 허용하지 않습니다.
bchurchill 2013

2
그러나 그것은 또한 http:/당신이 원하는 것이 아닐 수도 있습니다.
Bo Jeanes 2013

10

나를 위해 다음 정규식을 사용합니다.

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

선택권:

  • i -대소 문자 구분 안함
  • x -정규식의 공백 무시

이 방법을 설정하여 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

그것을 사용하려면 :

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

잘못된 URL로 테스트 :

  • http://ruby3arabi -결과가 잘못되었습니다.
  • http://http://ruby3arabi.com -결과가 잘못되었습니다.
  • http:// -결과가 잘못되었습니다.

올바른 URL로 테스트 :

  • http://ruby3arabi.com -결과가 유효합니다
  • http://www.ruby3arabi.com -결과가 유효합니다
  • https://www.ruby3arabi.com -결과가 유효합니다
  • https://www.ruby3arabi.com/article/1 -결과가 유효합니다
  • https://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en -결과가 유효합니다

다음은 유효한 것으로 표시됩니다. "http://test.com\n<script src=\"nasty.js\">", 5 자보다 길거나 두 개 이상의 연속 하이픈 이있는 683 TLD 중 하나를 사용하는 모든 도메인 은 유효하지 않은 것으로 표시됩니다. 0-65535 범위를 벗어난 포트 번호가 허용됩니다. FTP 및 IP 주소는 분명히 허용되지 않지만 주목할 가치가 있습니다.
aidan nov.

1
빠른 URL 확인을 위해 여기에서 가장 적합한 솔루션입니다. 감사
somedirection

4

이것은 조금 오래되었지만 여기에 내가하는 방법입니다. Ruby의 URI 모듈을 사용하여 URL을 구문 분석하십시오. 파싱 ​​할 수 있으면 유효한 URL입니다. (그러나 그것이 접근 가능하다는 것을 의미하지는 않습니다.)

URI는 다양한 체계를 지원하며 사용자 지정 체계를 직접 추가 할 수 있습니다.

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 모듈에 대한 자세한 정보 는 문서 를 참조하십시오 .


나는 segfault를 고치려고 이것을 우연히 만났습니다. URI.parse실제로 Ruby 2.5.5에서 사용하는 것이 원인이었습니다. 이상한 경우가 발생해도 괜찮다면 아래 @jonuts 답변으로 전환했습니다. 내 목적을 위해 나는 상관하지 않았으므로 이상적이었습니다.
el n00b

3

일반적으로

/^#{URI::regexp}$/

잘 작동하지만 http또는 일치하는 경우에만 https옵션으로 메서드에 전달할 수 있습니다.

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

.NET과 같은 프로토콜을 거부하려는 경우 약간 더 잘 작동하는 경향이 있습니다 ftp://.


-2

이 정규식이 정확하다고 가정하면 http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm 과 같은 정규식을 사용할 수도 있습니다 (완전히 확인하지 않았습니다). 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
}

위의 예는 다음을 출력합니다.

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

5
mailto 체계는 어떻습니까? 아니면 telnet, gopher, nntp, rsync, ssh 또는 다른 체계 중 하나? URL은 HTTP 및 FTP보다 조금 더 복잡합니다.
MU이 너무 짧

URL을 확인하기 위해 정규식을 작성하는 것은 어렵습니다. 왜 귀찮게?
Rimian

@Rimian, 할 URI수있는 모든 것이 실제로 깨지기 때문에 귀찮게해야합니다 . 위의 많은 찬성 답변에서 댓글을 참조하십시오. Janie의 대답이 옳은지는 확실하지 않지만 찬성 투표를하므로 사람들이 더 진지하게 생각합니다. TBH url.start_with?("http://") || url.start_with?("https://")HTTP 만 필요하고 사용자가 적절한 URL을 사용해야하기 때문에 결국 수행 하게됩니다.
akostadinov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.