класс Net::HTTPSession
Класс Net::HTTP предоставляет богатую библиотеку, которая реализует клиента в модели клиент-сервер, использующей протокол HTTP запросов-ответов. Для получения информации об HTTP, см.:
О примерах
Примеры здесь предполагают, что net/http был потребован (что также требует uri):
require 'net/http'
Многие примеры кода здесь используют эти веб-сайты:
Некоторые примеры также предполагают эти переменные:
uri = URI('https://jsonplaceholder.typicode.com/')
uri.freeze # Examples may not modify.
hostname = uri.hostname # => "jsonplaceholder.typicode.com"
path = uri.path # => "/"
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'
Стратегии
-
Если вы будете делать только несколько GET-запросов, рассмотрите использование
OpenURI. -
Если вы будете делать только несколько запросов всех типов, рассмотрите использование различных методов-утилит в этом классе. Каждый из следующих методов автоматически запускает и завершает сеанс, который отправляет один запрос:
# Return string response body. Net::HTTP.get(hostname, path) Net::HTTP.get(uri) # Write string response body to $stdout. Net::HTTP.get_print(hostname, path) Net::HTTP.get_print(uri) # Return response as Net::HTTPResponse object. Net::HTTP.get_response(hostname, path) Net::HTTP.get_response(uri) data = '{"title": "foo", "body": "bar", "userId": 1}' Net::HTTP.post(uri, data) params = {title: 'foo', body: 'bar', userId: 1} Net::HTTP.post_form(uri, params) data = '{"title": "foo", "body": "bar", "userId": 1}' Net::HTTP.put(uri, data) -
Если производительность важна, рассмотрите использование сеансов, которые снижают накладные расходы на запросы. Этот сеанс содержит несколько запросов для методов HTTP и методов WebDAV:
Net::HTTP.start(hostname) do |http| # Session started automatically before block execution. http.get(path) http.head(path) body = 'Some text' http.post(path, body) # Can also have a block. http.put(path, body) http.delete(path) http.options(path) http.trace(path) http.patch(path, body) # Can also have a block. http.copy(path) http.lock(path, body) http.mkcol(path, body) http.move(path) http.propfind(path, body) http.proppatch(path, body) http.unlock(path, body) # Session finished automatically at block exit. end
Приведенные выше методы являются методами-утилитами, которые посредством своих немногих аргументов позволяют минимальный контроль над запросами. Для большего контроля рассмотрите использование объектов запроса.
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)
См. списки стандартных полей запроса и общих полей запроса в Полях запроса. Хост также может принимать другие пользовательские поля.
Сеансы HTTP
Сеанс — это соединение между сервером (хостом) и клиентом, который:
-
Начинается методом экземпляра
Net::HTTP#start. -
Может содержать любое количество запросов.
-
Заканчивается методом экземпляра
Net::HTTP#finish.
См. примеры сеансов в Стратегии.
Сеанс с использованием Net::HTTP.start
Если вам нужно выполнить множество запросов к одному хосту (и порту), рассмотрите использование метода класса Net::HTTP.start с блоком; метод автоматически обрабатывает сеанс, выполняя:
В блоке вы можете использовать эти методы экземпляра, каждый из которых отправляет один запрос:
-
-
get,request_get: GET. -
head,request_head: HEAD. -
post,request_post: POST. -
delete: DELETE. -
options: OPTIONS. -
trace: TRACE. -
patch: PATCH.
-
Сеанс с использованием 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::HTTPResponse. См. иерархию классов ответов.
В частности, класс Net::HTTPRedirection является родителем всех классов перенаправления. Это позволяет создать оператор case для правильной обработки перенаправлений:
def fetch(uri, limit = 10)
# You should choose a better exception.
raise ArgumentError, 'Too many HTTP redirects' if limit == 0
res = Net::HTTP.get_response(URI(uri))
case res
when Net::HTTPSuccess # Any success class.
res
when Net::HTTPRedirection # Any redirection class.
location = res['Location']
warn "Redirected to #{location}"
fetch(location, limit - 1)
else # Any other class.
res.value
end
end
fetch(uri)
Базовая аутентификация
Базовая аутентификация выполняется в соответствии с RFC2617:
req = Net::HTTP::Get.new(uri)
req.basic_auth('user', 'pass')
res = Net::HTTP.start(hostname) do |http|
http.request(req)
end
Потоковая передача тел ответов
По умолчанию Net::HTTP считывает весь ответ в память. Если вы обрабатываете большие файлы или хотите реализовать индикатор прогресса, вы можете вместо этого передавать тело непосредственно в IO.
Net::HTTP.start(hostname) do |http|
req = Net::HTTP::Get.new(uri)
http.request(req) do |res|
open('t.tmp', 'w') do |f|
res.read_body do |chunk|
f.write chunk
end
end
end
end
HTTPS
HTTPS включен для соединения HTTP с помощью Net::HTTP#use_ssl=:
Net::HTTP.start(hostname, :use_ssl => true) do |http| req = Net::HTTP::Get.new(uri) res = http.request(req) end
Или, если вы просто хотите выполнить GET-запрос, вы можете передать объект URI, который имеет URL HTTPS. Net::HTTP автоматически включает проверку TLS, если объект URI имеет схему ‘https’ URI:
uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com/> Net::HTTP.get(uri)
Прокси-сервер
Объект HTTP может иметь прокси-сервер.
Вы можете создать объект HTTP с прокси-сервером, используя метод Net::HTTP.new или метод Net::HTTP.start.
Прокси может быть определён либо аргументом p_addr либо переменной среды 'http_proxy'.
Прокси, используя аргумент p_addr в качестве строки
Когда аргумент p_addr — строка имени хоста, возвращаемый http использует указанный хост в качестве прокси:
http = Net::HTTP.new(hostname, nil, 'proxy.example') http.proxy? # => true http.proxy_from_env? # => false 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_from_env? # => false 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 = Net::HTTP.new(hostname) http.proxy? # => true http.proxy_from_env? # => true http.proxy_address # => "example.com" # These use default values. http.proxy_port # => 80 http.proxy_user # => nil http.proxy_pass # => nil
Строка URI может содержать имя пользователя прокси, пароль и номер порта:
ENV['http_proxy'] = 'http://pname:ppass@example.com:8000' http = Net::HTTP.new(hostname) http.proxy? # => true http.proxy_from_env? # => true http.proxy_address # => "example.com" http.proxy_port # => 8000 http.proxy_user # => "pname" http.proxy_pass # => "ppass"
Фильтрация прокси
С помощью метода Net::HTTP.new (но не Net::HTTP.start) можно использовать аргумент 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
Сжатие и расжатие
Net::HTTP не сжимает тело запроса перед отправкой.
По умолчанию Net::HTTP добавляет заголовок 'Accept-Encoding' к новому объекту запроса:
Net::HTTP::Get.new(uri)['Accept-Encoding'] # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
Это запрашивает у сервера сжать тело ответа, если оно есть; сервер не обязан это делать.
Net::HTTP не распаковывает автоматически тело ответа, если в ответе есть заголовок 'Content-Range'.
В противном случае распаковка (или её отсутствие) зависит от значения заголовка Content-Encoding:
-
'deflate','gzip', или'x-gzip': распаковывает тело и удаляет заголовок. -
'none'или'identity': не распаковывает тело, но удаляет заголовок. -
Любое другое значение: оставляет тело и заголовок без изменений.
Что здесь
Сначала, что где-то ещё. Class Net::HTTP:
-
Наследуется от класса Object.
Это структурированный обзор методов и атрибутов.
Объекты Net::HTTP
Сессии
-
::start: Начинает новую сессию в новом объекте Net::HTTP.
-
#started?: Возвращает, находится ли в сессии.
-
#finish: Завершает активную сессию.
-
#start: Начинает новую сессию в существующем объекте Net::HTTP (
self).
Подключения
-
:continue_timeout: Возвращает таймаут продолжения.
-
#continue_timeout=: Устанавливает таймаут продолжения в секундах.
-
:keep_alive_timeout: Возвращает таймаут поддержания соединения.
-
:keep_alive_timeout=: Устанавливает таймаут поддержания соединения.
-
:max_retries: Возвращает максимальное количество попыток.
-
#max_retries=: Устанавливает максимальное количество попыток.
-
:open_timeout: Возвращает таймаут открытия.
-
:open_timeout=: Устанавливает таймаут открытия.
-
:read_timeout: Возвращает таймаут чтения.
-
:read_timeout=: Устанавливает таймаут чтения.
-
:ssl_timeout: Возвращает таймаут SSL.
-
:ssl_timeout=: Устанавливает таймаут SSL.
-
:write_timeout: Возвращает таймаут записи.
-
write_timeout=: Устанавливает таймаут записи.
Запросы
-
::get: Отправляет запрос GET и возвращает строковое тело ответа.
-
::get_print: Отправляет запрос GET и записывает строковое тело ответа в $stdout.
-
::get_response: Отправляет запрос GET и возвращает объект ответа.
-
::post_form: Отправляет запрос POST с данными формы и возвращает объект ответа.
-
::post: Отправляет запрос POST с данными и возвращает объект ответа.
-
::put: Отправляет запрос PUT с данными и возвращает объект ответа.
-
#copy: Отправляет запрос COPY и возвращает объект ответа.
-
#delete: Отправляет запрос DELETE и возвращает объект ответа.
-
#get: Отправляет запрос GET и возвращает объект ответа.
-
#head: Отправляет запрос HEAD и возвращает объект ответа.
-
#lock: Отправляет запрос LOCK и возвращает объект ответа.
-
#mkcol: Отправляет запрос MKCOL и возвращает объект ответа.
-
#move: Отправляет запрос MOVE и возвращает объект ответа.
-
#options: Отправляет запрос OPTIONS и возвращает объект ответа.
-
#patch: Отправляет запрос PATCH и возвращает объект ответа.
-
#post: Отправляет запрос POST и возвращает объект ответа.
-
#propfind: Отправляет запрос PROPFIND и возвращает объект ответа.
-
#proppatch: Отправляет запрос PROPPATCH и возвращает объект ответа.
-
#put: Отправляет запрос PUT и возвращает объект ответа.
-
#request: Отправляет запрос и возвращает объект ответа.
-
#request_get: Отправляет запрос GET и формирует объект ответа; если передан блок, вызывает блок с объектом, в противном случае возвращает объект.
-
#request_head: Отправляет запрос HEAD и формирует объект ответа; если передан блок, вызывает блок с объектом, в противном случае возвращает объект.
-
#request_post: Отправляет запрос POST и формирует объект ответа; если передан блок, вызывает блок с объектом, в противном случае возвращает объект.
-
#send_request: Отправляет запрос и возвращает объект ответа.
-
#trace: Отправляет запрос TRACE и возвращает объект ответа.
-
#unlock: Отправляет запрос UNLOCK и возвращает объект ответа.
Ответы
-
:close_on_empty_response: Возвращает, нужно ли закрывать соединение при пустом ответе.
-
:close_on_empty_response=: Устанавливает, нужно ли закрывать соединение при пустом ответе.
-
:ignore_eof: Возвращает, нужно ли игнорировать конец файла при чтении тела ответа с заголовками
Content-Length. -
:ignore_eof=: Устанавливает, нужно ли игнорировать конец файла при чтении тела ответа с заголовками
Content-Length. -
:response_body_encoding: Возвращает кодировку, используемую для тела ответа.
-
#response_body_encoding=: Устанавливает кодировку тела ответа.
Прокси
-
:proxy_address: Возвращает адрес прокси.
-
:proxy_address=: Устанавливает адрес прокси.
-
::proxy_class?: Возвращает, является ли
selfклассом прокси. -
#proxy?: Возвращает, имеет ли
selfпрокси. -
#proxy_address: Возвращает адрес прокси.
-
#proxy_from_env?: Возвращает, взят ли прокси из переменной среды.
-
:proxy_from_env=: Устанавливает, должен ли прокси браться из переменной среды.
-
:proxy_pass: Возвращает пароль прокси.
-
:proxy_pass=: Устанавливает пароль прокси.
-
:proxy_port: Возвращает порт прокси.
-
:proxy_port=: Устанавливает порт прокси.
-
#proxy_user: Возвращает имя пользователя прокси.
-
:proxy_user=: Устанавливает имя пользователя прокси.
Безопасность
-
:ca_file: Возвращает путь к файлу сертификата CA.
-
:ca_file=: Устанавливает путь к файлу сертификата CA.
-
:ca_path: Возвращает путь к каталогу CA, содержащему сертификаты.
-
:ca_path=: Устанавливает путь к каталогу CA, содержащему сертификаты.
-
:cert: Возвращает объект
OpenSSL::X509::Certificateдля использования при клиентской сертификации. -
:cert=: Устанавливает объект
OpenSSL::X509::Certificateдля использования при клиентской сертификации. -
:cert_store: Возвращает X509::Store для проверки сертификата удалённого узла.
-
:cert_store=: Устанавливает X509::Store для проверки сертификата удалённого узла.
-
:ciphers: Возвращает доступные шифры SSL.
-
:ciphers=: Устанавливает доступные шифры SSL.
-
:extra_chain_cert: Возвращает дополнительные сертификаты X509, которые нужно добавить к цепочке сертификатов.
-
:extra_chain_cert=: Устанавливает дополнительные сертификаты X509, которые нужно добавить к цепочке сертификатов.
-
:key: Возвращает объект
OpenSSL::PKey::RSAилиOpenSSL::PKey::DSA. -
:key=: Устанавливает объект
OpenSSL::PKey::RSAилиOpenSSL::PKey::DSA. -
:max_version: Возвращает максимальную версию SSL.
-
:max_version=: Устанавливает максимальную версию SSL.
-
:min_version: Возвращает минимальную версию SSL.
-
:min_version=: Устанавливает минимальную версию SSL.
-
#peer_cert: Возвращает цепочку сертификатов X509 для сокета удалённого узла сессии.
-
:ssl_version: Возвращает версию SSL.
-
:ssl_version=: Устанавливает версию SSL.
-
#use_ssl=: Устанавливает, будет ли новая сессия использовать протокол Transport Layer Security.
-
#use_ssl?: Возвращает, использует ли
selfSSL. -
:verify_callback: Возвращает обратный вызов для проверки сертификата сервера.
-
:verify_callback=: Устанавливает обратный вызов для проверки сертификата сервера.
-
:verify_depth: Возвращает максимальную глубину проверки цепочки сертификатов.
-
:verify_depth=: Устанавливает максимальную глубину проверки цепочки сертификатов.
-
:verify_hostname: Возвращает флаги проверки сертификации сервера в начале сессии SSL/TLS.
-
:verify_hostname=: Устанавливает флаги проверки сертификации сервера в начале сессии SSL/TLS.
-
:verify_mode: Возвращает флаги проверки сертификации сервера в начале сессии SSL/TLS.
-
:verify_mode=: Устанавливает флаги проверки сертификации сервера в начале сессии SSL/TLS.
Адреса и порты
-
:address: Возвращает строку имени хоста или IP-адреса хоста.
-
::default_port: Возвращает целое число 80, стандартный порт для
HTTPзапросов. -
::http_default_port: Возвращает целое число 80, стандартный порт для
HTTPзапросов. -
::https_default_port: Возвращает целое число 443, стандартный порт для запросов HTTPS.
-
#ipaddr: Возвращает IP-адрес для соединения.
-
#ipaddr=: Устанавливает IP-адрес для соединения.
-
:local_host: Возвращает строку локального хоста, используемого для установления соединения.
-
:local_host=: Устанавливает строку локального хоста, используемого для установления соединения.
-
:local_port: Возвращает целое число локального порта, используемого для установления соединения.
-
:local_port=: Устанавливает целое число локального порта, используемого для установления соединения.
-
:port: Возвращает целое число номера порта.
Версия HTTP
-
::version_1_2? (алиас ::version_1_2): Возвращает true; сохранено для совместимости.
Отладка
-
#set_debug_output: Устанавливает поток вывода для отладки.
Атрибуты
Позволяет установить конфигурацию по умолчанию, которая будет использоваться при создании нового соединения.
Пример:
Net::HTTP.default_configuration = {
read_timeout: 1,
write_timeout: 1
}
http = Net::HTTP.new(hostname)
http.open_timeout # => 60
http.read_timeout # => 1
http.write_timeout # => 1
Возвращает адрес прокси-сервера или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает пароль для доступа к прокси-серверу или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает номер порта прокси-сервера или nil если его нет; см. Proxy Server at Net::HTTP.
Использовать SSL при обращении к прокси-серверу. Если Net::HTTP не использует прокси, nil.
Возвращает имя пользователя для доступа к прокси-серверу или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает строку имени хоста или IP-адреса хоста, указанного в качестве аргумента address в ::new.
Устанавливает или возвращает путь к файлу сертификата CA в формате PEM.
Устанавливает или возвращает путь к каталогу CA, содержащему файлы сертификатов в формате PEM.
Устанавливает или возвращает объект OpenSSL::X509::Certificate, который будет использоваться для клиентского сертификата.
Устанавливает или возвращает X509::Store, который будет использоваться для проверки сертификата узла.
Устанавливает или возвращает доступные шифры SSL. См. :SSL::SSLContext#ciphers=.
Устанавливает или возвращает, следует ли закрывать соединение, когда ответ пуст; изначально false.
Возвращает значение таймаута продолжения; см. continue_timeout=.
Устанавливает или возвращает дополнительные сертификаты X509, которые будут добавлены в цепочку сертификатов. См. :SSL::SSLContext#add_certificate.
Устанавливает или возвращает, следует ли игнорировать конец файла при чтении тела ответа с заголовками Content-Length; изначально true.
Устанавливает или возвращает числовое (целое или вещественное) количество секунд, в течение которых соединение будет оставаться открытым после отправки запроса; изначально 2. Если новый запрос сделан в течение данного интервала, используется всё ещё открытое соединение; в противном случае соединение будет закрыто, и будет открыто новое соединение.
Устанавливает или возвращает объект OpenSSL::PKey::RSA или OpenSSL::PKey::DSA.
Устанавливает или возвращает строку локального хоста, используемого для установления соединения; изначально nil.
Устанавливает или возвращает целое число локального порта, используемого для установления соединения; изначально nil.
Возвращает максимальное количество попыток повтора идемпотентного запроса; см. max_retries=.
Устанавливает или возвращает максимальную версию SSL. См. :SSL::SSLContext#max_version=.
Устанавливает или возвращает минимальную версию SSL. См. :SSL::SSLContext#min_version=.
Устанавливает или возвращает числовое (целое или вещественное) значение в секундах, ожидаемое для открытия подключения; по умолчанию 60. Если подключение не установлено в заданный интервал, генерируется исключение.
Устанавливает адрес прокси-сервера; см. Proxy Server.
Устанавливает, следует ли определять прокси-сервер из переменной среды ‘ENV['http_proxy']’; см. Proxy Using ENV[‘http_proxy’].
Устанавливает пароль для доступа к прокси-серверу; см. Proxy Server.
Устанавливает порт прокси-сервера; см. Proxy Server.
Устанавливает имя пользователя для доступа к прокси-серверу; см. Proxy Server.
Возвращает числовое (целое или вещественное) значение в секундах, ожидаемое для чтения одного блока (с помощью одной вызова read(2)); см. read_timeout=.
Возвращает кодировку, используемую для тела ответа; см. response_body_encoding=.
Устанавливает или возвращает таймаут SSL в секундах.
Устанавливает или возвращает версию SSL. См. :SSL::SSLContext#ssl_version=.
Устанавливает или возвращает обратный вызов для проверки сертификации сервера.
Устанавливает или возвращает максимальную глубину проверки цепочки сертификатов.
Устанавливает или возвращает флаг, указывающий на необходимость проверки соответствия сертификата сервера имени хоста. См. :SSL::SSLContext#verify_hostname=.
Устанавливает или возвращает флаги для проверки сертификации сервера в начале сессии SSL/TLS. Приемлемы OpenSSL::SSL::VERIFY_NONE или OpenSSL::SSL::VERIFY_PEER.
Возвращает числовое (целое или вещественное) значение в секундах, ожидаемое для записи одного блока (с помощью одного вызова write(2)); см. write_timeout=.
Публичные методы класса
Исходный код
# File lib/net/http.rb, line 935 def HTTP.default_port http_default_port() end
Возвращает целое число 80, порт по умолчанию для HTTP-запросов:
Net::HTTP.default_port # => 80
Исходный код
# File lib/net/http.rb, line 804 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: класс запроса для метода HTTPGET. -
Net::HTTP#get: вспомогательный метод для метода HTTPGET.
Исходный код
# File lib/net/http.rb, line 763
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.
Исходный код
# File lib/net/http.rb, line 814
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 вместо строки тела.
Исходный код
# File lib/net/http.rb, line 943 def HTTP.http_default_port 80 end
Возвращает целое число 80, порт по умолчанию для HTTP-запросов:
Net::HTTP.http_default_port # => 80
Исходный код
# File lib/net/http.rb, line 951 def HTTP.https_default_port 443 end
Возвращает целое число 443, порт по умолчанию для HTTPS-запросов:
Net::HTTP.https_default_port # => 443
Исходный код
# File lib/net/http.rb, line 1100
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = 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
http.proxy_use_ssl = @proxy_use_ssl
elsif p_addr == :ENV then
http.proxy_from_env = true
else
if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, 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
http.proxy_use_ssl = p_use_ssl
end
http
end Возвращает новый объект Net::HTTP http (но не открывает TCP-соединение или HTTP-сессию).
Если указан только строковый аргумент address (и 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_no_proxy, см. Прокси-сервер.
Исходный код
# File lib/net/http.rb, line 857
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: класс запроса для метода HTTPPOST. -
Net::HTTP#post: вспомогательный метод для метода HTTPPOST.
Исходный код
# File lib/net/http.rb, line 884
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
}
Исходный код
# File lib/net/http.rb, line 1826 def proxy_class? defined?(@is_proxy_class) ? @is_proxy_class : false end
Возвращает true, если self является классом, созданным HTTP::Proxy.
Исходный код
# File lib/net/http.rb, line 920
def HTTP.put(url, data, header = nil)
start(url.hostname, url.port,
:use_ssl => url.scheme == 'https' ) {|http|
http.put(url, data, header)
}
end Отправляет PUT-запрос на сервер; возвращает объект 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.put(_uri, data, headers) # => #<Net::HTTPCreated 201 Created readbody=true>
puts res.body
Вывод:
{
"title": "foo",
"body": "bar",
"userId": 1,
"id": 101
}
Связанные элементы:
-
Net::HTTP::Put: класс запроса для метода HTTPPUT. -
Net::HTTP#put: вспомогательный метод для метода HTTPPUT.
Исходный код
# File lib/net/http.rb, line 1045
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:
-
Для аргументов
addressиport, см.Net::HTTP.new. -
Для аргументов, определяющих прокси
p_addrиp_pass, см. Сервер прокси. -
Для аргумента
opts, см. ниже.
Без блока:
-
Вызывает
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, где каждый ключ — вызываемый метод или аксессор, а значение — устанавливаемое значение.
Ключи могут включать:
Примечание: Если port — nil и opts[:use_ssl] — истинное значение, значение, передаваемое в new — Net::HTTP.https_default_port, а не port.
Исходный код
# File lib/net/http.rb, line 738 def HTTP.version_1_2 true end
Возвращает true; сохранено для совместимости.
Исходный код
# File lib/net/http.rb, line 743 def HTTP.version_1_2? true end
Возвращает true; сохранено для совместимости.
Публичные методы экземпляра
Исходный код
# File lib/net/http.rb, line 1451 def continue_timeout=(sec) @socket.continue_timeout = sec if @socket @continue_timeout = sec end
Устанавливает значение тайм-аута продолжения, которое представляет собой количество секунд ожидания ожидаемого ответа 100 Continue. Если HTTP-объект не получает ответ за это время, он отправляет тело запроса.
Исходный код
# File lib/net/http.rb, line 2195 def copy(path, initheader = nil) request(Copy.new(path, initheader)) end
Отправляет запрос COPY на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Copy, созданном из строки path и начального хеша заголовков initheader.
http = Net::HTTP.new(hostname)
http.copy('/todos/1')
Исходный код
# File lib/net/http.rb, line 2169
def delete(path, initheader = {'Depth' => 'Infinity'})
request(Delete.new(path, initheader))
end Отправляет запрос DELETE на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Delete, созданном из строки path и начального хеша заголовков initheader.
http = Net::HTTP.new(hostname)
http.delete('/todos/1')
Исходный код
# File lib/net/http.rb, line 1770 def finish raise IOError, 'HTTP session not yet started' unless started? do_finish end
Завершает HTTP-сеанс:
http = Net::HTTP.new(hostname) http.start http.started? # => true http.finish # => nil http.started? # => false
Вызывает исключение IOError, если сеанс не активен.
Исходный код
# File lib/net/http.rb, line 1981
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 Отправляет запрос GET на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Get, созданном из строки path и начального хеша заголовков initheader.
Если передан блок, вызывает блок с телом ответа:
http = Net::HTTP.new(hostname)
http.get('/todos/1') do |res|
p res
end # => #<Net::HTTPOK 200 OK readbody=true>
Вывод:
"{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}"
Без блока просто возвращает объект ответа:
http.get('/') # => #<Net::HTTPOK 200 OK readbody=true>
Связанные элементы:
-
Net::HTTP::Get: класс запроса для метода HTTP GET. -
Net::HTTP.get: отправляет запрос GET, возвращает тело ответа.
Исходный код
# File lib/net/http.rb, line 2005 def head(path, initheader = nil) request(Head.new(path, initheader)) end
Отправляет запрос HEAD на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Head, созданном из строки path и начального хеша заголовков initheader:
res = http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
res.body # => nil
res.to_hash.take(3)
# =>
[["date", ["Wed, 15 Feb 2023 15:25:42 GMT"]],
["content-type", ["application/json; charset=utf-8"]],
["connection", ["close"]]]
Исходный код
# File lib/net/http.rb, line 1205
def inspect
"#<#{self.class} #{@address}:#{@port} open=#{started?}>"
end Возвращает строковое представление self:
Net::HTTP.new(hostname).inspect # => "#<Net::HTTP jsonplaceholder.typicode.com:80 open=false>"
Исходный код
# File lib/net/http.rb, line 1345 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
Исходный код
# File lib/net/http.rb, line 1357 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-адрес может не быть установлен, если сеанс запущен.
Исходный код
# File lib/net/http.rb, line 2115 def lock(path, body, initheader = nil) request(Lock.new(path, initheader), body) end
Отправляет запрос LOCK на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Lock, созданном из строки path, строки body и начального хеша заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.lock('/todos/1', data)
Исходный код
# File lib/net/http.rb, line 1391
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
Исходный код
# File lib/net/http.rb, line 2209 def mkcol(path, body = nil, initheader = nil) request(Mkcol.new(path, initheader), body) end
Отправляет запрос MKCOL на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Mkcol, созданном из строки path, строки body и начального хеша заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http.mkcol('/todos/1', data)
http = Net::HTTP.new(hostname)
Исходный код
# File lib/net/http.rb, line 2182 def move(path, initheader = nil) request(Move.new(path, initheader)) end
Отправляет запрос MOVE на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Move, созданном из строки path и начального хеша заголовков initheader.
http = Net::HTTP.new(hostname)
http.move('/todos/1')
Исходный код
# File lib/net/http.rb, line 2142 def options(path, initheader = nil) request(Options.new(path, initheader)) end
Отправляет запрос OPTIONS на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Options, созданном из строки path и начального хэша заголовков initheader.
http = Net::HTTP.new(hostname)
http.options('/')
Исходный код
# File lib/net/http.rb, line 2068 def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+ send_entity(path, data, initheader, dest, Patch, &block) end
Отправляет запрос PATCH на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Patch, созданном из строки path, строки data, и начального хэша заголовков initheader.
При использовании блока, вызывает блок с телом ответа:
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.patch('/todos/1', data) do |res|
p res
end # => #<Net::HTTPOK 200 OK readbody=true>
Вывод:
"{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false,\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\"\n}"
Без блока, просто возвращает объект ответа:
http.patch('/todos/1', data) # => #<Net::HTTPCreated 201 Created readbody=true>
Исходный код
# File lib/net/http.rb, line 1593
def peer_cert
if not use_ssl? or not @socket
return nil
end
@socket.io.peer_cert
end Возвращает цепочку сертификатов X509 (массив строк) для сокета peer сеанса, или nil если нет.
Исходный код
# File lib/net/http.rb, line 2039 def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+ send_entity(path, data, initheader, dest, Post, &block) end
Отправляет запрос POST на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Post, созданном из строки path, строки data, и начального хэша заголовков initheader.
При использовании блока, вызывает блок с телом ответа:
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.post('/todos', data) do |res|
p res
end # => #<Net::HTTPCreated 201 Created readbody=true>
Вывод:
"{\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\",\n \"id\": 201\n}"
Без блока, просто возвращает объект ответа:
http.post('/todos', data) # => #<Net::HTTPCreated 201 Created readbody=true>
Связанные:
-
Net::HTTP::Post: класс запроса для HTTP метода POST. -
Net::HTTP.post: отправляет запрос POST, возвращает тело ответа.
Исходный код
# File lib/net/http.rb, line 2156
def propfind(path, body = nil, initheader = {'Depth' => '0'})
request(Propfind.new(path, initheader), body)
end Отправляет запрос PROPFIND на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Propfind, созданном из строки path, строки body, и начального хэша заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.propfind('/todos/1', data)
Исходный код
# File lib/net/http.rb, line 2101 def proppatch(path, body, initheader = nil) request(Proppatch.new(path, initheader), body) end
Отправляет запрос PROPPATCH на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Proppatch, созданном из строки path, строки body, и начального хэша заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.proppatch('/todos/1', data)
Исходный код
# File lib/net/http.rb, line 1852 def proxy? !!(@proxy_from_env ? proxy_uri : @proxy_address) end
Возвращает true если сервер прокси определён, false в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 1874
def proxy_address
if @proxy_from_env then
proxy_uri&.hostname
else
@proxy_address
end
end Возвращает адрес сервера прокси, если определён, nil в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 1859 def proxy_from_env? @proxy_from_env end
Возвращает true если сервер прокси определён в переменных окружения, false в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 1905
def proxy_pass
if @proxy_from_env
pass = proxy_uri&.password
unescape(pass) if pass
else
@proxy_pass
end
end Возвращает пароль сервера прокси, если определён, nil в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 1884
def proxy_port
if @proxy_from_env then
proxy_uri&.port
else
@proxy_port
end
end Возвращает номер порта сервера прокси, если определён, nil в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 1894
def proxy_user
if @proxy_from_env
user = proxy_uri&.user
unescape(user) if user
else
@proxy_user
end
end Возвращает имя пользователя сервера прокси, если определён, nil в противном случае; см. Сервер прокси.
Исходный код
# File lib/net/http.rb, line 2087 def put(path, data, initheader = nil) request(Put.new(path, initheader), data) end
Отправляет запрос PUT на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Put, созданном из строки path, строки data, и начального хэша заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.put('/todos/1', data) # => #<Net::HTTPOK 200 OK readbody=true>
Связанные:
-
Net::HTTP::Put: класс запроса для HTTP метода PUT. -
Net::HTTP.put: отправляет запрос PUT, возвращает тело ответа.
Исходный код
# File lib/net/http.rb, line 1414 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.
Исходный код
# File lib/net/http.rb, line 2367
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 Отправляет заданный запрос req на сервер; формирует ответ в объект Net::HTTPResponse.
Заданный req должен быть экземпляром подкласса Net::HTTPRequest. Аргумент body следует указывать только при необходимости для запроса.
Без блока возвращает объект ответа:
http = Net::HTTP.new(hostname)
req = Net::HTTP::Get.new('/todos/1')
http.request(req)
# => #<Net::HTTPOK 200 OK readbody=true>
req = Net::HTTP::Post.new('/todos')
http.request(req, 'xyzzy')
# => #<Net::HTTPCreated 201 Created readbody=true>
С блоком вызывает блок с ответом и возвращает ответ:
req = Net::HTTP::Get.new('/todos/1')
http.request(req) do |res|
p res
end # => #<Net::HTTPOK 200 OK readbody=true>
Вывод:
#<Net::HTTPOK 200 OK readbody=false>
Исходный код
# File lib/net/http.rb, line 2248 def request_get(path, initheader = nil, &block) # :yield: +response+ request(Get.new(path, initheader), &block) end
Отправляет запрос GET на сервер; формирует ответ в объект Net::HTTPResponse объект.
Запрос основан на объекте Net::HTTP::Get, созданном из строки path и хэша начальных заголовков initheader.
Без блока возвращает объект ответа:
http = Net::HTTP.new(hostname)
http.request_get('/todos') # => #<Net::HTTPOK 200 OK readbody=true>
С блоком вызывает блок с объектом ответа и возвращает объект ответа:
http.request_get('/todos') do |res|
p res
end # => #<Net::HTTPOK 200 OK readbody=true>
Вывод:
#<Net::HTTPOK 200 OK readbody=false>
Исходный код
# File lib/net/http.rb, line 2261 def request_head(path, initheader = nil, &block) request(Head.new(path, initheader), &block) end
Отправляет запрос HEAD на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Head, созданном из строки path и хэша начальных заголовков initheader.
http = Net::HTTP.new(hostname)
http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
Исходный код
# File lib/net/http.rb, line 2288 def request_post(path, data, initheader = nil, &block) # :yield: +response+ request Post.new(path, initheader), data, &block end
Отправляет запрос POST на сервер; формирует ответ в объект Net::HTTPResponse объект.
Запрос основан на объекте Net::HTTP::Post, созданном из строки path, строки data, и хэша начальных заголовков initheader.
Без блока возвращает объект ответа:
http = Net::HTTP.new(hostname)
http.post('/todos', 'xyzzy')
# => #<Net::HTTPCreated 201 Created readbody=true>
С блоком вызывает блок с телом ответа и возвращает объект ответа:
http.post('/todos', 'xyzzy') do |res|
p res
end # => #<Net::HTTPCreated 201 Created readbody=true>
Вывод:
"{\n \"xyzzy\": \"\",\n \"id\": 201\n}"
Исходный код
# File lib/net/http.rb, line 1299 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"
Исходный код
# File lib/net/http.rb, line 2331 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-запрос на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTPRequest, созданном из строки path, строки data, и хэша начальных заголовков header. Этот объект является экземпляром подкласса Net::HTTPRequest, который соответствует заданной строке в верхнем регистре name, которая должна быть методом HTTP-запроса или методом запроса WebDAV.
Примеры:
http = Net::HTTP.new(hostname)
http.send_request('GET', '/todos/1')
# => #<Net::HTTPOK 200 OK readbody=true>
http.send_request('POST', '/todos', 'xyzzy')
# => #<Net::HTTPCreated 201 Created readbody=true>
Исходный код
# File lib/net/http.rb, line 1258 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 Исходный код
# File lib/net/http.rb, line 1621
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 Начинает сеанс HTTP.
Без блока возвращает self:
http = Net::HTTP.new(hostname) # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false> http.start # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=true> http.started? # => true http.finish
С блоком вызывает блок с self, завершает сеанс по выходу из блока и возвращает значение блока:
http.start do |http| http end # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false> http.started? # => false
Исходный код
# File lib/net/http.rb, line 1484 def started? @started end
Возвращает true , если сеанс HTTP был запущен:
http = Net::HTTP.new(hostname) http.started? # => false http.start http.started? # => true http.finish # => nil http.started? # => false Net::HTTP.start(hostname) do |http| http.started? end # => true http.started? # => false
Исходный код
# File lib/net/http.rb, line 2222 def trace(path, initheader = nil) request(Trace.new(path, initheader)) end
Отправляет запрос TRACE на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Trace, созданном из строки path и хэша начальных заголовков initheader.
http = Net::HTTP.new(hostname)
http.trace('/todos/1')
Исходный код
# File lib/net/http.rb, line 2129 def unlock(path, body, initheader = nil) request(Unlock.new(path, initheader), body) end
Отправляет запрос UNLOCK на сервер; возвращает экземпляр подкласса Net::HTTPResponse.
Запрос основан на объекте Net::HTTP::Unlock, созданном из строки path, строки body, и хэша начальных заголовков initheader.
data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.unlock('/todos/1', data)
Исходный код
# File lib/net/http.rb, line 1506
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 Устанавливает, будет ли новый сеанс использовать Transport Layer Security:
Вызывает IOError, если попытка изменить во время сессии.
Вызывает OpenSSL::SSL::SSLError, если порт не является портом HTTPS.
Исходный код
# File lib/net/http.rb, line 1496 def use_ssl? @use_ssl end
Возвращает true, если self использует SSL, false в противном случае. Смотрите Net::HTTP#use_ssl=.
Исходный код
# File lib/net/http.rb, line 1438 def write_timeout=(sec) @socket.write_timeout = sec if @socket @write_timeout = sec end
Устанавливает таймаут записи, в секундах, для self в целое число sec; начальное значение равно 60.
Аргумент sec должен быть неотрицательным числовым значением:
_uri = uri.dup
_uri.path = '/posts'
body = 'bar' * 200000
data = <<EOF
{"title": "foo", "body": "#{body}", "userId": "1"}
EOF
headers = {'content-type': 'application/json'}
http = Net::HTTP.new(hostname)
http.write_timeout # => 60
http.post(_uri.path, data, headers)
# => #<Net::HTTPCreated 201 Created readbody=true>
http.write_timeout = 0
http.post(_uri.path, data, headers) # Raises Net::WriteTimeout.
Приватные методы экземпляра
Исходный код
# File lib/net/http.rb, line 2539
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
Исходный код
# File lib/net/http.rb, line 2456
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 Исходный код
# File lib/net/http.rb, line 1641
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?
if @proxy_use_ssl
proxy_sock = OpenSSL::SSL::SSLSocket.new(s)
ssl_socket_connect(proxy_sock, @open_timeout)
else
proxy_sock = s
end
proxy_sock = BufferedIO.new(proxy_sock, 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" \
"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"
proxy_sock.write(buf)
HTTPResponse.read_new(proxy_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 Исходный код
# File lib/net/http.rb, line 2547 def debug(msg) return unless @debug_output @debug_output << msg @debug_output << "\n" end
Добавляет сообщение в вывод отладки
Исходный код
# File lib/net/http.rb, line 1775 def do_finish @started = false @socket.close if @socket @socket = nil end
Исходный код
# File lib/net/http.rb, line 1934
def edit_path(path)
if proxy?
if path.start_with?("ftp://") || use_ssl?
path
else
"http://#{addr_port}#{path}"
end
else
path
end
end Исходный код
# File lib/net/http.rb, line 2479
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 Исходный код
# File lib/net/http.rb, line 2496
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 Исходный код
# File lib/net/http.rb, line 2390
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 Выполняет запрос, который использует представление и возвращает его тело.
Исходный код
# File lib/net/http.rb, line 2520
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 Исходный код
# File lib/net/http.rb, line 2505
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 Исходный код
# File lib/net/http.rb, line 2401
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?) {
if block_given?
count = max_retries # Don't restart in the middle of a download
yield res
end
}
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 Исходный код
# File lib/net/http.rb, line 1919 def unescape(value) require 'cgi/util' CGI.unescape(value) end
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.