require 'spec_helper' URIS_WITHOUT_PATH_OR_PARAMS = [ "www.example.com", "www.example.com/", "www.example.com:80", "www.example.com:80/", "http://www.example.com", "http://www.example.com/", "http://www.example.com:80", "http://www.example.com:80/" ].sort URIS_WITHOUT_PATH_BUT_WITH_PARAMS = [ "www.example.com?a=b", "www.example.com/?a=b", "www.example.com:80?a=b", "www.example.com:80/?a=b", "http://www.example.com?a=b", "http://www.example.com/?a=b", "http://www.example.com:80?a=b", "http://www.example.com:80/?a=b" ].sort URIS_WITH_AUTH = [ "a b:pass@www.example.com", "a b:pass@www.example.com/", "a b:pass@www.example.com:80", "a b:pass@www.example.com:80/", "http://a b:pass@www.example.com", "http://a b:pass@www.example.com/", "http://a b:pass@www.example.com:80", "http://a b:pass@www.example.com:80/", "a%20b:pass@www.example.com", "a%20b:pass@www.example.com/", "a%20b:pass@www.example.com:80", "a%20b:pass@www.example.com:80/", "http://a%20b:pass@www.example.com", "http://a%20b:pass@www.example.com/", "http://a%20b:pass@www.example.com:80", "http://a%20b:pass@www.example.com:80/" ].sort URIS_WITH_PATH_AND_PARAMS = [ "www.example.com/my path/?a=my param&b=c d", "www.example.com/my%20path/?a=my%20param&b=c%20d", "www.example.com:80/my path/?a=my param&b=c d", "www.example.com:80/my%20path/?a=my%20param&b=c%20d", "http://www.example.com/my path/?a=my param&b=c d", "http://www.example.com/my%20path/?a=my%20param&b=c%20d", "http://www.example.com:80/my path/?a=my param&b=c d", "http://www.example.com:80/my%20path/?a=my%20param&b=c%20d", ].sort URIS_WITH_DIFFERENT_PORT = [ "www.example.com:88", "www.example.com:88/", "http://www.example.com:88", "http://www.example.com:88/" ].sort URIS_FOR_HTTPS = [ "https://www.example.com", "https://www.example.com/", "https://www.example.com:443", "https://www.example.com:443/" ].sort URIS_FOR_LOCALHOST = [ "localhost", "localhost/", "localhost:80", "localhost:80/", "http://localhost", "http://localhost/", "http://localhost:80", "http://localhost:80/" ].sort URIS_WITH_SCHEME = [ "http://www.example.com", "http://www.example.com/", "http://www.example.com:80", "http://www.example.com:80/" ].sort URIS_WITH_COLON_IN_PATH = [ [ "https://example.com/a/b:80", "https://example.com:443/a/b:80", ].sort, [ "https://example.com:443/a/b:443", "https://example.com/a/b:443", ].sort, [ "http://example.com/a/b:443", "example.com/a/b:443", "http://example.com:80/a/b:443", "example.com:80/a/b:443", ].sort, [ "http://example.com/a/b:80", "example.com/a/b:80", "http://example.com:80/a/b:80", "example.com:80/a/b:80", ].sort ] describe WebMock::Util::URI do describe "reporting variations of uri" do it "should find all variations of the same uri for all variations of uri with params and path" do URIS_WITH_PATH_AND_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_PATH_AND_PARAMS) end end it "should find all variations of the same uri for all variations of uri with params but without path" do URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITHOUT_PATH_BUT_WITH_PARAMS) end end it "should find all variations of the same uri for all variations of uri without params or path" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITHOUT_PATH_OR_PARAMS) end end it "should find all variations of the same uri for all variations of uri with auth" do URIS_WITH_AUTH.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_AUTH) end end it "should find all variations of the same uri for all variations of uri with different port" do URIS_WITH_DIFFERENT_PORT.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_DIFFERENT_PORT) end end it "should find all variations of the same uri for all variations of https uris" do URIS_FOR_HTTPS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_FOR_HTTPS) end end it "should find all variations of the same uri for all variations of host names uris without a period" do URIS_FOR_LOCALHOST.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_FOR_LOCALHOST) end end it "should find all variations of the same uri with scheme for all variations when only_with_scheme is true" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri| variations_of_uri_with_scheme = WebMock::Util::URI.variations_of_uri_as_strings(uri, only_with_scheme: true) expect(variations_of_uri_with_scheme.sort).to eq(URIS_WITH_SCHEME) end end it "should not replace :80 or :443 in path" do URIS_WITH_COLON_IN_PATH.each do |uris| uris.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(uris) end end end it "should find all variations of uris with https, basic auth, a non-standard port and a path" do uri = "https://~%8A:pass@www.example.com:9000/foo" variations = [ "https://~%8A:pass@www.example.com:9000/foo", "https://~\x8A:pass@www.example.com:9000/foo".force_encoding(Encoding::ASCII_8BIT) ] expect(WebMock::Util::URI.variations_of_uri_as_strings(uri)).to eq(variations) end end describe "normalized uri equality" do it "should successfully compare all variations of the same uri with path and params" do URIS_WITH_PATH_AND_PARAMS.each do |uri_a| URIS_WITH_PATH_AND_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri with path but with params" do URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri_a| URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri without path or params" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri_a| URIS_WITHOUT_PATH_OR_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri with authority" do URIS_WITH_AUTH.each do |uri_a| URIS_WITH_AUTH.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri custom port" do URIS_WITH_DIFFERENT_PORT.each do |uri_a| URIS_WITH_DIFFERENT_PORT.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same https uri" do URIS_FOR_HTTPS.each do |uri_a| URIS_FOR_HTTPS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully handle array parameters" do uri_string = 'http://www.example.com:80/path?a[]=b&a[]=c' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"a"=>["b", "c"]}) end it "should successfully handle hash parameters" do uri_string = 'http://www.example.com:80/path?a[d]=b&a[e]=c&a[b][c]=1' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"a"=>{"d"=>"b", "e"=>"c", "b"=>{"c"=>"1"}}}) end it "should successfully handle nested hash parameters" do uri_string = 'http://www.example.com:80/path?one[two][three][]=four&one[two][three][]=five' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"one"=>{"two"=>{"three" => ["four", "five"]}}}) end it "should successfully handle mixed array and hash parameters" do # derived from an elasticsearch query: # load => { # :include => [ # { :staff => :email }, # :business_name # ] # } uri_string = "http://www.example.com:80/path?load[include][][staff]=email&load[include][]=business_name" uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"load"=>{"include"=>[{"staff"=>"email"},"business_name"]}}) end context "when query notation is set to :flat_array" do before :all do WebMock::Config.instance.query_values_notation = :flat_array end it "should successfully handle repeated paramters" do uri_string = "http://www.example.com:80/path?target=host1&target=host2" uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query, notation: WebMock::Config.instance.query_values_notation)).to eq([['target', 'host1'], ['target', 'host2']]) end end end describe "sorting query values" do context "when query values is a Hash" do it "returns an alphabetically sorted hash" do sorted_query = WebMock::Util::URI.sort_query_values({"b"=>"one", "a"=>"two"}) expect(sorted_query).to eq({"a"=>"two", "b"=>"one"}) end end context "when query values is an Array" do it "returns an alphabetically sorted array" do sorted_query = WebMock::Util::URI.sort_query_values([["b","two"],["a","one_b"],["a","one_a"]]) expect(sorted_query).to eq([["a","one_a"],["a","one_b"],["b","two"]]) end end end describe "stripping default port" do it "should strip_default_port_from_uri strips 80 from http with path" do uri = "http://example.com:80/foo/bar" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("http://example.com/foo/bar") end it "should strip_default_port_from_uri strips 80 from http without path" do uri = "http://example.com:80" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("http://example.com") end it "should strip_default_port_from_uri strips 443 from https without path" do uri = "https://example.com:443" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("https://example.com") end it "should strip_default_port_from_uri strips 443 from https" do uri = "https://example.com:443/foo/bar" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("https://example.com/foo/bar") end it "should strip_default_port_from_uri does not strip 8080 from http" do uri = "http://example.com:8080/foo/bar" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not strip 443 from http" do uri = "http://example.com:443/foo/bar" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not strip 80 from query string" do uri = "http://example.com/?a=:80&b=c" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not modify strings that do not start with http or https" do uri = "httpz://example.com:80/" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end end describe "encoding userinfo" do it "should encode unsafe chars in userinfo does not encode userinfo safe punctuation" do userinfo = "user;&=+$,:secret" expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(userinfo) end it "should encode unsafe chars in userinfo does not encode rfc 3986 unreserved characters" do userinfo = "-.!~*'()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:secret" expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(userinfo) end it "should encode unsafe chars in userinfo does encode other characters" do userinfo, safe_userinfo = 'us#rn@me:sec//ret?"', 'us%23rn%40me:sec%2F%2Fret%3F%22' expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(safe_userinfo) end end end