Rails: 링크(URL)를 검증하는 좋은 방법은 무엇입니까?
레일즈에서 URL을 어떻게 검증하는 것이 가장 좋을지 궁금합니다.정규 표현을 사용하려고 했는데 이게 최선의 방법인지 모르겠어요.
그리고, 만약 제가 정규식을 사용한다면, 누가 저에게 하나 제안해주실 수 있나요?나는 아직 Regex에 익숙하지 않습니다.
URL의 유효성을 검사하는 것은 까다로운 작업입니다.그것은 또한 매우 광범위한 요청입니다.
정확히 무엇을 하고 싶습니까?URL 형식, 존재 또는 무엇을 검증하시겠습니까?당신이 하고 싶은 일에 따라 몇 가지 가능성이 있습니다.
정규식은 URL 형식의 유효성을 검사할 수 있습니다.그러나 복잡한 정규식도 유효한 URL을 처리할 수 없습니다.
예를 들어 간단한 정규식을 사용하면 다음 호스트가 거부될 수 있습니다.
http://invalid##host.com
하지만 그것은 허락할 것입니다.
http://invalid-host.foo
이는 유효한 호스트이지만 기존 TLD를 고려할 때 유효한 도메인은 아닙니다.실제로 솔루션은 도메인이 아닌 호스트 이름의 유효성을 확인하려는 경우 작동합니다. 도메인이 유효한 호스트 이름이기 때문입니다.
http://host.foo
다음 것과 마찬가지로
http://localhost
이제, 몇 가지 해결책을 드리겠습니다.
도메인의 유효성을 검사하려면 정규식을 잊어야 합니다.현재 사용 가능한 최고의 솔루션은 Mozilla가 관리하는 목록인 공개 접미사 목록입니다.공용 접미사 목록에 대한 도메인을 분석하고 검증하기 위해 루비 라이브러리를 만들었습니다. 이 라이브러리는 공용 접미사 목록이라고 합니다.
URI/URL 형식의 유효성을 검사하려면 정규식을 사용해야 합니다.된 Ruby 검를색는대내장신 Ruby 다니합사를 하세요.URI.parse
방법.
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && uri.host.present?
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.present?
rescue URI::InvalidURIError
false
end
물론, 이 방법에 적용할 수 있는 개선 사항은 경로 또는 계획 확인을 포함하여 매우 많습니다.
마지막으로, 이 코드를 검증자로 패키지화할 수도 있습니다.
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && uri.host.present?
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 버전(예: 0.12.1)에 대한 참고 사항
.present?
/.blank?
를 사용하는 대신 호스트를 검증하는 더 정확한 방법이 될 것입니다.uri.host.nil?
아니면 그냥if uri.host
이전 버전(예: URI v 0.11).
URI.parse("https:///394")의 예:
- 버전 새URI 전버(0.12),
host
문자열을 하고, " " " " 를 반환합니다./394
경로됩니다. HTTPS >#<URI::HTTPS https://394> - 버전 이전 URI 버전(0.11),
host
문자열을 하고, " " " " 를 반환합니다./394
길되도합니다기이. HTTPS >#<URI::HTTPS https:/394>
저는 모델 내부에 하나의 라이너를 사용합니다.
validates :url, format: URI::DEFAULT_PARSER.make_regexp(%w[http https])
저는 사용하기에 충분하고 간단하다고 생각합니다.또한 내부적으로 매우 동일한 regexp를 사용하기 때문에 이론적으로 Simone의 방법과 동등해야 합니다.
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
당신 모델에서.
validate_url gem도 있습니다(이것은 단지 좋은 포장지일 뿐입니다).Addressable::URI.parse
해결책).
그냥 추가
gem 'validate_url'
의 신에게에.Gemfile
그리고 모델에서 당신은 할 수 있습니다.
validates :click_through_url, url: true
이 질문에는 이미 답이 나와 있습니다만, 도대체 제가 사용하고 있는 해결책을 제안합니다.
regexp는 내가 만난 모든 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
저에게 효과적인 솔루션은 다음과 같습니다.
validates_format_of :url, :with => /\A(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?\Z/i
당신이 첨부한 예시 중 일부를 사용하려고 했지만, 저는 그렇게 url을 지원하고 있습니다.
^과 $를 사용하면 레일 검사기에서 이 경고 보안을 볼 수 있으므로 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'
또한 valid_url gem을 사용하여 체계 없이 URL을 허용하고 도메인 영역 및 IP-hostname을 확인할 수 있습니다.
Gem 파일에 추가:
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과 일치하도록 정규식이 변경되었습니다.
함). URL의 사항( Rails URL(Rails URL))을 해결해야 . 하지만 유니코드 URL의 추가 요구 사항(예:http://кц.рф
)...
몇 가지 솔루션을 조사한 결과 다음과 같은 사실을 알게 되었습니다.
- 첫 번째이자 가장 많이 제안되는 것은 사용하는 것입니다.
URI.parse
자세한 내용은 Simone Carletti의 답변을 확인하십시오.이것은 정상적으로 작동하지만 유니코드 URL에는 작동하지 않습니다. - 제가 본 두 번째 방법은 Ilya Grigorik의 방법입니다: http://www.igvita.com/2006/09/07/validating-url-in-ruby-on-rails/ 기본적으로, 그는 URL에 요청을 하려고 합니다; 만약 그것이 효과가 있다면, 그것은 유효합니다...
- 세 제가은 제가찾세그방은법번째다방다음니접유법입근법사과한선은는제호하가고리▁to▁similar▁i▁the▁approach은그다▁an니)▁is제접▁method입다and▁third가▁(유▁i▁one▁the▁prefer음법근▁found사한과찾과 비슷한 방법입니다.
URI.parse
하지만 그것을 사용하는 것.addressable
대신URI
stdlib.이 접근 방식은 http://rawsyntax.com/blog/url-validation-in-rails-3-and-ruby-in-general/ 에서 자세히 설명합니다.
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
여기 예시를 다루는 보석에 대한 이슈가 있습니다.
나는 위의 고무 용액에 약간 변형을 사용합니다.호스트 이름에서 연속적인 점을 허용하지 않습니다(예: 의 경우).www.many...dots.com
):
%r"\A(https?://)?[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]{2,6}(/.*)?\Z"i
URI.parse
철자할 수 을 빨리 철자할 수 있도록 ) 스킴 접두사를 해야 하는 것 .twitter.com/username
)
나는 '능동적인 유효성 검사기' 보석을 사용해 왔고 그것은 꽤 잘 작동합니다(URL 유효성 검사뿐만 아니라).
여기서 찾을 수 있습니다.
모두 문서화되어 있지만 기본적으로 보석이 추가되면 이니셜라이저에 /config/environments/initializers/active_validators_activation.rb와 같은 몇 줄을 추가할 수 있습니다.
# Activate all the validators
ActiveValidators.activate(:all)
(참고: 특정 유형의 값만 확인하려는 경우 :all by :url 또는 :what로 대체할 수 있습니다.)
그리고 다시 당신의 모델로 돌아가서 이런 것.
class Url < ActiveRecord::Base
validates :url, :presence => true, :url => true
end
이제 서버를 다시 시작하면 됩니다.
단순 유효성 검사 및 사용자 지정 오류 메시지를 원하는 경우:
validates :some_field_expecting_url_value,
format: {
with: URI.regexp(%w[http https]),
message: 'is not a valid URL'
}
URI 모듈을 몽키패치하여 유효한 것을 추가하고 싶습니다.방법
東京의 config/initializers/uri.rb
module URI
def self.valid?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
end
다음과 같은 방법을 사용하여 여러 URL의 유효성을 검사할 수 있습니다.
validates_format_of [:field1, :field2], with: URI.regexp(['http', 'https']), allow_nil: true
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',\|\(\).:;?\-\[\]>\)])
URI::regexp(%w[http https])
사용되지 않으므로 사용해서는 안 됩니다.
대신 사용URI::DEFAULT_PARSER.make_regexp(%w[http https])
단순성 유지:
validates :url, format: %r{http(s)://.+}
HTTPS의 유효성을 검사하려면 다음을 사용할 수 있습니다.
require "uri"
class HttpsUrlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless valid_url?(value)
record.errors[attribute] << "is not a valid URL"
end
end
private
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTPS) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
end
모델에서 다음과 같은 용도:
validates :website_url, presence: true, https_url: true
언급URL : https://stackoverflow.com/questions/7167895/rails-whats-a-good-way-to-validate-links-urls
'programing' 카테고리의 다른 글
문자열 목록을 숫자로 정렬하는 방법은 무엇입니까? (0) | 2023.07.17 |
---|---|
코코아 포드가 설치되지 않았거나 잘못된 상태임 (0) | 2023.07.17 |
URL에서 반환된 Zip 파일 다운로드 (0) | 2023.07.17 |
Content-Type 헤더에 관계없이 Python Flask에서 원시 POST 본문 가져오기 (0) | 2023.07.17 |
C 표준 라이브러리의 위치 (0) | 2023.07.17 |