Spec-Zone.ru › Ruby 4.0

модуль URI

URI — это модуль, предоставляющий классы для работы с унифицированными идентификаторами ресурсов (RFC2396).

Возможности

  • Единый способ работы с URI.

  • Возможность вводить пользовательские схемы URI.

  • Возможность использовать альтернативный URI::Parser (или просто другие шаблоны и регулярные выражения).

Простой пример

require 'uri'

uri = URI("http://foo.com/posts?id=30&limit=5#time=1305298413")
#=> #<URI::HTTP http://foo.com/posts?id=30&limit=5#time=1305298413>

uri.scheme    #=> "http"
uri.host      #=> "foo.com"
uri.path      #=> "/posts"
uri.query     #=> "id=30&limit=5"
uri.fragment  #=> "time=1305298413"

uri.to_s      #=> "http://foo.com/posts?id=30&limit=5#time=1305298413"

Добавление пользовательских URI

module URI
  class RSYNC < Generic
    DEFAULT_PORT = 873
  end
  register_scheme 'RSYNC', RSYNC
end
#=> URI::RSYNC

URI.scheme_list
#=> {"FILE"=>URI::File, "FTP"=>URI::FTP, "HTTP"=>URI::HTTP,
#    "HTTPS"=>URI::HTTPS, "LDAP"=>URI::LDAP, "LDAPS"=>URI::LDAPS,
#    "MAILTO"=>URI::MailTo, "RSYNC"=>URI::RSYNC}

uri = URI("rsync://rsync.foo.com")
#=> #<URI::RSYNC rsync://rsync.foo.com>

Ссылки на RFC

Хорошее место для просмотра спецификаций RFC — www.ietf.org/rfc.html.

Список всех связанных RFC:

  • RFC822

  • RFC1738

  • RFC2255

  • RFC2368

  • RFC2373

  • RFC2396

  • RFC2732

  • RFC3986

Дерево классов

  • URI::Generic (в uri/generic.rb)

    • URI::File — (в uri/file.rb)

    • URI::FTP — (в uri/ftp.rb)

    • URI::HTTP — (в uri/http.rb)

      • URI::HTTPS — (в uri/https.rb)

    • URI::LDAP — (в uri/ldap.rb)

      • URI::LDAPS — (в uri/ldaps.rb)

    • URI::MailTo — (в uri/mailto.rb)

  • URI::Parser — (в uri/common.rb)

  • URI::REGEXP — (в uri/common.rb)

    • URI::REGEXP::PATTERN — (в uri/common.rb)

  • URI::Util — (в uri/common.rb)

  • URI::Error — (в uri/common.rb)

    • URI::InvalidURIError — (в uri/common.rb)

    • URI::InvalidComponentError — (в uri/common.rb)

    • URI::BadURIError — (в uri/common.rb)

Сведения об авторских правах

Автор

Akira Yamada <akira@ruby-lang.org>

Документация

Akira Yamada <akira@ruby-lang.org> Dmitry V. Sabanin <sdmitry@lrn.ru> Vincent Batts <vbatts@hashbangbash.com>

Лицензия

Авторское право © 2001 akira yamada <akira@ruby-lang.org>. Вы можете распространять и/или изменять этот материал на тех же условиях, что и Ruby.

Константы

DEFAULT_PARSER

Экземпляр парсера по умолчанию.

RFC2396_PARSER

Экземпляр парсера по умолчанию для RFC 2396.

RFC3986_PARSER

Экземпляр парсера по умолчанию для RFC 3986.

Общедоступные методы класса

decode_uri_component (str, enc=Encoding::UTF_8) Показать исходный код
# File lib/uri/common.rb, line 441
def self.decode_uri_component(str, enc=Encoding::UTF_8)
  _decode_uri_component(/%\h\h/, str, enc)
end

Как URI.decode_www_form_component, за исключением того, что '+' сохраняется.

decode_www_form (str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false) Показать исходный код
# File lib/uri/common.rb, line 620
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
  raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
  ary = []
  return ary if str.empty?
  enc = Encoding.find(enc)
  str.b.each_line(separator) do |string|
    string.chomp!(separator)
    key, sep, val = string.partition('=')
    if isindex
      if sep.empty?
        val = key
        key = +''
      end
      isindex = false
    end

    if use__charset_ and key == '_charset_' and e = get_encoding(val)
      enc = e
      use__charset_ = false
    end

    key.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_)
    if val
      val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_)
    else
      val = +''
    end

    ary << [key, val]
  end
  ary.each do |k, v|
    k.force_encoding(enc)
    k.scrub!
    v.force_encoding(enc)
    v.scrub!
  end
  ary
end

Возвращает пары имя/значение, полученные из заданной строки str, которая должна быть строкой ASCII.

Метод можно использовать для декодирования тела объекта Net::HTTPResponse res, для которого res['Content-Type'] имеет значение 'application/x-www-form-urlencoded'.

Возвращаемые данные представляют собой массив подмассивов из двух элементов; каждый подмассив — это пара имя/значение (оба элемента являются строками). Кодировка каждой возвращаемой строки — enc; недопустимые символы удаляются с помощью String#scrub.

Простой пример:

URI.decode_www_form('foo=0&bar=1&baz')
# => [["foo", "0"], ["bar", "1"], ["baz", ""]]

Возвращаемые строки подвергаются некоторым преобразованиям, аналогичным тем, которые выполняются в URI.decode_www_form_component:

URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
# => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]

Заданная строка может содержать несколько разделителей подряд:

URI.decode_www_form('foo=0&&bar=1&&baz=2')
# => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]

Можно указать другой разделитель:

URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
# => [["foo", "0"], ["bar", "1"], ["baz", ""]]
decode_www_form_component (str, enc=Encoding::UTF_8) Показать исходный код
# File lib/uri/common.rb, line 430
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
  _decode_uri_component(/\+|%\h\h/, str, enc)
end

Возвращает строку, декодированную из заданной строки с URL-кодированием str.

Сначала заданная строка кодируется как Encoding::ASCII-8BIT (с помощью String#b), затем декодируется (как описано ниже), а в конце принудительно преобразуется в заданную кодировку enc.

Возвращаемая строка:

  • Сохраняет:

    • Символы '*', '.', '-' и '_'.

    • Символы из диапазонов 'a'..'z', 'A'..'Z' и '0'..'9'.

    Пример:

    URI.decode_www_form_component('*.-_azAZ09')
    # => "*.-_azAZ09"
    
  • Преобразует:

    • Символ '+' в символ ' '.

    • Каждую «процентную запись» в символ ASCII.

    Пример:

    URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
    # => "Here are some punctuation characters: ,;?:"
    

Связанный метод: URI.decode_uri_component (сохраняет '+').

encode_uri_component (str, enc=nil) Показать исходный код
# File lib/uri/common.rb, line 436
def self.encode_uri_component(str, enc=nil)
  _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
end

Как URI.encode_www_form_component, за исключением того, что ' ' (пробел) кодируется как '%20' (вместо '+').

encode_www_form (enum, enc=nil) Показать исходный код
# File lib/uri/common.rb, line 567
def self.encode_www_form(enum, enc=nil)
  enum.map do |k,v|
    if v.nil?
      encode_www_form_component(k, enc)
    elsif v.respond_to?(:to_ary)
      v.to_ary.map do |w|
        str = encode_www_form_component(k, enc)
        unless w.nil?
          str << '='
          str << encode_www_form_component(w, enc)
        end
      end.join('&')
    else
      str = encode_www_form_component(k, enc)
      str << '='
      str << encode_www_form_component(v, enc)
    end
  end.join('&')
end

Возвращает строку с URL-кодированием, полученную из заданного объекта Enumerable enum.

Результат подходит для использования в качестве данных формы в HTTP-запросе, у которого Content-Type равно 'application/x-www-form-urlencoded'.

Возвращаемая строка состоит из элементов enum, каждый из которых преобразуется в одну или несколько строк с URL-кодированием; все строки объединяются символом '&'.

Простые примеры:

URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
# => "foo=0&bar=1&baz=2"
URI.encode_www_form({foo: 0, bar: 1, baz: 2})
# => "foo=0&bar=1&baz=2"

Возвращаемая строка формируется с помощью метода URI.encode_www_form_component, который преобразует некоторые символы:

URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
# => "f%23o=%2F&b-r=%24&b+z=%40"

Если enum подобен массиву, каждый элемент ele преобразуется в поле:

  • Если ele — это массив из двух или более элементов, поле формируется из первых двух элементов (все остальные элементы игнорируются):

    name = URI.encode_www_form_component(ele[0], enc)
    value = URI.encode_www_form_component(ele[1], enc)
    "#{name}=#{value}"
    

    Примеры:

    URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
    # => "foo=bar&baz=bat"
    URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
    # => "foo=0&bar=baz"
    
  • Если ele — это массив из одного элемента, поле формируется из ele[0]:

    URI.encode_www_form_component(ele[0])
    

    Пример:

    URI.encode_www_form([['foo'], [:bar], [0]])
    # => "foo&bar&0"
    
  • В противном случае поле формируется из ele:

    URI.encode_www_form_component(ele)
    

    Пример:

    URI.encode_www_form(['foo', :bar, 0])
    # => "foo&bar&0"
    

Элементы объекта enum, подобного массиву, могут быть смешанными:

URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
# => "foo=0&bar=1&baz&bat"

Если enum подобен хешу, каждая пара key/value преобразуется в одно или несколько полей:

  • Если value можно преобразовать в массив, каждый элемент ele в value объединяется с key для формирования поля:

    name = URI.encode_www_form_component(key, enc)
    value = URI.encode_www_form_component(ele, enc)
    "#{name}=#{value}"
    

    Пример:

    URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
    # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
    
  • В противном случае key и value объединяются для формирования поля:

    name = URI.encode_www_form_component(key, enc)
    value = URI.encode_www_form_component(value, enc)
    "#{name}=#{value}"
    

    Пример:

    URI.encode_www_form({foo: 0, bar: 1, baz: 2})
    # => "foo=0&bar=1&baz=2"
    

Элементы объекта enum, подобного хешу, могут быть смешанными:

URI.encode_www_form({foo: [0, 1], bar: 2})
# => "foo=0&foo=1&bar=2"
encode_www_form_component (str, enc=nil) Показать исходный код
# File lib/uri/common.rb, line 397
def self.encode_www_form_component(str, enc=nil)
  _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
end

Возвращает строку с URL-кодированием, полученную из заданной строки str.

Возвращаемая строка:

  • Сохраняет:

    • Символы '*', '.', '-' и '_'.

    • Символы из диапазонов 'a'..'z', 'A'..'Z' и '0'..'9'.

    Пример:

    URI.encode_www_form_component('*.-_azAZ09')
    # => "*.-_azAZ09"
    
  • Преобразует:

    • Символ ' ' в символ '+'.

    • Любой другой символ в «процентную запись»; процентная запись для символа c — это '%%%X' % c.ord.

    Пример:

    URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
    # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
    

Кодировка:

  • Если str имеет кодировку Encoding::ASCII_8BIT, аргумент enc игнорируется.

  • В противном случае сначала str преобразуется в Encoding::UTF_8 (с подходящей заменой символов), а затем — в кодировку enc.

В обоих случаях кодировка возвращаемой строки принудительно устанавливается в Encoding::US_ASCII.

Связанный метод: URI.encode_uri_component (кодирует ' ' как '%20').

for (scheme, *arguments, default: Generic) Показать исходный код
# File lib/uri/common.rb, line 187
def self.for(scheme, *arguments, default: Generic)
  const_name = Schemes.escape(scheme)

  uri_class = INITIAL_SCHEMES[const_name]
  uri_class ||= Schemes.find(const_name)
  uri_class ||= default

  return uri_class.new(scheme, *arguments)
end

Возвращает новый объект, созданный на основе заданных scheme, arguments и default:

  • Новый объект является экземпляром URI.scheme_list[scheme.upcase].

  • Объект инициализируется вызовом инициализатора класса с использованием scheme и arguments. См. URI::Generic.new.

Примеры:

values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
URI.for('https', *values)
# => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
URI.for('foo', *values, default: URI::HTTP)
# => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
join (*str) Показать исходный код
# File lib/uri/common.rb, line 273
def self.join(*str)
  DEFAULT_PARSER.join(*str)
end

Объединяет заданные строки URI str в соответствии с RFC 2396.

Перед объединением каждая строка в str преобразуется в URI по RFC3986.

Примеры:

URI.join("http://example.com/","main.rbx")
# => #<URI::HTTP http://example.com/main.rbx>

URI.join('http://example.com', 'foo')
# => #<URI::HTTP http://example.com/foo>

URI.join('http://example.com', '/foo', '/bar')
# => #<URI::HTTP http://example.com/bar>

URI.join('http://example.com', '/foo', 'bar')
# => #<URI::HTTP http://example.com/bar>

URI.join('http://example.com', '/foo/', 'bar')
# => #<URI::HTTP http://example.com/foo/bar>
open (name, *rest, &block) Показать исходный код
# File lib/open-uri.rb, line 23
def self.open(name, *rest, &block)
  if name.respond_to?(:open)
    name.open(*rest, &block)
  elsif name.respond_to?(:to_str) &&
        %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
        (uri = URI.parse(name)).respond_to?(:open)
    uri.open(*rest, &block)
  else
    super
  end
end

Позволяет открывать различные ресурсы, в том числе URI.

Если первый аргумент отвечает на метод ‘open’, этот метод вызывается для него с остальными аргументами.

Если первый аргумент — строка, начинающаяся с (protocol)://, она разбирается методом URI.parse. Если полученный объект отвечает на метод ‘open’, этот метод вызывается для него с остальными аргументами.

В противном случае вызывается Kernel#open.

OpenURI::OpenRead#open предоставляет URI::HTTP#open, URI::HTTPS#open и URI::FTP#open, Kernel#open.

Метод принимает URI и строки, начинающиеся с http://, https:// и ftp://. В этих случаях объект открытого файла расширяется модулем OpenURI::Meta.

Вызов метода суперкласса
parse (uri) Показать исходный код
# File lib/uri/common.rb, line 246
def self.parse(uri)
  PARSER.parse(uri)
end

Возвращает новый объект URI, созданный из заданной строки uri:

URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
# => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
# => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>

Рекомендуется сначала вызвать URI::RFC2396_PARSER.escape для строки uri, если она может содержать недопустимые символы URI>.

parser= (parser = RFC3986_PARSER) Показать исходный код
# File lib/uri/common.rb, line 29
def self.parser=(parser = RFC3986_PARSER)
  remove_const(:Parser) if defined?(::URI::Parser)
  const_set("Parser", parser.class)

  remove_const(:PARSER) if defined?(::URI::PARSER)
  const_set("PARSER", parser)

  remove_const(:REGEXP) if defined?(::URI::REGEXP)
  remove_const(:PATTERN) if defined?(::URI::PATTERN)
  if Parser == RFC2396_Parser
    const_set("REGEXP", URI::RFC2396_REGEXP)
    const_set("PATTERN", URI::RFC2396_REGEXP::PATTERN)
  end

  Parser.new.regexp.each_pair do |sym, str|
    remove_const(sym) if const_defined?(sym, false)
    const_set(sym, str)
  end
end

Устанавливает экземпляр парсера по умолчанию.

register_scheme (scheme, klass) Показать исходный код
# File lib/uri/common.rb, line 143
def self.register_scheme(scheme, klass)
  Schemes.register(scheme, klass)
end

Регистрирует заданный klass как класс, экземпляр которого создаётся при разборе URI с заданной scheme:

URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
URI.scheme_list['MS_SEARCH']                   # => URI::Generic

Обратите внимание: после вызова String#upcase для scheme результат должен быть допустимым именем константы.

scheme_list () Показать исходный код
# File lib/uri/common.rb, line 161
def self.scheme_list
  Schemes.list
end

Возвращает хеш определённых схем:

URI.scheme_list
# =>
{"MAILTO"=>URI::MailTo,
 "LDAPS"=>URI::LDAPS,
 "WS"=>URI::WS,
 "HTTP"=>URI::HTTP,
 "HTTPS"=>URI::HTTPS,
 "LDAP"=>URI::LDAP,
 "FILE"=>URI::File,
 "FTP"=>URI::FTP}

Связанный метод: URI.register_scheme.

split (uri) Показать исходный код
# File lib/uri/common.rb, line 232
def self.split(uri)
  PARSER.split(uri)
end

Возвращает массив из 9 элементов, представляющий части URI, полученного из строки uri; каждый элемент массива — это строка или nil:

names = %w[scheme userinfo host port registry path opaque query fragment]
values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
names.zip(values)
# =>
[["scheme", "https"],
 ["userinfo", "john.doe"],
 ["host", "www.example.com"],
 ["port", "123"],
 ["registry", nil],
 ["path", "/forum/questions/"],
 ["opaque", nil],
 ["query", "tag=networking&order=newest"],
 ["fragment", "top"]]

Закрытые методы класса

_decode_uri_component (regexp, str, enc) Показать исходный код
# File lib/uri/common.rb, line 463
def self._decode_uri_component(regexp, str, enc)
  raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
  str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
end

Возвращает строку, декодируя символы, соответствующие regexp, из заданной строки с URL-кодированием str.

_encode_uri_component (regexp, table, str, enc) Показать исходный код
# File lib/uri/common.rb, line 447
def self._encode_uri_component(regexp, table, str, enc)
  str = str.to_s.dup
  if str.encoding != Encoding::ASCII_8BIT
    if enc && enc != Encoding::ASCII_8BIT
      str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
      str.encode!(enc, fallback: ->(x){"&##{x.ord};"})
    end
    str.force_encoding(Encoding::ASCII_8BIT)
  end
  str.gsub!(regexp, table)
  str.force_encoding(Encoding::US_ASCII)
end

Возвращает строку, полученную из заданной строки str, в которой символы, соответствующие regexp, закодированы в URI согласно table.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API