addressable 2.6.0 → 2.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +64 -0
- data/Gemfile +14 -16
- data/README.md +12 -10
- data/Rakefile +14 -8
- data/addressable.gemspec +28 -0
- data/lib/addressable/idna/native.rb +8 -3
- data/lib/addressable/idna/pure.rb +20 -191
- data/lib/addressable/idna.rb +0 -1
- data/lib/addressable/template.rb +37 -53
- data/lib/addressable/uri.rb +257 -176
- data/lib/addressable/version.rb +2 -3
- data/spec/addressable/idna_spec.rb +9 -7
- data/spec/addressable/net_http_compat_spec.rb +0 -1
- data/spec/addressable/security_spec.rb +0 -1
- data/spec/addressable/template_spec.rb +78 -265
- data/spec/addressable/uri_spec.rb +503 -208
- data/spec/spec_helper.rb +9 -0
- data/tasks/gem.rake +9 -7
- data/tasks/profile.rake +72 -0
- data/tasks/rspec.rake +1 -1
- metadata +16 -15
- data/spec/addressable/rack_mount_compat_spec.rb +0 -106
data/lib/addressable/template.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# encoding:utf-8
|
4
3
|
#--
|
5
4
|
# Copyright (C) Bob Aman
|
6
5
|
#
|
@@ -37,7 +36,7 @@ module Addressable
|
|
37
36
|
Addressable::URI::CharacterClasses::DIGIT + '_'
|
38
37
|
|
39
38
|
var_char =
|
40
|
-
"(
|
39
|
+
"(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
|
41
40
|
RESERVED =
|
42
41
|
"(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])"
|
43
42
|
UNRESERVED =
|
@@ -412,7 +411,7 @@ module Addressable
|
|
412
411
|
# match.captures
|
413
412
|
# #=> ["a", ["b", "c"]]
|
414
413
|
def match(uri, processor=nil)
|
415
|
-
uri = Addressable::URI.parse(uri)
|
414
|
+
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
|
416
415
|
mapping = {}
|
417
416
|
|
418
417
|
# First, we need to process the pattern, and extract the values.
|
@@ -653,50 +652,16 @@ module Addressable
|
|
653
652
|
self.to_regexp.named_captures
|
654
653
|
end
|
655
654
|
|
656
|
-
##
|
657
|
-
# Generates a route result for a given set of parameters.
|
658
|
-
# Should only be used by rack-mount.
|
659
|
-
#
|
660
|
-
# @param params [Hash] The set of parameters used to expand the template.
|
661
|
-
# @param recall [Hash] Default parameters used to expand the template.
|
662
|
-
# @param options [Hash] Either a `:processor` or a `:parameterize` block.
|
663
|
-
#
|
664
|
-
# @api private
|
665
|
-
def generate(params={}, recall={}, options={})
|
666
|
-
merged = recall.merge(params)
|
667
|
-
if options[:processor]
|
668
|
-
processor = options[:processor]
|
669
|
-
elsif options[:parameterize]
|
670
|
-
# TODO: This is sending me into fits trying to shoe-horn this into
|
671
|
-
# the existing API. I think I've got this backwards and processors
|
672
|
-
# should be a set of 4 optional blocks named :validate, :transform,
|
673
|
-
# :match, and :restore. Having to use a singleton here is a huge
|
674
|
-
# code smell.
|
675
|
-
processor = Object.new
|
676
|
-
class <<processor
|
677
|
-
attr_accessor :block
|
678
|
-
def transform(name, value)
|
679
|
-
block.call(name, value)
|
680
|
-
end
|
681
|
-
end
|
682
|
-
processor.block = options[:parameterize]
|
683
|
-
else
|
684
|
-
processor = nil
|
685
|
-
end
|
686
|
-
result = self.expand(merged, processor)
|
687
|
-
result.to_s if result
|
688
|
-
end
|
689
|
-
|
690
655
|
private
|
691
656
|
def ordered_variable_defaults
|
692
657
|
@ordered_variable_defaults ||= begin
|
693
658
|
expansions, _ = parse_template_pattern(pattern)
|
694
|
-
expansions.
|
659
|
+
expansions.flat_map do |capture|
|
695
660
|
_, _, varlist = *capture.match(EXPRESSION)
|
696
661
|
varlist.split(',').map do |varspec|
|
697
662
|
varspec[VARSPEC, 1]
|
698
663
|
end
|
699
|
-
end
|
664
|
+
end
|
700
665
|
end
|
701
666
|
end
|
702
667
|
|
@@ -927,25 +892,24 @@ module Addressable
|
|
927
892
|
# operator.
|
928
893
|
#
|
929
894
|
# @param [Hash, Array, String] value
|
930
|
-
# Normalizes keys and values with
|
895
|
+
# Normalizes unicode keys and values with String#unicode_normalize (NFC)
|
931
896
|
#
|
932
897
|
# @return [Hash, Array, String] The normalized values
|
933
898
|
def normalize_value(value)
|
934
|
-
unless value.is_a?(Hash)
|
935
|
-
value = value.respond_to?(:to_ary) ? value.to_ary : value.to_str
|
936
|
-
end
|
937
|
-
|
938
899
|
# Handle unicode normalization
|
939
|
-
if value.
|
940
|
-
value.map! { |val|
|
900
|
+
if value.respond_to?(:to_ary)
|
901
|
+
value.to_ary.map! { |val| normalize_value(val) }
|
941
902
|
elsif value.kind_of?(Hash)
|
942
903
|
value = value.inject({}) { |acc, (k, v)|
|
943
|
-
acc[
|
944
|
-
Addressable::IDNA.unicode_normalize_kc(v)
|
904
|
+
acc[normalize_value(k)] = normalize_value(v)
|
945
905
|
acc
|
946
906
|
}
|
947
907
|
else
|
948
|
-
value =
|
908
|
+
value = value.to_s if !value.kind_of?(String)
|
909
|
+
if value.encoding != Encoding::UTF_8
|
910
|
+
value = value.dup.force_encoding(Encoding::UTF_8)
|
911
|
+
end
|
912
|
+
value = value.unicode_normalize(:nfc)
|
949
913
|
end
|
950
914
|
value
|
951
915
|
end
|
@@ -973,15 +937,35 @@ module Addressable
|
|
973
937
|
end
|
974
938
|
end
|
975
939
|
|
940
|
+
##
|
941
|
+
# Generates the <tt>Regexp</tt> that parses a template pattern. Memoizes the
|
942
|
+
# value if template processor not set (processors may not be deterministic)
|
943
|
+
#
|
944
|
+
# @param [String] pattern The URI template pattern.
|
945
|
+
# @param [#match] processor The template processor to use.
|
946
|
+
#
|
947
|
+
# @return [Array, Regexp]
|
948
|
+
# An array of expansion variables nad a regular expression which may be
|
949
|
+
# used to parse a template pattern
|
950
|
+
def parse_template_pattern(pattern, processor = nil)
|
951
|
+
if processor.nil? && pattern == @pattern
|
952
|
+
@cached_template_parse ||=
|
953
|
+
parse_new_template_pattern(pattern, processor)
|
954
|
+
else
|
955
|
+
parse_new_template_pattern(pattern, processor)
|
956
|
+
end
|
957
|
+
end
|
958
|
+
|
976
959
|
##
|
977
960
|
# Generates the <tt>Regexp</tt> that parses a template pattern.
|
978
961
|
#
|
979
962
|
# @param [String] pattern The URI template pattern.
|
980
963
|
# @param [#match] processor The template processor to use.
|
981
964
|
#
|
982
|
-
# @return [Regexp]
|
983
|
-
#
|
984
|
-
|
965
|
+
# @return [Array, Regexp]
|
966
|
+
# An array of expansion variables nad a regular expression which may be
|
967
|
+
# used to parse a template pattern
|
968
|
+
def parse_new_template_pattern(pattern, processor = nil)
|
985
969
|
# Escape the pattern. The two gsubs restore the escaped curly braces
|
986
970
|
# back to their original form. Basically, escape everything that isn't
|
987
971
|
# within an expansion.
|
@@ -1037,7 +1021,7 @@ module Addressable
|
|
1037
1021
|
end
|
1038
1022
|
|
1039
1023
|
# Ensure that the regular expression matches the whole URI.
|
1040
|
-
regexp_string = "
|
1024
|
+
regexp_string = "\\A#{regexp_string}\\z"
|
1041
1025
|
return expansions, Regexp.new(regexp_string)
|
1042
1026
|
end
|
1043
1027
|
|