Fix: SafeURI normalize and eql? to work as expected

normalize wasn't doing what was expected (URI.normalize)
also make sure SafeURI can be stored in Hash (proper eql?)

Fixes #11443
This commit is contained in:
Karol Bucek 2019-12-17 14:23:49 +01:00
parent ded1749e76
commit 97b2273b39
2 changed files with 72 additions and 4 deletions

View file

@ -45,9 +45,14 @@ class LogStash::Util::SafeURI
make_uri(scheme, user_info, host, port, path, query, fragment)
end
def ==(other)
def hash
@uri.hash * 11
end
def eql?(other)
other.is_a?(::LogStash::Util::SafeURI) ? @uri == other.uri : false
end
alias == eql?
def clone
# No need to clone the URI, in java its immutable
@ -144,13 +149,13 @@ class LogStash::Util::SafeURI
# Same algorithm as Ruby's URI class uses
def normalize!
if path && path == ''
path = '/'
update(:path, '/')
end
if scheme && scheme != scheme.downcase
scheme = self.scheme.downcase
update(:scheme, self.scheme.downcase)
end
if host && host != host.downcase
host = self.host.downcase
update(:host, self.host.downcase)
end
end

View file

@ -17,6 +17,22 @@ module LogStash module Util
end
end
describe "equality" do
subject { LogStash::Util::SafeURI.new("https://localhost:9200/uri") }
it "should eql/== to dup" do
expect(subject == subject.clone).to be true
expect(subject == subject.dup).to be true
expect(subject.eql? subject.dup).to be true
end
it "should eql to same uri" do
uri = LogStash::Util::SafeURI.new("https://localhost:9200/uri")
expect(uri.eql? subject).to be true
expect(subject.hash).to eql uri.hash
end
end
describe "handling escapable fields" do
let(:user) { "u%20" }
let(:password) { "p%20ss" }
@ -72,5 +88,52 @@ module LogStash module Util
end
end
end
describe "normalization" do
subject { LogStash::Util::SafeURI.new("HTTPS://FOO:BaR@S11.ORG") }
it "should normalize" do # like URI().normalize
subject.normalize!
expect(subject.to_s).to eq('https://FOO:xxxxxx@s11.org/')
end
end
describe "writers" do
subject { LogStash::Util::SafeURI.new("http://sample.net") }
it "should update :user" do
subject.user = 'user'
expect(subject.user).to eq('user')
expect(subject.to_s).to eq('http://user@sample.net/')
end
it "should update :password" do
subject.user = 'user'
subject.password = 'pass'
expect(subject.password).to eq('pass')
end
it "should update :path" do
subject.path = '/path'
expect(subject.path).to eq('/path')
expect(subject.to_s).to eq('http://sample.net/path')
subject.path = ''
expect(subject.path).to eq('/')
expect(subject.to_s).to eq('http://sample.net/')
end
it "should update :host" do
subject.host = '127.0.0.1'
expect(subject.host).to eq('127.0.0.1')
expect(subject.to_s).to eq('http://127.0.0.1/')
end
it "should update :scheme" do
subject.update(:scheme, 'https')
expect(subject.scheme).to eq('https')
expect(subject.to_s).to eq('https://sample.net/')
end
end
end
end end