Spec-Zone.ru › Ruby 3.2

класс Net::HTTP

Родитель:
Протокол

Класс Net::HTTP предоставляет богатую библиотеку, которая реализует клиента в модели клиент-сервер, использующей протокол HTTP запросов-ответов. Для информации об HTTP, см.

  • Протокол передачи гипертекста.

  • Техническое описание.

Примечание: если вы выполняете только несколько запросов GET, рассмотрите использование OpenURI; в противном случае, продолжайте чтение.

Краткое описание

Если вы уже знакомы с HTTP, это краткое описание может быть полезным.

Сессия с несколькими запросами для методов HTTP:

Net::HTTP.start(hostname) do |http|
  # Session started automatically before block execution.
  http.get(path_or_uri, headers = {})
  http.head(path_or_uri, headers = {})
  http.post(path_or_uri, data, headers = {})  # Can also have a block.
  http.put(path_or_uri, data, headers = {})
  http.delete(path_or_uri, headers = {Depth: 'Infinity'})
  http.options(path_or_uri, headers = {})
  http.trace(path_or_uri, headers = {})
  http.patch(path_or_uri, data, headers = {}) # Can also have a block.
  # Session finished automatically at block exit.
end

Сессия с несколькими запросами для методов WebDAV:

Net::HTTP.start(hostname) do |http|
  # Session started automatically before block execution.
  http.copy(path_or_uri, headers = {})
  http.lock(path_or_uri, body, headers = {})
  http.mkcol(path_or_uri, body = nil, headers = {})
  http.move(path_or_uri, headers = {})
  http.propfind(path_or_uri, body = nil, headers = {'Depth' => '0'})
  http.proppatch(path_or_uri, body, headers = {})
  http.unlock(path_or_uri, body, headers = {})
  # Session finished automatically at block exit.
end

Каждый из следующих методов автоматически начинает и завершает сессию, отправляя один запрос:

# Return string response body.
Net::HTTP.get(hostname, path, port = 80)
Net::HTTP.get(uri, headers = {}, port = 80)

# Write string response body to $stdout.
Net::HTTP.get_print(hostname, path_or_uri, port = 80)
Net::HTTP.get_print(uri, headers = {}, port = 80)

# Return response as Net::HTTPResponse object.
Net::HTTP.get_response(hostname, path_or_uri, port = 80)
Net::HTTP.get_response(uri, headers = {}, port = 80)

Net::HTTP.post(uri, data, headers = {})
Net::HTTP.post_form(uri, params)

Описание примеров

Примеры здесь предполагают, что net/http был подключен (что также требует uri):

require 'net/http'

Многие примеры кода здесь используют эти примерные веб-сайты:

  • jsonplaceholder.typicode.com.

  • example.com.

В некоторых примерах также предполагаются эти переменные:

uri = URI('https://jsonplaceholder.typicode.com')
uri.freeze # Examples may not modify.
hostname = uri.hostname # => "jsonplaceholder.typicode.com"
port = uri.port         # => 443

Так что примерные запросы могут быть записаны как:

Net::HTTP.get(uri)
Net::HTTP.get(hostname, '/index.html')
Net::HTTP.start(hostname) do |http|
  http.get('/todos/1')
  http.get('/todos/2')
end

Пример, который требует модифицированного URI сначала дублирует uri, затем изменяет дубликат:

_uri = uri.dup
_uri.path = '/todos/1'

URI

В интернете URI (универсальный идентификатор ресурса) — это строка, идентифицирующая конкретный ресурс. Она состоит из некоторых или всех элементов: схема, имя хоста, путь, запрос и фрагмент; см. синтаксис URI.

Объект Ruby URI::Generic представляет собой интернет-URI. Он предоставляет, среди прочего, методы scheme, hostname, path, query, и fragment.

Схемы

Интернет-URI имеет схему.

Две поддерживаемые в Net::HTTP схемы — это 'https' и 'http':

uri.scheme                       # => "https"
URI('http://example.com').scheme # => "http"

Имена хостов

Имя хоста идентифицирует сервер (хост), которому могут быть отправлены запросы:

hostname = uri.hostname # => "jsonplaceholder.typicode.com"
Net::HTTP.start(hostname) do |http|
  # Some HTTP stuff.
end

Пути

Путь, специфичный для хоста, идентифицирует ресурс на этом хосте:

_uri = uri.dup
_uri.path = '/todos/1'
hostname = _uri.hostname
path = _uri.path
Net::HTTP.get(hostname, path)

Запросы

Специфичный для хоста запрос добавляет пары имя/значение в URI:

_uri = uri.dup
params = {userId: 1, completed: false}
_uri.query = URI.encode_www_form(params)
_uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false>
Net::HTTP.get(_uri)

Фрагменты

Фрагмент URI не оказывает никакого эффекта в Net::HTTP; данные возвращаются одинаково, независимо от того, включен фрагмент или нет.

Заголовки запроса

Заголовки запроса могут использоваться для передачи дополнительной информации хосту, аналогично аргументам, передаваемым в вызове метода; каждый заголовок представляет собой пару имя/значение.

Каждый из методов Net::HTTP, отправляющих запрос хосту, имеет необязательный аргумент headers, где заголовки выражены как хеш пар имя-значение поля:

headers = {Accept: 'application/json', Connection: 'Keep-Alive'}
Net::HTTP.get(uri, headers)

См. списки стандартных и общих полей запроса по адресу Поля запроса. Хост также может принимать и другие пользовательские поля.

Сессии

Сессия — это соединение между сервером (хостом) и клиентом, которое:

  • Начинается методом экземпляра Net::HTTP#start.

  • Может содержать любое количество запросов.

  • Заканчивается методом экземпляра Net::HTTP#finish.

См. примеры сессий в разделе Краткое описание.

Сессия с использованием Net::HTTP.start

Если у вас много запросов к одному хосту (и порту), рассмотрите использование метода класса Net::HTTP.start с блоком; метод обрабатывает сессию автоматически, выполняя:

  • Вызов start перед выполнением блока.

  • Выполнение блока.

  • Вызов finish после выполнения блока.

В блоке вы можете использовать эти методы экземпляра, каждый из которых отправляет один запрос:

  • Методы HTTP:

    • get, request_get: GET.

    • head, request_head: HEAD.

    • post, request_post: POST.

    • delete: DELETE.

    • options: OPTIONS.

    • trace: TRACE.

    • patch: PATCH.

  • Методы WebDAV:

    • copy: COPY.

    • lock: LOCK.

    • mkcol: MKCOL.

    • move: MOVE.

    • propfind: PROPFIND.

    • proppatch: PROPPATCH.

    • unlock: UNLOCK.

Сессия с использованием Net::HTTP.start и Net::HTTP.finish

Вы можете управлять сессией вручную, используя методы start и finish:

http = Net::HTTP.new(hostname)
http.start
http.get('/todos/1')
http.get('/todos/2')
http.delete('/posts/1')
http.finish # Needed to free resources.

Сессия с одним запросом

Определенные удобные методы автоматически обрабатывают сессию, выполняя:

  • Создание объекта HTTP

  • Начало сессии.

  • Отправка одного запроса.

  • Завершение сессии.

  • Удаление объекта.

Методы, отправляющие запросы GET:

  • ::get: Возвращает строку тела ответа.

  • ::get_print: Выводит строку тела ответа в $stdout.

  • ::get_response: Возвращает объект Net::HTTPResponse.

Методы, отправляющие запросы POST:

  • ::post: Отправляет данные на хост.

  • ::post_form: Отправляет данные формы на хост.

HTTP-запросы и ответы

Многие методы выше — это удобные методы, каждый из которых отправляет запрос и возвращает строку без непосредственного использования объектов Net::HTTPRequest и Net::HTTPResponse.

Однако вы можете напрямую создать объект запроса, отправить запрос и получить объект ответа; см.:

  • Net::HTTPRequest.

  • Net::HTTPResponse.

Следование перенаправлению

Каждый объект Net::HTTPResponse принадлежит классу для соответствующего кода ответа.

Например, все ответы 2XX являются экземплярами подкласса Net::HTTPSuccess, ответ 3XX — экземпляром подкласса Net::HTTPRedirection, а ответ 200 — экземпляром класса Net::HTTPOK. Подробности о классах ответов см. в разделе «Классы ответов HTTP» ниже.

Используя оператор case, вы можете правильно обработать различные типы ответов:

def fetch(uri_str, limit = 10)
  # You should choose a better exception.
  raise ArgumentError, 'too many HTTP redirects' if limit == 0

  response = Net::HTTP.get_response(URI(uri_str))

  case response
  when Net::HTTPSuccess then
    response
  when Net::HTTPRedirection then
    location = response['location']
    warn "redirected to #{location}"
    fetch(location, limit - 1)
  else
    response.value
  end
end

print fetch('http://www.ruby-lang.org')

Базовая аутентификация

Базовая аутентификация выполняется в соответствии с [RFC2617](www.ietf.org/rfc/rfc2617.txt).

uri = URI('http://example.com/index.html?key=value')

req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'

res = Net::HTTP.start(uri.hostname, uri.port) {|http|
  http.request(req)
}
puts res.body

Потоковое чтение тел ответов

По умолчанию Net::HTTP считывает весь ответ в память. Если вы работаете с большими файлами или хотите реализовать индикатор прогресса, вы можете вместо этого передать тело потоком непосредственно в IO.

uri = URI('http://example.com/large_file')

Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new uri

  http.request request do |response|
    open 'large_file', 'w' do |io|
      response.read_body do |chunk|
        io.write chunk
      end
    end
  end
end

HTTPS

HTTPS включен для соединения HTTP с помощью Net::HTTP#use_ssl=.

uri = URI('https://secure.example.com/some_path?query=string')

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
  request = Net::HTTP::Get.new uri
  response = http.request request # Net::HTTPResponse object
end

Или, если вы просто хотите отправить запрос GET, вы можете передать объект URI с URL HTTPS. Net::HTTP автоматически включает проверку TLS, если объект URI имеет схему ‘https’ URI.

uri = URI('https://example.com/')
Net::HTTP.get(uri) # => String

В предыдущих версиях Ruby вам нужно было подключить «net/https», чтобы использовать HTTPS. Это больше не так.

Прокси-серверы

Net::HTTP автоматически создаст прокси из переменной среды http_proxy , если она присутствует. Чтобы отключить использование http_proxy, передайте nil в качестве адреса прокси.

Вы также можете создать пользовательский прокси:

proxy_addr = 'your.proxy.host'
proxy_port = 8080

Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http|
  # always proxy via your.proxy.addr:8080
}

См. Net::HTTP.new для получения дополнительных сведений и примеров, таких как прокси, требующие имени пользователя и пароля.

Сжатие

Net::HTTP автоматически добавляет Accept-Encoding для сжатия тел ответов и автоматически распаковывает ответы gzip и deflate, если заголовок Range не был отправлен.

Сжатие можно отключить, используя заголовок Accept-Encoding: identity.

Константы

SSL_ATTRIBUTES
SSL_IVNAMES
STATUS_CODES

Атрибуты

proxy_address[R]

Адрес хоста прокси. Если Net::HTTP не использует прокси, nil.

proxy_pass[R]

Пароль пользователя для доступа к прокси. Если Net::HTTP не использует прокси, nil.

proxy_port[R]

Порт хоста прокси. Если Net::HTTP не использует прокси, nil.

proxy_user[R]

Имя пользователя для доступа к прокси. Если Net::HTTP не использует прокси, nil.

address[R]

Имя хоста DNS или IP-адрес для подключения.

ca_file[RW]

Устанавливает путь к файлу сертификатов CA в формате PEM.

Файл может содержать несколько сертификатов CA.

ca_path[RW]

Устанавливает путь к каталогу сертификатов CA, содержащих сертификаты в формате PEM.

cert[RW]

Устанавливает объект OpenSSL::X509::Certificate в качестве клиентского сертификата. (Этот метод появился в расширении OpenSSL Михаила Рокоса).

cert_store[RW]

Устанавливает X509::Store для проверки сертификата узла.

ciphers[RW]

Устанавливает доступные шифры. См. OpenSSL::SSL::SSLContext#ciphers=

close_on_empty_response[RW]
continue_timeout[R]

Секунды ожидания ответа 100 Continue. Если объект HTTP не получает ответа в течение этого времени, он отправляет тело запроса. Значение по умолчанию — nil.

extra_chain_cert[RW]

Устанавливает дополнительные X509-сертификаты, которые должны быть добавлены в цепочку сертификатов. См. OpenSSL::SSL::SSLContext#extra_chain_cert=

ignore_eof[RW]

Нужно ли игнорировать EOF при чтении тел ответов с заданными заголовками Content-Length. Для обратной совместимости значение по умолчанию — true.

keep_alive_timeout[RW]

Секунды для повторного использования соединения предыдущего запроса. Если время простоя меньше, чем это время Keep-Alive Timeout, Net::HTTP повторно использует TCP/IP-сокет, использованный в предыдущей коммуникации. Значение по умолчанию — 2 секунды.

key[RW]

Устанавливает объект OpenSSL::PKey::RSA или OpenSSL::PKey::DSA. (Этот метод появился в расширении OpenSSL Михаила Рокоса.)

local_host[RW]

Локальный хост, используемый для установления соединения.

local_port[RW]

Локальный порт, используемый для установления соединения.

max_retries[R]
max_version[RW]

Устанавливает максимальную версию SSL. См. OpenSSL::SSL::SSLContext#max_version=

min_version[RW]

Устанавливает минимальную версию SSL. См. OpenSSL::SSL::SSLContext#min_version=

open_timeout[RW]

Количество секунд ожидания открытия соединения. Можно использовать любое число, включая дробные (с плавающей точкой). Если объект HTTP не может открыть соединение в течение этого времени, он вызывает исключение Net::OpenTimeout. Значение по умолчанию — 60 секунд.

port[R]

Номер порта для подключения.

proxy_address[W]
proxy_from_env[W]
proxy_pass[W]
proxy_port[W]
proxy_user[W]
read_timeout[R]

Количество секунд ожидания чтения одного блока (через один вызов read(2)). Можно использовать любое число, включая дробные (с плавающей точкой). Если объект HTTP не может прочитать данные в течение этого времени, он вызывает исключение Net::ReadTimeout. Значение по умолчанию — 60 секунд.

response_body_encoding[R]

Кодировка, используемая для тела ответа. Если Encoding, используется указанная кодировка. Если другое истинное значение, пытается определить кодировку тела ответа.

ssl_timeout[RW]

Устанавливает время ожидания SSL в секундах.

ssl_version[RW]

Устанавливает версию SSL. См. OpenSSL::SSL::SSLContext#ssl_version=

END_OF_DOCUMENT_MARKER
verify_callback[RW]

Устанавливает обратный вызов проверки сертификата сервера.

verify_depth[RW]

Устанавливает максимальную глубину проверки цепочки сертификатов.

verify_hostname[RW]

Устанавливает проверку того, что сертификат сервера действителен для указанного имени хоста. См. OpenSSL::SSL::SSLContext#verify_hostname=

verify_mode[RW]

Устанавливает флаги для проверки сертификации сервера в начале сессии SSL/TLS.

Допустимы значения OpenSSL::SSL::VERIFY_NONE или OpenSSL::SSL::VERIFY_PEER.

write_timeout[R]

Количество секунд ожидания записи одного блока (через один вызов write(2)). Можно использовать любое число, включая числа с плавающей точкой для дробных секунд. Если объект HTTP не может записать данные за это время, он поднимает исключение Net::WriteTimeout. Значение по умолчанию — 60 секунд. Исключение Net::WriteTimeout не генерируется в Windows.

Методы публичного класса

default_port() Показать исходный код
# File lib/net/http.rb, line 558
def HTTP.default_port
  http_default_port()
end

Возвращает целое число 80, стандартный порт для HTTP запросов:

Net::HTTP.default_port # => 80
Net::HTTP.get(hostname, path, port = 80) → body Показать исходный код
Net::HTTP:get(uri, headers = {}, port = uri.port) → body
# File lib/net/http.rb, line 460
def HTTP.get(uri_or_host, path_or_headers = nil, port = nil)
  get_response(uri_or_host, path_or_headers, port).body
end

Отправляет запрос GET и возвращает тело HTTP-ответа в виде строки.

С использованием строковых аргументов hostname и path:

hostname = 'jsonplaceholder.typicode.com'
path = '/todos/1'
puts Net::HTTP.get(hostname, path)

Вывод:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

С объектом URI uri и необязательным аргументом-словарём headers:

uri = URI('https://jsonplaceholder.typicode.com/todos/1')
headers = {'Content-type' => 'application/json; charset=UTF-8'}
Net::HTTP.get(uri, headers)

Связанные:

  • Net::HTTP::Get: класс запроса для HTTP-метода GET.

  • Net::HTTP#get: удобный метод для HTTP-метода GET.

Net::HTTP.get_print(hostname, path, port = 80) → nil Показать исходный код
Net::HTTP:get_print(uri, headers = {}, port = uri.port) → nil
# File lib/net/http.rb, line 419
def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil)
  get_response(uri_or_host, path_or_headers, port) {|res|
    res.read_body do |chunk|
      $stdout.print chunk
    end
  }
  nil
end

Аналогично Net::HTTP.get, но записывает возвращаемое тело в $stdout; возвращает nil.

Net::HTTP.get_response(hostname, path, port = 80) → http_response Показать исходный код
Net::HTTP:get_response(uri, headers = {}, port = uri.port) → http_response
# File lib/net/http.rb, line 470
def HTTP.get_response(uri_or_host, path_or_headers = nil, port = nil, &block)
  if path_or_headers && !path_or_headers.is_a?(Hash)
    host = uri_or_host
    path = path_or_headers
    new(host, port || HTTP.default_port).start {|http|
      return http.request_get(path, &block)
    }
  else
    uri = uri_or_host
    headers = path_or_headers
    start(uri.hostname, uri.port,
          :use_ssl => uri.scheme == 'https') {|http|
      return http.request_get(uri, headers, &block)
    }
  end
end

Аналогично Net::HTTP.get, но возвращает объект Net::HTTPResponse вместо строки тела.

http_default_port() Показать исходный код
# File lib/net/http.rb, line 566
def HTTP.http_default_port
  80
end

Возвращает целое число 80, стандартный порт для HTTP запросов:

Net::HTTP.http_default_port # => 80
https_default_port() Показать исходный код
# File lib/net/http.rb, line 574
def HTTP.https_default_port
  443
end

Возвращает целое число 443, стандартный порт для запросов HTTPS:

Net::HTTP.https_default_port # => 443
is_version_1_2?()
Псевдоним для: version_1_2?
new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil) Показать исходный код
# File lib/net/http.rb, line 802
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
  http = super address, port

  if proxy_class? then # from Net::HTTP::Proxy()
    http.proxy_from_env = @proxy_from_env
    http.proxy_address  = @proxy_address
    http.proxy_port     = @proxy_port
    http.proxy_user     = @proxy_user
    http.proxy_pass     = @proxy_pass
  elsif p_addr == :ENV then
    http.proxy_from_env = true
  else
    if p_addr && p_no_proxy && !URI::Generic.use_proxy?(p_addr, p_addr, p_port, p_no_proxy)
      p_addr = nil
      p_port = nil
    end
    http.proxy_address = p_addr
    http.proxy_port    = p_port || default_port
    http.proxy_user    = p_user
    http.proxy_pass    = p_pass
  end

  http
end

Возвращает новый объект Net::HTTP http (но не открывает TCP-соединение или HTTP сеанс).

Без прокси

Если передан только строковый аргумент hostname (и ENV['http_proxy'] не определен или nil), возвращаемый объект http:

  • Имеет заданный адрес.

  • Имеет стандартный номер порта, Net::HTTP.default_port (80).

  • Не имеет прокси.

Пример:

http = Net::HTTP.new(hostname)
# => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
http.address # => "jsonplaceholder.typicode.com"
http.port    # => 80
http.proxy?  # => false

Если также передан целочисленный аргумент port, возвращаемый объект http имеет заданный порт:

http = Net::HTTP.new(hostname, 8000)
# => #<Net::HTTP jsonplaceholder.typicode.com:8000 open=false>
http.port # => 8000

Прокси, используя аргумент p_addr как строку

Если аргумент p_addr является строковым именем хоста, возвращаемый объект http имеет прокси:

http = Net::HTTP.new(hostname, nil, 'proxy.example')
# => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
http.proxy?        # => true
http.proxy_address # => "proxy.example"
# These use default values.
http.proxy_port    # => 80
http.proxy_user    # => nil
http.proxy_pass    # => nil

Порт, имя пользователя и пароль для прокси также могут быть указаны:

http = Net::HTTP.new(hostname, nil, 'proxy.example', 8000, 'pname', 'ppass')
# => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
http.proxy?        # => true
http.proxy_address # => "proxy.example"
http.proxy_port    # => 8000
http.proxy_user    # => "pname"
http.proxy_pass    # => "ppass"

Прокси, используя ENV['http_proxy']

Если переменная окружения 'http_proxy' установлена в строку URI, возвращаемый объект http будет иметь этот URI в качестве прокси; обратите внимание, что строка URI должна иметь протокол, такой как 'http' или 'https':

ENV['http_proxy'] = 'http://example.com'
# => "http://example.com"
http = Net::HTTP.new(hostname)
# => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
http.proxy?        # => true
http.address       # => "jsonplaceholder.typicode.com"
http.proxy_address # => "example.com"

Строка URI может включать имя пользователя прокси, пароль и номер порта:

ENV['http_proxy'] = 'http://pname:ppass@example.com:8000'
# => "http://pname:ppass@example.com:8000"
http = Net::HTTP.new(hostname)
# => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
http.proxy_port # => 8000
http.proxy_user # => "pname"
http.proxy_pass # => "ppass"

Аргумент p_no_proxy

Вы можете использовать аргумент p_no_proxy для отклонения определённых прокси:

  • Отклонить определённый адрес:

    http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
    http.proxy_address # => nil
    
  • Отклонить определённые домены или поддомены:

    http = Net::HTTP.new('example.com', nil, 'my.proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
    http.proxy_address # => nil
    
  • Отклонить определённые сочетания адресов и портов:

    http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:1234')
    http.proxy_address # => "proxy.example"
    
    http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:8000')
    http.proxy_address # => nil
    
  • Отклонить список вышеперечисленных типов, разделённых запятыми:

    http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
    http.proxy_address # => nil
    
    http = Net::HTTP.new('example.com', nil, 'my.proxy', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
    http.proxy_address # => nil
    
Вызывается метод суперкласса
Также алиас: newobj
new(address, port = nil) Показать исходный код
# File lib/net/http.rb, line 830
def initialize(address, port = nil)
  @address = address
  @port    = (port || HTTP.default_port)
  @ipaddr = nil
  @local_host = nil
  @local_port = nil
  @curr_http_version = HTTPVersion
  @keep_alive_timeout = 2
  @last_communicated = nil
  @close_on_empty_response = false
  @socket  = nil
  @started = false
  @open_timeout = 60
  @read_timeout = 60
  @write_timeout = 60
  @continue_timeout = nil
  @max_retries = 1
  @debug_output = nil
  @response_body_encoding = false
  @ignore_eof = true

  @proxy_from_env = false
  @proxy_uri      = nil
  @proxy_address  = nil
  @proxy_port     = nil
  @proxy_user     = nil
  @proxy_pass     = nil

  @use_ssl = false
  @ssl_context = nil
  @ssl_session = nil
  @sspi_enabled = false
  SSL_IVNAMES.each do |ivname|
    instance_variable_set ivname, nil
  end
end

Создаёт новый объект Net::HTTP для указанного адреса сервера без открытия TCP-соединения или инициализации HTTP сеанса. address должен быть именем хоста DNS или IP-адресом.

newobj(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
Псевдоним для: new
post(url, data, header = nil) Показать исходный код
# File lib/net/http.rb, line 513
def HTTP.post(url, data, header = nil)
  start(url.hostname, url.port,
        :use_ssl => url.scheme == 'https' ) {|http|
    http.post(url, data, header)
  }
end

Отправляет данные на хост; возвращает объект Net::HTTPResponse.

Аргумент url должен быть URL; аргумент data должен быть строкой:

_uri = uri.dup
_uri.path = '/posts'
data = '{"title": "foo", "body": "bar", "userId": 1}'
headers = {'content-type': 'application/json'}
res = Net::HTTP.post(_uri, data, headers) # => #<Net::HTTPCreated 201 Created readbody=true>
puts res.body

Вывод:

{
  "title": "foo",
  "body": "bar",
  "userId": 1,
  "id": 101
}

Связанные:

  • Net::HTTP::Post: класс запроса для HTTP-метода POST.

  • Net::HTTP#post: удобный метод для HTTP-метода POST.

post_form(url, params) Показать исходный код
# File lib/net/http.rb, line 540
def HTTP.post_form(url, params)
  req = Post.new(url)
  req.form_data = params
  req.basic_auth url.user, url.password if url.user
  start(url.hostname, url.port,
        :use_ssl => url.scheme == 'https' ) {|http|
    http.request(req)
  }
end

Отправляет данные на хост; возвращает объект Net::HTTPResponse.

Аргумент url должен быть URI; аргумент data должен быть словарём:

_uri = uri.dup
_uri.path = '/posts'
data = {title: 'foo', body: 'bar', userId: 1}
res = Net::HTTP.post_form(_uri, data) # => #<Net::HTTPCreated 201 Created readbody=true>
puts res.body

Вывод:

{
  "title": "foo",
  "body": "bar",
  "userId": "1",
  "id": 101
}
proxy_class?() Показать исходный код
# File lib/net/http.rb, line 1423
def proxy_class?
  defined?(@is_proxy_class) ? @is_proxy_class : false
end

Возвращает true, если self — класс, созданный HTTP::Proxy.

start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) → http Показать исходный код
start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) {|http| ... } → object
# File lib/net/http.rb, line 668
def HTTP.start(address, *arg, &block) # :yield: +http+
  arg.pop if opt = Hash.try_convert(arg[-1])
  port, p_addr, p_port, p_user, p_pass = *arg
  p_addr = :ENV if arg.size < 2
  port = https_default_port if !port && opt && opt[:use_ssl]
  http = new(address, port, p_addr, p_port, p_user, p_pass)
  http.ipaddr = opt[:ipaddr] if opt && opt[:ipaddr]

  if opt
    if opt[:use_ssl]
      opt = {verify_mode: OpenSSL::SSL::VERIFY_PEER}.update(opt)
    end
    http.methods.grep(/\A(\w+)=\z/) do |meth|
      key = $1.to_sym
      opt.key?(key) or next
      http.__send__(meth, opt[key])
    end
  end

  http.start(&block)
end

Создаёт новый объект Net::HTTP, http, с помощью Net::HTTP.new:

Net::HTTP.new(address, port, p_addr, p_port, p_user, p_pass)
  • Для аргументов hostname по p_pass, см. Net::HTTP.new.

  • Для аргумента opts, см. ниже.

Примечание: Если port равно nil и opts[:use_ssl] имеет истинное значение, значение, переданное в new — Net::HTTP.https_default_port, а не port.

Без блока:

  • Вызывает http.start без блока (см. start), что открывает TCP-соединение и HTTP-сессию.

  • Возвращает http.

  • Вызывающий метод должен вызвать finish для закрытия сессии:

    http = Net::HTTP.start(hostname)
    http.started? # => true
    http.finish
    http.started? # => false
    

С блоком:

  • Вызывает http.start с блоком (см. start), что:

    • Открывает TCP-соединение и HTTP-сессию.

    • Вызывает блок, который может выполнить любое количество запросов к хосту.

    • Закрывает HTTP-сессию и TCP-соединение при выходе из блока.

    • Возвращает значение блока object.

  • Возвращает object.

Пример:

hostname = 'jsonplaceholder.typicode.com'
Net::HTTP.start(hostname) do |http|
  puts http.get('/todos/1').body
  puts http.get('/todos/2').body
end

Вывод:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}
{
  "userId": 1,
  "id": 2,
  "title": "quis ut nam facilis et officia qui",
  "completed": false
}

Если последний переданный аргумент — хеш, это хеш opts, где каждый ключ — метод или аксессор, который нужно вызвать, а его значение — значение, которое нужно установить.

Ключи могут включать:

  • ca_file

  • ca_path

  • cert

  • cert_store

  • ciphers

  • close_on_empty_response

  • ipaddr (вызывает ipaddr=)

  • keep_alive_timeout

  • key

  • open_timeout

  • read_timeout

  • ssl_timeout

  • ssl_version

  • use_ssl (вызывает use_ssl=)

  • verify_callback

  • verify_depth

  • verify_mode

  • write_timeout

version_1_2() Показать исходный код
# File lib/net/http.rb, line 394
def HTTP.version_1_2
  true
end

Возвращает true; сохранено для совместимости.

version_1_2?() Показать исходный код
# File lib/net/http.rb, line 399
def HTTP.version_1_2?
  true
end

Возвращает true; сохранено для совместимости.

Также алиас: is_version_1_2?
END_OF_DOCUMENT_MARKER

Общедоступные методы экземпляров

active?()
Псевдоним для: started?
continue_timeout=(sec) Показать исходный код
# File lib/net/http.rb, line 1085
def continue_timeout=(sec)
  @socket.continue_timeout = sec if @socket
  @continue_timeout = sec
end

Устанавливает значение атрибута continue_timeout.

copy(path, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1685
def copy(path, initheader = nil)
  request(Copy.new(path, initheader))
end

Отправляет запрос COPY на path и получает ответ в виде объекта HTTPResponse.

delete(path, initheader = {'Depth' => 'Infinity'}) Показать исходный код
# File lib/net/http.rb, line 1673
def delete(path, initheader = {'Depth' => 'Infinity'})
  request(Delete.new(path, initheader))
end

Отправляет запрос DELETE на path и получает ответ в виде объекта HTTPResponse.

finish() Показать исходный код
# File lib/net/http.rb, line 1369
def finish
  raise IOError, 'HTTP session not yet started' unless started?
  do_finish
end

Завершает сеанс HTTP и закрывает TCP-соединение. Вызывает исключение IOError, если сеанс не был начат.

get(path, initheader = nil, dest = nil) { |body_segment| ... } Показать исходный код
# File lib/net/http.rb, line 1573
def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
  res = nil
  request(Get.new(path, initheader)) {|r|
    r.read_body dest, &block
    res = r
  }
  res
end

Получает данные из path на подключенном хосте, который может быть абсолютным путем String или URI для извлечения пути.

initheader должен быть Hash типом, например { ‘Accept’ => ‘/’, … }, и по умолчанию является пустым массивом. Если у initheader нет ключа ‘accept-encoding’, используется значение «gzip;q=1.0,deflate;q=0.6,identity;q=0.3», так что сжатие gzip используется в приоритете перед сжатием deflate, которое используется в приоритете перед отсутствием сжатия. В Ruby нет библиотек для поддержки сжатия (Lempel-Ziv), поэтому оно не поддерживается. Цель этого — по умолчанию уменьшить пропускную способность. Если эта функция настраивает сжатие, она также выполняет разархивирование, удаляя заголовок, чтобы избежать путаницы. В противном случае она оставляет тело в том виде, в котором оно было найдено.

Этот метод возвращает объект Net::HTTPResponse.

Если вызывается с блоком, он передает каждый фрагмент тела сущности по очереди как строку по мере чтения его из сокета. Обратите внимание, что в этом случае возвращаемый объект ответа не будет содержать тело (полезной информации).

Аргумент dest устарел. Он всё ещё работает, но его не следует использовать.

Этот метод никогда не генерирует исключение.

response = http.get('/index.html')

# using block
File.open('result.txt', 'w') {|f|
  http.get('/~foo/') do |str|
    f.write str
  end
}
get2(path, initheader = nil)
Псевдоним для: request_get
head(path, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1595
def head(path, initheader = nil)
  request(Head.new(path, initheader))
end

Получает только заголовок из path на подключенном хосте. header является Hash типом, например { ‘Accept’ => ‘/’, … }.

Этот метод возвращает объект Net::HTTPResponse.

Этот метод никогда не генерирует исключение.

response = nil
Net::HTTP.start('some.www.server', 80) {|http|
  response = http.head('/index.html')
}
p response['content-type']
head2(path, initheader = nil, &block)
Псевдоним для: request_head
inspect() Показать исходный код
# File lib/net/http.rb, line 872
def inspect
  "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
end

Возвращает строковое представление self:

Net::HTTP.new(hostname).inspect
# => "#<Net::HTTP jsonplaceholder.typicode.com:80 open=false>"
ipaddr() Показать исходный код
# File lib/net/http.rb, line 995
def ipaddr
  started? ?  @socket.io.peeraddr[3] : @ipaddr
end

Возвращает IP-адрес для подключения.

Если сеанс не был начат, возвращает значение, установленное ipaddr=, или nil, если оно не было установлено:

http = Net::HTTP.new(hostname)
http.ipaddr # => nil
http.ipaddr = '172.67.155.76'
http.ipaddr # => "172.67.155.76"

Если сеанс был начат, возвращает IP-адрес из сокета:

http = Net::HTTP.new(hostname)
http.start
http.ipaddr # => "172.67.155.76"
http.finish
ipaddr=(addr) Показать исходный код
# File lib/net/http.rb, line 1007
def ipaddr=(addr)
  raise IOError, "ipaddr value changed, but session already started" if started?
  @ipaddr = addr
end

Устанавливает IP-адрес для подключения:

http = Net::HTTP.new(hostname)
http.ipaddr # => nil
http.ipaddr = '172.67.155.76'
http.ipaddr # => "172.67.155.76"

IP-адрес не может быть установлен, если сеанс уже начат.

lock(path, body, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1649
def lock(path, body, initheader = nil)
  request(Lock.new(path, initheader), body)
end

Отправляет запрос LOCK на path и получает ответ в виде объекта HTTPResponse.

max_retries=(retries) Показать исходный код
# File lib/net/http.rb, line 1043
def max_retries=(retries)
  retries = retries.to_int
  if retries < 0
    raise ArgumentError, 'max_retries should be non-negative integer number'
  end
  @max_retries = retries
end

Устанавливает максимальное количество попыток повтора идемпотентного запроса в случае Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError, Timeout::Error. Начальное значение равно 1.

Аргумент retries должен быть неотрицательным числовым значением:

http = Net::HTTP.new(hostname)
http.max_retries = 2   # => 2
http.max_retries       # => 2
mkcol(path, body = nil, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1691
def mkcol(path, body = nil, initheader = nil)
  request(Mkcol.new(path, initheader), body)
end

Отправляет запрос MKCOL на path и получает ответ в виде объекта HTTPResponse.

move(path, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1679
def move(path, initheader = nil)
  request(Move.new(path, initheader))
end

Отправляет запрос MOVE на path и получает ответ в виде объекта HTTPResponse.

options(path, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1661
def options(path, initheader = nil)
  request(Options.new(path, initheader))
end

Отправляет запрос OPTIONS на path и получает ответ в виде объекта HTTPResponse.

patch(path, data, initheader = nil, dest = nil) { |body_segment| ... } Показать исходный код
# File lib/net/http.rb, line 1633
def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
  send_entity(path, data, initheader, dest, Patch, &block)
end

Отправляет запрос PATCH на path и получает ответ в виде объекта HTTPResponse.

END_OF_DOCUMENT_MARKER
peer_cert() Показать исходный код
# File lib/net/http.rb, line 1217
def peer_cert
  if not use_ssl? or not @socket
    return nil
  end
  @socket.io.peer_cert
end

Возвращает сертификаты X.509, представленные сервером.

post(path, data, initheader = nil, dest = nil) { |body_segment| ... } Показать исходный код
# File lib/net/http.rb, line 1627
def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
  send_entity(path, data, initheader, dest, Post, &block)
end

Отправляет data (должен быть String) на path. header должен быть Hash типа { ‘Accept’ => ‘/’, … }.

Этот метод возвращает объект Net::HTTPResponse.

Если вызывается с блоком, он поочерёдно передает каждый фрагмент тела сущности в качестве строки по мере его чтения из сокета. Обратите внимание, что в этом случае возвращаемый объект ответа не будет содержать (полезное) тело.

Аргумент dest устарел. Он всё ещё работает, но его не следует использовать.

Этот метод никогда не вызывает исключения.

response = http.post('/cgi-bin/search.rb', 'query=foo')

# using block
File.open('result.txt', 'w') {|f|
  http.post('/cgi-bin/search.rb', 'query=foo') do |str|
    f.write str
  end
}

Для POST запроса необходимо установить заголовок Content-Type. Если заголовок Content-Type не задан, этот метод по умолчанию использует «application/x-www-form-urlencoded».

post2(path, data, initheader = nil)
Псевдоним для: request_post
propfind(path, body = nil, initheader = {'Depth' => '0'}) Показать исходный код
# File lib/net/http.rb, line 1667
def propfind(path, body = nil, initheader = {'Depth' => '0'})
  request(Propfind.new(path, initheader), body)
end

Отправляет запрос PROPFIND на path и получает ответ в виде объекта HTTPResponse.

proppatch(path, body, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1643
def proppatch(path, body, initheader = nil)
  request(Proppatch.new(path, initheader), body)
end

Отправляет запрос PROPPATCH на path и получает ответ в виде объекта HTTPResponse.

proxy?() Показать исходный код
# File lib/net/http.rb, line 1442
def proxy?
  !!(@proxy_from_env ? proxy_uri : @proxy_address)
end

Истина, если запросы для этого соединения будут проксироваться

proxy_address() Показать исходный код
# File lib/net/http.rb, line 1461
def proxy_address
  if @proxy_from_env then
    proxy_uri&.hostname
  else
    @proxy_address
  end
end

Адрес сервера прокси, если он настроен.

Также алиас как: proxyaddr
proxy_from_env?() Показать исходный код
# File lib/net/http.rb, line 1447
def proxy_from_env?
  @proxy_from_env
end

Истина, если прокси для этого соединения определяется из среды

proxy_pass() Показать исходный код
# File lib/net/http.rb, line 1489
def proxy_pass
  if @proxy_from_env
    pass = proxy_uri&.password
    unescape(pass) if pass
  else
    @proxy_pass
  end
end

Пароль сервера прокси, если он настроен.

proxy_port() Показать исходный код
# File lib/net/http.rb, line 1470
def proxy_port
  if @proxy_from_env then
    proxy_uri&.port
  else
    @proxy_port
  end
end

Порт сервера прокси, если он настроен.

Также алиас как: proxyport
proxy_user() Показать исходный код
# File lib/net/http.rb, line 1479
def proxy_user
  if @proxy_from_env
    user = proxy_uri&.user
    unescape(user) if user
  else
    @proxy_user
  end
end

Имя пользователя сервера прокси, если он настроен.

proxyaddr()
Псевдоним для: proxy_address
proxyport()
Псевдоним для: proxy_port
read_timeout=(sec) Показать исходный код
# File lib/net/http.rb, line 1064
def read_timeout=(sec)
  @socket.read_timeout = sec if @socket
  @read_timeout = sec
end

Устанавливает таймаут чтения в секундах для self до целого числа sec; начальное значение равно 60.

Аргумент sec должен быть неотрицательным числовым значением:

http = Net::HTTP.new(hostname)
http.read_timeout # => 60
http.get('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
http.read_timeout = 0
http.get('/todos/1') # Raises Net::ReadTimeout.
request(req, body = nil) { |response| ... } Показать исходный код
# File lib/net/http.rb, line 1815
def request(req, body = nil, &block)  # :yield: +response+
  unless started?
    start {
      req['connection'] ||= 'close'
      return request(req, body, &block)
    }
  end
  if proxy_user()
    req.proxy_basic_auth proxy_user(), proxy_pass() unless use_ssl?
  end
  req.set_body_internal body
  res = transport_request(req, &block)
  if sspi_auth?(res)
    sspi_auth(req)
    res = transport_request(req, &block)
  end
  res
end

Отправляет объект HTTPRequest req на сервер HTTP.

Если req является запросом Net::HTTP::Post или Net::HTTP::Put содержащим данные, данные также отправляются. Предоставление данных для запроса Net::HTTP::Head или Net::HTTP::Get приводит к ошибке ArgumentError.

Возвращает объект HTTPResponse.

При вызове с блоком, передаёт объект HTTPResponse в блок. Тело ответа ещё не будет прочитано; блок может обработать его используя HTTPResponse#read_body, если необходимо.

Этот метод никогда не вызывает исключений Net::*.

request_get(path, initheader = nil) { |response| ... } Показать исходный код
# File lib/net/http.rb, line 1726
def request_get(path, initheader = nil, &block) # :yield: +response+
  request(Get.new(path, initheader), &block)
end

Отправляет запрос GET на path. Возвращает ответ как объект Net::HTTPResponse.

При вызове с блоком, передаёт объект HTTPResponse в блок. Тело ответа ещё не будет прочитано; блок может обработать его используя HTTPResponse#read_body, если необходимо.

Возвращает ответ.

Этот метод никогда не вызывает исключений Net::*.

response = http.request_get('/index.html')
# The entity body is already read in this case.
p response['content-type']
puts response.body

# Using a block
http.request_get('/index.html') {|response|
  p response['content-type']
  response.read_body do |str|   # read body now
    print str
  end
}
Также алиас как: get2
request_head(path, initheader = nil, &block) Показать исходный код
# File lib/net/http.rb, line 1740
def request_head(path, initheader = nil, &block)
  request(Head.new(path, initheader), &block)
end

Отправляет запрос HEAD на path и возвращает ответ как объект Net::HTTPResponse.

Возвращает ответ.

Этот метод никогда не вызывает исключений Net::*.

response = http.request_head('/index.html')
p response['content-type']
Также алиас как: head2
request_post(path, data, initheader = nil) { |response| ... } Показать исходный код
# File lib/net/http.rb, line 1770
def request_post(path, data, initheader = nil, &block) # :yield: +response+
  request Post.new(path, initheader), data, &block
end

Отправляет запрос POST на path.

Возвращает ответ как объект Net::HTTPResponse.

При вызове с блоком, в блок передаётся объект HTTPResponse. Тело ответа ещё не будет прочитано; блок может обработать его используя HTTPResponse#read_body, если необходимо.

Возвращает ответ.

Этот метод никогда не вызывает исключений Net::*.

# example
response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
p response.status
puts response.body          # body is already read in this case

# using block
http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
  p response.status
  p response['content-type']
  response.read_body do |str|   # read body now
    print str
  end
}
Также алиас как: post2
response_body_encoding=(value) Показать исходный код
# File lib/net/http.rb, line 965
def response_body_encoding=(value)
  value = Encoding.find(value) if value.is_a?(String)
  @response_body_encoding = value
end

Устанавливает кодировку, используемую для тела ответа; возвращает кодировку.

Переданное value может быть:

  • Объектом Encoding.

  • Названием кодировки.

  • Псевдонимом имени кодировки.

См. Encoding.

Примеры:

http = Net::HTTP.new(hostname)
http.response_body_encoding = Encoding::US_ASCII # => #<Encoding:US-ASCII>
http.response_body_encoding = 'US-ASCII'         # => "US-ASCII"
http.response_body_encoding = 'ASCII'            # => "ASCII"
send_request(name, path, data = nil, header = nil) Показать исходный код
# File lib/net/http.rb, line 1794
def send_request(name, path, data = nil, header = nil)
  has_response_body = name != 'HEAD'
  r = HTTPGenericRequest.new(name,(data ? true : false),has_response_body,path,header)
  request r, data
end

Отправляет запрос HTTP на сервер HTTP. Также отправляет строку DATA, если data задана.

Возвращает объект Net::HTTPResponse.

Этот метод никогда не вызывает исключений Net::*.

response = http.send_request('GET', '/index.html')
puts response.body
set_debug_output(output) Показать исходный код
# File lib/net/http.rb, line 925
def set_debug_output(output)
  warn 'Net::HTTP#set_debug_output called after HTTP started', uplevel: 1 if started?
  @debug_output = output
end

ПРЕДУПРЕЖДЕНИЕ Этот метод открывает серьезную уязвимость безопасности. Никогда не используйте этот метод в рабочем коде.

Устанавливает поток вывода для отладки:

http = Net::HTTP.new(hostname)
File.open('t.tmp', 'w') do |file|
  http.set_debug_output(file)
  http.start
  http.get('/nosuch/1')
  http.finish
end
puts File.read('t.tmp')

Вывод:

opening connection to jsonplaceholder.typicode.com:80...
opened
<- "GET /nosuch/1 HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: jsonplaceholder.typicode.com\r\n\r\n"
-> "HTTP/1.1 404 Not Found\r\n"
-> "Date: Mon, 12 Dec 2022 21:14:11 GMT\r\n"
-> "Content-Type: application/json; charset=utf-8\r\n"
-> "Content-Length: 2\r\n"
-> "Connection: keep-alive\r\n"
-> "X-Powered-By: Express\r\n"
-> "X-Ratelimit-Limit: 1000\r\n"
-> "X-Ratelimit-Remaining: 999\r\n"
-> "X-Ratelimit-Reset: 1670879660\r\n"
-> "Vary: Origin, Accept-Encoding\r\n"
-> "Access-Control-Allow-Credentials: true\r\n"
-> "Cache-Control: max-age=43200\r\n"
-> "Pragma: no-cache\r\n"
-> "Expires: -1\r\n"
-> "X-Content-Type-Options: nosniff\r\n"
-> "Etag: W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"\r\n"
-> "Via: 1.1 vegur\r\n"
-> "CF-Cache-Status: MISS\r\n"
-> "Server-Timing: cf-q-config;dur=1.3000000762986e-05\r\n"
-> "Report-To: {\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=yOr40jo%2BwS1KHzhTlVpl54beJ5Wx2FcG4gGV0XVrh3X9OlR5q4drUn2dkt5DGO4GDcE%2BVXT7CNgJvGs%2BZleIyMu8CLieFiDIvOviOY3EhHg94m0ZNZgrEdpKD0S85S507l1vsEwEHkoTm%2Ff19SiO\"}],\"group\":\"cf-nel\",\"max_age\":604800}\r\n"
-> "NEL: {\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}\r\n"
-> "Server: cloudflare\r\n"
-> "CF-RAY: 778977dc484ce591-DFW\r\n"
-> "alt-svc: h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400\r\n"
-> "\r\n"
reading 2 bytes...
-> "{}"
read 2 bytes
Conn keep-alive
start() { |http| ... } Показать исходный код
# File lib/net/http.rb, line 1233
def start  # :yield: http
  raise IOError, 'HTTP session already opened' if @started
  if block_given?
    begin
      do_start
      return yield(self)
    ensure
      do_finish
    end
  end
  do_start
  self
end

Открывает TCP-соединение и сеанс HTTP.

Когда этот метод вызывается с блоком, он передает объект Net::HTTP в блок и закрывает TCP-соединение и сеанс HTTP после выполнения блока.

При вызове с блоком он возвращает результат блока; в противном случае он возвращает self.

started?() Показать исходный код
# File lib/net/http.rb, line 1101
def started?
  @started
end

Возвращает true, если сеанс HTTP был начат.

Также алиасируется как: active?
trace(path, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1697
def trace(path, initheader = nil)
  request(Trace.new(path, initheader))
end

Отправляет запрос TRACE на path и получает ответ в виде объекта HTTPResponse.

unlock(path, body, initheader = nil) Показать исходный код
# File lib/net/http.rb, line 1655
def unlock(path, body, initheader = nil)
  request(Unlock.new(path, initheader), body)
end

Отправляет запрос UNLOCK на path и получает ответ в виде объекта HTTPResponse.

use_ssl=(flag) Показать исходный код
# File lib/net/http.rb, line 1118
def use_ssl=(flag)
  flag = flag ? true : false
  if started? and @use_ssl != flag
    raise IOError, "use_ssl value changed, but session already started"
  end
  @use_ssl = flag
end

Включает/выключает SSL. Этот флаг должен быть установлен до начала сеанса. Если вы измените значение use_ssl после запуска сеанса, объект Net::HTTP вызовет исключение IOError.

use_ssl?() Показать исходный код
# File lib/net/http.rb, line 1110
def use_ssl?
  @use_ssl
end

Возвращает true, если SSL/TLS используется с HTTP.

write_timeout=(sec) Показать исходный код
# File lib/net/http.rb, line 1074
def write_timeout=(sec)
  @socket.write_timeout = sec if @socket
  @write_timeout = sec
end

Устанавливает тайм-аут записи в секундах для self до целого числа sec; начальное значение равно 60.

Аргумент sec должен быть неотрицательным числовым значением.

Методы приватного экземпляра

D(msg)
Псевдоним для: debug
addr_port() Показать исходный код
# File lib/net/http.rb, line 1984
def addr_port
  addr = address
  addr = "[#{addr}]" if addr.include?(":")
  default_port = use_ssl? ? HTTP.https_default_port : HTTP.http_default_port
  default_port == port ? addr : "#{addr}:#{port}"
end

utils

begin_transport(req) Показать исходный код
# File lib/net/http.rb, line 1901
def begin_transport(req)
  if @socket.closed?
    connect
  elsif @last_communicated
    if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
      debug 'Conn close because of keep_alive_timeout'
      @socket.close
      connect
    elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
      debug "Conn close because of EOF"
      @socket.close
      connect
    end
  end

  if not req.response_body_permitted? and @close_on_empty_response
    req['connection'] ||= 'close'
  end

  req.update_uri address, port, use_ssl?
  req['host'] ||= addr_port()
end
connect() Показать исходный код
# File lib/net/http.rb, line 1253
def connect
  if use_ssl?
    # reference early to load OpenSSL before connecting,
    # as OpenSSL may take time to load.
    @ssl_context = OpenSSL::SSL::SSLContext.new
  end

  if proxy? then
    conn_addr = proxy_address
    conn_port = proxy_port
  else
    conn_addr = conn_address
    conn_port = port
  end

  debug "opening connection to #{conn_addr}:#{conn_port}..."
  s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
    begin
      TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
    rescue => e
      raise e, "Failed to open TCP connection to " +
        "#{conn_addr}:#{conn_port} (#{e.message})"
    end
  }
  s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
  debug "opened"
  if use_ssl?
    if proxy?
      plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
                                  write_timeout: @write_timeout,
                                  continue_timeout: @continue_timeout,
                                  debug_output: @debug_output)
      buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
      buf << "Host: #{@address}:#{@port}\r\n"
      if proxy_user
        credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
        buf << "Proxy-Authorization: Basic #{credential}\r\n"
      end
      buf << "\r\n"
      plain_sock.write(buf)
      HTTPResponse.read_new(plain_sock).value
      # assuming nothing left in buffers after successful CONNECT response
    end

    ssl_parameters = Hash.new
    iv_list = instance_variables
    SSL_IVNAMES.each_with_index do |ivname, i|
      if iv_list.include?(ivname)
        value = instance_variable_get(ivname)
        unless value.nil?
          ssl_parameters[SSL_ATTRIBUTES[i]] = value
        end
      end
    end
    @ssl_context.set_params(ssl_parameters)
    unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
      @ssl_context.session_cache_mode =
          OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
              OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
    end
    if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
      @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
    end

    # Still do the post_connection_check below even if connecting
    # to IP address
    verify_hostname = @ssl_context.verify_hostname

    # Server Name Indication (SNI) RFC 3546/6066
    case @address
    when Resolv::IPv4::Regex, Resolv::IPv6::Regex
      # don't set SNI, as IP addresses in SNI is not valid
      # per RFC 6066, section 3.

      # Avoid openssl warning
      @ssl_context.verify_hostname = false
    else
      ssl_host_address = @address
    end

    debug "starting SSL for #{conn_addr}:#{conn_port}..."
    s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
    s.sync_close = true
    s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address

    if @ssl_session and
       Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
      s.session = @ssl_session
    end
    ssl_socket_connect(s, @open_timeout)
    if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
      s.post_connection_check(@address)
    end
    debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
  end
  @socket = BufferedIO.new(s, read_timeout: @read_timeout,
                           write_timeout: @write_timeout,
                           continue_timeout: @continue_timeout,
                           debug_output: @debug_output)
  @last_communicated = nil
  on_connect
rescue => exception
  if s
    debug "Conn close because of connect error #{exception}"
    s.close
  end
  raise
end
debug(msg) Показать исходный код
# File lib/net/http.rb, line 1992
def debug(msg)
  return unless @debug_output
  @debug_output << msg
  @debug_output << "\n"
end

Добавляет сообщение в выходные данные отладки

Также используется как: D
do_finish() Показать исходный код
# File lib/net/http.rb, line 1374
def do_finish
  @started = false
  @socket.close if @socket
  @socket = nil
end
do_start() Показать исходный код
# File lib/net/http.rb, line 1247
def do_start
  connect
  @started = true
end
edit_path(path) Показать исходный код
# File lib/net/http.rb, line 1518
def edit_path(path)
  if proxy?
    if path.start_with?("ftp://") || use_ssl?
      path
    else
      "http://#{addr_port}#{path}"
    end
  else
    path
  end
end
end_transport(req, res) Показать исходный код
# File lib/net/http.rb, line 1924
def end_transport(req, res)
  @curr_http_version = res.http_version
  @last_communicated = nil
  if @socket.closed?
    debug 'Conn socket closed'
  elsif not res.body and @close_on_empty_response
    debug 'Conn close'
    @socket.close
  elsif keep_alive?(req, res)
    debug 'Conn keep-alive'
    @last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  else
    debug 'Conn close'
    @socket.close
  end
end
keep_alive?(req, res) Показать исходный код
# File lib/net/http.rb, line 1941
def keep_alive?(req, res)
  return false if req.connection_close?
  if @curr_http_version <= '1.0'
    res.connection_keep_alive?
  else   # HTTP/1.1 or later
    not res.connection_close?
  end
end
on_connect() Показать исходный код
# File lib/net/http.rb, line 1363
def on_connect
end
send_entity(path, data, initheader, dest, type, &block) Показать исходный код
# File lib/net/http.rb, line 1838
def send_entity(path, data, initheader, dest, type, &block)
  res = nil
  request(type.new(path, initheader), data) {|r|
    r.read_body dest, &block
    res = r
  }
  res
end

Выполняет запрос, использующий представление, и возвращает его тело.

sspi_auth(req) Показать исходный код
# File lib/net/http.rb, line 1965
def sspi_auth(req)
  n = Win32::SSPI::NegotiateAuth.new
  req["Proxy-Authorization"] = "Negotiate #{n.get_initial_token}"
  # Some versions of ISA will close the connection if this isn't present.
  req["Connection"] = "Keep-Alive"
  req["Proxy-Connection"] = "Keep-Alive"
  res = transport_request(req)
  authphrase = res["Proxy-Authenticate"]  or return res
  req["Proxy-Authorization"] = "Negotiate #{n.complete_authentication(authphrase)}"
rescue => err
  raise HTTPAuthenticationError.new('HTTP authentication failed', err)
end
sspi_auth?(res) Показать исходный код
# File lib/net/http.rb, line 1950
def sspi_auth?(res)
  return false unless @sspi_enabled
  if res.kind_of?(HTTPProxyAuthenticationRequired) and
      proxy? and res["Proxy-Authenticate"].include?("Negotiate")
    begin
      require 'win32/sspi'
      true
    rescue LoadError
      false
    end
  else
    false
  end
end
transport_request(req) { |res| ... } Показать исходный код
# File lib/net/http.rb, line 1849
def transport_request(req)
  count = 0
  begin
    begin_transport req
    res = catch(:response) {
      begin
        req.exec @socket, @curr_http_version, edit_path(req.path)
      rescue Errno::EPIPE
        # Failure when writing full request, but we can probably
        # still read the received response.
      end

      begin
        res = HTTPResponse.read_new(@socket)
        res.decode_content = req.decode_content
        res.body_encoding = @response_body_encoding
        res.ignore_eof = @ignore_eof
      end while res.kind_of?(HTTPInformation)

      res.uri = req.uri

      res
    }
    res.reading_body(@socket, req.response_body_permitted?) {
      yield res if block_given?
    }
  rescue Net::OpenTimeout
    raise
  rescue Net::ReadTimeout, IOError, EOFError,
         Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, Errno::ETIMEDOUT,
         # avoid a dependency on OpenSSL
         defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError,
         Timeout::Error => exception
    if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
      count += 1
      @socket.close if @socket
      debug "Conn close because of error #{exception}, and retry"
      retry
    end
    debug "Conn close because of error #{exception}"
    @socket.close if @socket
    raise
  end

  end_transport req, res
  res
rescue => exception
  debug "Conn close because of error #{exception}"
  @socket.close if @socket
  raise exception
end
unescape(value) Показать исходный код
# File lib/net/http.rb, line 1503
def unescape(value)
  require 'cgi/util'
  CGI.unescape(value)
end

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

Spec-Zone.ru

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