class URI::Generic
Extension and monkeypatch of Ruby’s StdLib URI::Generic
class.
Public Instance Methods
(see normalize!
) @return [URI::Generic] a normalized copy of ‘self`.
# File lib/rackful/uri.rb, line 28 def normalize r = self.dup r.normalize! r end
Monkeypatch of [Ruby’s StdLib implementation](ruby-doc.org/stdlib/libdoc/uri/rdoc/URI/Generic.html#method-i-normalize-21). In addition to the default implementation, this implementation ensures that
-
no unreserved characters are pct-encoded, and
-
all non-unreserved characters are pct-encoded.
Check [RFC3986](tools.ietf.org/html/rfc3986) syntax:
abempty = *( "/" *(unreserved / pct-encoded / sub-delims / ":" / "@") ) unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
@return [self, nil] ‘self` if the URI
was modified, or `nil` of the uri was
already in normal form.
# File lib/rackful/uri.rb, line 47 def normalize! #unless %r{\A(?:/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*\z}i === self.path # raise TypeError, "Can’t convert String #{self.path.inspect} to Rackful::Path" #end self.uri_generic_normalize! path = '/' + self.segments( Encoding::BINARY ).collect do |segment| segment.gsub(/([^a-zA-Z0-9\-._~]+)/n) { '%'+$1.unpack('H2'*bytesize($1)).join('%').upcase } end.join('/') if path == self.path nil else self.path = path self end end
Turns a relative URI
(starting with ‘/`) into a relative path (starting with `./` or `../`) @param base_path [Path] @return [String] a relative URI
@deprecated
# File lib/rackful/uri.rb, line 121 def relative_deprecated base_path case self when base_path # RFC2396, Section 4.2 return '' when %r{(?:\A|/)\.\.?(?:/|\z)} # self has abnormal absolute path, # like "/./", "/../", "/x/../", ... return self.dup end src_path = base_path.scan(%r{(?:\A|[^/]+)/}) dst_path = self.scan(%r{(?:\A|[^/]+)/?}) # discard same parts while !dst_path.empty? && dst_path.first == src_path.first src_path.shift dst_path.shift end tmp = dst_path.join # calculate if src_path.empty? if tmp.empty? return './' elsif dst_path.first.include?(':') # (see RFC2396 Section 5) return './' + tmp else return tmp end end return '../' * src_path.size + tmp end
@return [Array<String>] Unencoded segments
# File lib/rackful/uri.rb, line 108 def segments( encoding = Encoding::UTF_8 ) r = self.path.split(%r{/+}).collect do |s| Rack::Utils.unescape( s, encoding ) end r.shift r end
@return [Path] a copy of ‘self`, with a trailing slash.
# File lib/rackful/uri.rb, line 67 def slashify r = self.dup r.slashify! r end
Adds a trailing slash to ‘self` if necessary. @return [self]
# File lib/rackful/uri.rb, line 76 def slashify! if '/' != self.path[-1,1] self.path += '/' self else nil end end
@return [Path] a copy of ‘self` without trailing slashes.
# File lib/rackful/uri.rb, line 87 def unslashify r = self.dup r.unslashify! r end
Removes trailing slashes from ‘self`. @return [self]
# File lib/rackful/uri.rb, line 96 def unslashify! path = self.path.sub( %r{/+\z}, '' ) if path == self.path nil else self.path = path self end end