답변:
URL 유효성 검사는 까다로운 작업입니다. 또한 매우 광범위한 요청입니다.
정확히 무엇을 하시겠습니까? URL 형식, 존재 여부 또는 무엇을 확인 하시겠습니까? 수행하려는 작업에 따라 몇 가지 가능성이 있습니다.
정규식은 URL 형식의 유효성을 검사 할 수 있습니다. 그러나 복잡한 정규식조차도 유효한 URL을 처리하고 있는지 확인할 수 없습니다.
예를 들어 간단한 정규 표현식을 사용하면 다음 호스트를 거부 할 것입니다.
http://invalid##host.com
그러나 그것은 허용 할 것입니다
http://invalid-host.foo
유효한 호스트이지만 기존 TLD를 고려할 경우 유효한 도메인이 아닙니다. 실제로 다음 항목이 유효한 호스트 이름이므로 도메인이 아닌 호스트 이름을 확인하려는 경우 솔루션이 작동합니다.
http://host.foo
다음 중 하나
http://localhost
이제 몇 가지 해결책을 드리겠습니다.
도메인의 유효성을 검사하려면 정규식을 잊어야합니다. 현재 사용 가능한 최상의 솔루션은 Mozilla에서 관리하는 목록 인 Public Suffix List입니다. Public Suffix List에 대해 도메인을 구문 분석하고 유효성을 검사하기 위해 Ruby 라이브러리를 만들었으며 PublicSuffix 라고합니다. 합니다.
URI / URL의 형식을 검증하려면 정규식을 사용할 수 있습니다. 하나를 검색하는 대신 내장 Ruby URI.parse
메서드를 사용하십시오 .
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
더 제한적으로 만들 수도 있습니다. 예를 들어 URL이 HTTP / HTTPS URL이되도록하려면 유효성 검사를 더 정확하게 만들 수 있습니다.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
물론 경로 또는 구성표 확인을 포함하여이 방법에 적용 할 수있는 많은 개선 사항이 있습니다.
마지막으로이 코드를 유효성 검사기로 패키징 할 수도 있습니다.
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
def validate_each(record, attribute, value)
unless value.present? && self.class.compliant?(value)
record.errors.add(attribute, "is not a valid HTTP URL")
end
end
end
# in the model
validates :example_attribute, http_url: true
URI::HTTPS
https uris (예 :URI.parse("https://yo.com").class => URI::HTTPS
URI::HTTPS
상속 URI:HTTP
, 그것이 내가 사용하는 이유 kind_of?
입니다.
URI.parse('http://invalid-host.foo')
해당 URI가 유효한 URL이기 때문에 true를 반환합니다. 또한 .foo
이제 유효한 TLD입니다. iana.org/domains/root/db/foo.html
Simone의 아이디어에 따라 자신 만의 유효성 검사기를 쉽게 만들 수 있습니다.
class UrlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.blank?
begin
uri = URI.parse(value)
resp = uri.kind_of?(URI::HTTP)
rescue URI::InvalidURIError
resp = false
end
unless resp == true
record.errors[attribute] << (options[:message] || "is not an url")
end
end
end
그런 다음
validates :url, :presence => true, :url => true
모델에서.
URI("http:").kind_of?(URI::HTTP) #=> true
도 있습니다 validate_url 보석 단지 멋진 래퍼 (Addressable::URI.parse
솔루션).
그냥 추가
gem 'validate_url'
에 추가 Gemfile
한 다음 모델에서
validates :click_through_url, url: true
이 질문은 이미 답변되어 있지만 도대체 내가 사용하는 솔루션을 제안합니다.
정규식은 내가 만난 모든 URL에서 잘 작동합니다. setter 방법은 프로토콜이 언급되지 않은 경우 처리하는 것입니다 (http : //로 가정).
마지막으로 페이지를 가져 오려고합니다. HTTP 200 OK뿐만 아니라 리디렉션을 수락해야 할 수도 있습니다.
# app/models/my_model.rb
validates :website, :allow_blank => true, :uri => { :format => /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix }
def website= url_str
unless url_str.blank?
unless url_str.split(':')[0] == 'http' || url_str.split(':')[0] == 'https'
url_str = "http://" + url_str
end
end
write_attribute :website, url_str
end
과...
# app/validators/uri_vaidator.rb
require 'net/http'
# Thanks Ilya! http://www.igvita.com/2006/09/07/validating-url-in-ruby-on-rails/
# Original credits: http://blog.inquirylabs.com/2006/04/13/simple-uri-validation/
# HTTP Codes: http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html
class UriValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
raise(ArgumentError, "A regular expression must be supplied as the :format option of the options hash") unless options[:format].nil? or options[:format].is_a?(Regexp)
configuration = { :message => I18n.t('errors.events.invalid_url'), :format => URI::regexp(%w(http https)) }
configuration.update(options)
if value =~ configuration[:format]
begin # check header response
case Net::HTTP.get_response(URI.parse(value))
when Net::HTTPSuccess then true
else object.errors.add(attribute, configuration[:message]) and false
end
rescue # Recover on DNS failures..
object.errors.add(attribute, configuration[:message]) and false
end
else
object.errors.add(attribute, configuration[:message]) and false
end
end
end
valid_url 을 사용해 볼 수도 있습니다.스키마없이 URL을 허용하고 도메인 영역과 ip-hostnames를 확인하는 gem을 .
Gemfile에 추가하십시오.
gem 'valid_url'
그리고 모델에서 :
class WebSite < ActiveRecord::Base
validates :url, :url => true
end
내 2 센트 :
before_validation :format_website
validate :website_validator
private
def format_website
self.website = "http://#{self.website}" unless self.website[/^https?/]
end
def website_validator
errors[:website] << I18n.t("activerecord.errors.messages.invalid") unless website_valid?
end
def website_valid?
!!website.match(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-=\?]*)*\/?$/)
end
편집 : 매개 변수 URL과 일치하도록 정규식을 변경했습니다.
http://test.com/fdsfsdf?a=b
나를 위해 일한 솔루션은 다음과 같습니다.
validates_format_of :url, :with => /\A(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?\Z/i
첨부 한 예제 중 일부를 사용하려고 시도했지만 다음과 같이 URL을 지원하고 있습니다.
^ 및 $를 사용하면 Rails 유효성 검사기에서이 경고 보안을 볼 수 있으므로 A와 Z를 사용하는 것에 유의하십시오.
Valid ones:
'www.crowdint.com'
'crowdint.com'
'http://crowdint.com'
'http://www.crowdint.com'
Invalid ones:
'http://www.crowdint. com'
'http://fake'
'http:fake'
"https://portal.example.com/portal/#"
. Ruby 2.1.6에서는 평가가 중단됩니다.
최근에 동일한 문제가 발생했지만 (Rails 앱에서 URL의 유효성을 검사해야했습니다) 유니 코드 URL의 추가 요구 사항 (예 : http://кц.рф
...
몇 가지 솔루션을 조사하고 다음을 발견했습니다.
URI.parse
. 자세한 내용은 Simone Carletti의 답변을 확인하십시오. 이것은 정상적으로 작동하지만 유니 코드 URL에는 적용되지 않습니다.URI.parse
사용하는 것과 비슷한 접근 방식 입니다. 이 접근 방식은 http://rawsyntax.com/blog/url-validation-in-rails-3-and-ruby-in-general/에 자세히 설명되어 있습니다.addressable
URI
Addressable::URI.parse('http:///').scheme # => "http"
나 Addressable::URI.parse('Съешь [же] ещё этих мягких французских булок да выпей чаю')
완벽하게 :( 뷰의 어드레스로의 시점에서 확인된다
다음은 David James가 게시 한 유효성 검사기 의 업데이트 된 버전입니다 . 그것은 된 벤자민 플라이셔에 의해 출판 . 한편, 여기 에서 찾을 수있는 업데이트 된 포크를 푸시했습니다 .
require 'addressable/uri'
# Source: http://gist.github.com/bf4/5320847
# Accepts options[:message] and options[:allowed_protocols]
# spec/validators/uri_validator_spec.rb
class UriValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
uri = parse_uri(value)
if !uri
record.errors[attribute] << generic_failure_message
elsif !allowed_protocols.include?(uri.scheme)
record.errors[attribute] << "must begin with #{allowed_protocols_humanized}"
end
end
private
def generic_failure_message
options[:message] || "is an invalid URL"
end
def allowed_protocols_humanized
allowed_protocols.to_sentence(:two_words_connector => ' or ')
end
def allowed_protocols
@allowed_protocols ||= [(options[:allowed_protocols] || ['http', 'https'])].flatten
end
def parse_uri(value)
uri = Addressable::URI.parse(value)
uri.scheme && uri.host && uri
rescue URI::InvalidURIError, Addressable::URI::InvalidURIError, TypeError
end
end
...
require 'spec_helper'
# Source: http://gist.github.com/bf4/5320847
# spec/validators/uri_validator_spec.rb
describe UriValidator do
subject do
Class.new do
include ActiveModel::Validations
attr_accessor :url
validates :url, uri: true
end.new
end
it "should be valid for a valid http url" do
subject.url = 'http://www.google.com'
subject.valid?
subject.errors.full_messages.should == []
end
['http://google', 'http://.com', 'http://ftp://ftp.google.com', 'http://ssh://google.com'].each do |invalid_url|
it "#{invalid_url.inspect} is a invalid http url" do
subject.url = invalid_url
subject.valid?
subject.errors.full_messages.should == []
end
end
['http:/www.google.com','<>hi'].each do |invalid_url|
it "#{invalid_url.inspect} is an invalid url" do
subject.url = invalid_url
subject.valid?
subject.errors.should have_key(:url)
subject.errors[:url].should include("is an invalid URL")
end
end
['www.google.com','google.com'].each do |invalid_url|
it "#{invalid_url.inspect} is an invalid url" do
subject.url = invalid_url
subject.valid?
subject.errors.should have_key(:url)
subject.errors[:url].should include("is an invalid URL")
end
end
['ftp://ftp.google.com','ssh://google.com'].each do |invalid_url|
it "#{invalid_url.inspect} is an invalid url" do
subject.url = invalid_url
subject.valid?
subject.errors.should have_key(:url)
subject.errors[:url].should include("must begin with http or https")
end
end
end
유효한 주소로 구문 분석 된 이상한 HTTP URI가 여전히 있습니다.
http://google
http://.com
http://ftp://ftp.google.com
http://ssh://google.com
다음은 예제를 다루는 gem에 대한 문제입니다addressable
.
위의 lafeber 솔루션 에 약간의 변형을 사용합니다 . 호스트 이름에 연속 된 점 (예 :)을 허용하지 않습니다 www.many...dots.com
.
%r"\A(https?://)?[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]{2,6}(/.*)?\Z"i
URI.parse
어떤 경우에는 당신이 할 수 있습니다 무엇을하지 않은, 구성표 추가하는 설정을 의무화하는 것 (예를 들어, 당신이 당신의 사용자가 신속하게 같은 형태의 URL을 철자를 허용 할 경우 twitter.com/username
)
나는 'activevalidators'젬을 사용 하고 있으며 꽤 잘 작동합니다 (URL 유효성 검사뿐만 아니라)
모두 문서화되어 있지만 기본적으로 gem이 추가되면 이니셜 라이저에 다음과 같은 몇 줄을 추가 할 수 있습니다. /config/environments/initializers/active_validators_activation.rb
# Activate all the validators
ActiveValidators.activate(:all)
(참고 : 특정 유형의 값을 확인하려는 경우 : all을 : url 또는 : whatever로 바꿀 수 있습니다)
그런 다음 다음과 같이 모델로 돌아갑니다.
class Url < ActiveRecord::Base
validates :url, :presence => true, :url => true
end
이제 서버를 다시 시작 하고 그것을해야
https://github.com/perfectline/validates_url 은 당신을 위해 거의 모든 것을 할 수있는 멋지고 간단한 보석입니다.
최근에 동일한 문제가 발생하여 유효한 URL에 대한 해결 방법을 찾았습니다.
validates_format_of :url, :with => URI::regexp(%w(http https))
validate :validate_url
def validate_url
unless self.url.blank?
begin
source = URI.parse(self.url)
resp = Net::HTTP.get_response(source)
rescue URI::InvalidURIError
errors.add(:url,'is Invalid')
rescue SocketError
errors.add(:url,'is Invalid')
end
end
validate_url 메소드의 첫 번째 부분은 URL 형식을 검증하기에 충분합니다. 두 번째 부분은 요청을 보내 URL이 존재하는지 확인합니다.
그리고 모듈로
module UrlValidator
extend ActiveSupport::Concern
included do
validates :url, presence: true, uniqueness: true
validate :url_format
end
def url_format
begin
errors.add(:url, "Invalid url") unless URI(self.url).is_a?(URI::HTTP)
rescue URI::InvalidURIError
errors.add(:url, "Invalid url")
end
end
end
그런 다음 include UrlValidator
URL의 유효성을 검사하려는 모든 모델에서. 옵션을 포함합니다.
웹 사이트 수가 계속 증가하고 새로운 도메인 명명 체계가 계속 등장하기 때문에 정규 표현식을 사용하여 URL 유효성 검사를 간단히 처리 할 수 없습니다.
제 경우에는 성공적인 응답을 확인하는 사용자 지정 유효성 검사기를 작성합니다.
class UrlValidator < ActiveModel::Validator
def validate(record)
begin
url = URI.parse(record.path)
response = Net::HTTP.get(url)
true if response.is_a?(Net::HTTPSuccess)
rescue StandardError => error
record.errors[:path] << 'Web address is invalid'
false
end
end
end
path
을 사용하여 내 모델 의 속성을 확인하고 record.path
있습니다. 또한을 사용하여 각 속성 이름에 오류를 푸시하고 record.errors[:path]
있습니다.
이를 속성 이름으로 간단히 바꿀 수 있습니다.
그런 다음 모델에서 사용자 지정 유효성 검사기를 호출하기 만하면됩니다.
class Url < ApplicationRecord
# validations
validates_presence_of :path
validates_with UrlValidator
end
나를 위해 정규식을 사용할 수 있습니다.
(^|[\s.:;?\-\]<\(])(ftp|https?:\/\/[-\w;\/?:@&=+$\|\_.!~*\|'()\[\]%#,]+[\w\/#](\(\))?)(?=$|[\s',\|\(\).:;?\-\[\]>\)])