класс Net::HTTP
Класс 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) -
Если производительность важна, рассмотрите использование сеансов, которые снижают нагрузку на запросы. Этот сеанс содержит несколько запросов для методов 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 является строкой hostname, возвращаемый 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': не разархивирует тело, но удаляет заголовок. -
Любое другое значение: оставляет тело и заголовок без изменений.
Что здесь
Это категоризированный обзор методов и атрибутов.
Объекты Net::HTTP
Сессии
-
::start: Начинает новую сессию в новом объекте Net::HTTP.
-
#started? (алиас #active?): Возвращает, находится ли в сессии.
-
#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 с данными и возвращает объект ответа.
-
#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 (алиас #get2): Отправляет запрос GET и формирует объект ответа; если задан блок, вызывает блок с объектом, в противном случае возвращает объект.
-
#request_head (алиас #head2): Отправляет запрос HEAD и формирует объект ответа; если задан блок, вызывает блок с объектом, в противном случае возвращает объект.
-
#request_post (алиас #post2): Отправляет запрос 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 (алиас #proxyaddr): Возвращает адрес прокси.
-
#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? (алиасы ::is_version_1_2? и ::version_1_2): Возвращает true; сохранено для совместимости.
Отладка
-
#set_debug_output: Устанавливает поток вывода для отладки.
Атрибуты
Возвращает адрес прокси-хоста или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает пароль для доступа к прокси или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает номер порта прокси-хоста или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает имя пользователя для доступа к прокси или nil если его нет; см. Proxy Server at Net::HTTP.
Возвращает строку имени хоста или IP-адреса хоста, указанного в качестве аргумента address в ::new.
Устанавливает или возвращает путь к файлу сертификата CA в формате PEM.
Устанавливает или возвращает путь к каталогу CA, содержащему файлы сертификатов в формате PEM.
Устанавливает или возвращает объект OpenSSL::X509::Certificate, который будет использоваться для клиентской сертификации.
Устанавливает или возвращает X509::Store, который будет использоваться для проверки сертификата узла.
Устанавливает или возвращает доступные шифры SSL. См. OpenSSL::SSL::SSLContext#ciphers=.
Устанавливает или возвращает, следует ли закрывать соединение, когда ответ пуст; изначально false.
Возвращает значение тайм-аута продолжения; см. continue_timeout=.
Устанавливает или возвращает дополнительные сертификаты X509, которые будут добавлены к цепочке сертификатов. См. OpenSSL::SSL::SSLContext#add_certificate.
Устанавливает или возвращает, следует ли игнорировать конец файла при чтении тела ответа с заголовками Content-Length; изначально true.
Устанавливает или возвращает числовое (целое или вещественное) количество секунд для поддержания соединения открытым после отправки запроса; изначально 2. Если новый запрос сделан в течение заданного интервала, используется все еще открытое соединение; в противном случае соединение будет закрыто и будет установлено новое соединение.
Устанавливает или возвращает объект OpenSSL::PKey::RSA или OpenSSL::PKey::DSA.
Устанавливает или возвращает строку локального хоста, используемого для установления соединения; изначально nil.
Устанавливает или возвращает целое число локального порта, используемого для установления соединения; изначально nil.
Возвращает максимальное количество попыток повтора идемпотентного запроса; см. max_retries=.
Устанавливает или возвращает максимальную версию SSL. См. OpenSSL::SSL::SSLContext#max_version=.
Устанавливает или возвращает минимальную версию SSL. См. OpenSSL::SSL::SSLContext#min_version=.
Устанавливает или возвращает числовое (целое или вещественное) количество секунд ожидания открытия соединения; изначально 60. Если соединение не установлено в течение заданного интервала, возникает исключение.
Возвращает целое число номера порта, указанного в качестве аргумента port в ::new.
Устанавливает адрес прокси; см. 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. См. OpenSSL::SSL::SSLContext#ssl_version=.
Устанавливает или возвращает обратный вызов для проверки сертификата сервера.
Устанавливает или возвращает максимальную глубину проверки цепочки сертификатов.
Устанавливает или возвращает, нужно ли проверять, соответствует ли сертификат сервера имени хоста. См. OpenSSL::SSL::SSLContext#verify_hostname=.
Устанавливает или возвращает флаги для проверки сертификации сервера в начале сессии SSL/TLS. Допустимы OpenSSL::SSL::VERIFY_NONE или OpenSSL::SSL::VERIFY_PEER.
Возвращает числовое (целое или с плавающей запятой) значение, количество секунд ожидания записи одного блока (через один вызов write(2)); см. write_timeout=.
Методы Публичного Класса
# File lib/net/http.rb, line 900 def HTTP.default_port http_default_port() end
Возвращает целое число 80, стандартный порт для HTTP-запросов:
Net::HTTP.default_port # => 80
# File lib/net/http.rb, line 802 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.
# File lib/net/http.rb, line 761
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 812
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 908 def HTTP.http_default_port 80 end
Возвращает целое число 80, стандартный порт для HTTP-запросов:
Net::HTTP.http_default_port # => 80
# File lib/net/http.rb, line 916 def HTTP.https_default_port 443 end
Возвращает целое число 443, стандартный порт для HTTPS-запросов:
Net::HTTP.https_default_port # => 443
# File lib/net/http.rb, line 1065
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?(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
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, см. Proxy Server.
# File lib/net/http.rb, line 855
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.
# File lib/net/http.rb, line 882
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 1762 def proxy_class? defined?(@is_proxy_class) ? @is_proxy_class : false end
Возвращает true, если self — класс, созданный с помощью HTTP::Proxy.
# File lib/net/http.rb, line 1010
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 736 def HTTP.version_1_2 true end
Возвращает true; сохранено для совместимости.
# File lib/net/http.rb, line 741 def HTTP.version_1_2? true end
Возвращает true; сохранено для совместимости.
Общедоступные методы экземпляров
# File lib/net/http.rb, line 1380 def continue_timeout=(sec) @socket.continue_timeout = sec if @socket @continue_timeout = sec end
Устанавливает значение таймаута ожидания ответа 100 Continue, которое представляет собой количество секунд, в течение которых ожидается ответ 100 Continue. Если объект HTTP не получает ответа в течение этого времени, он отправляет тело запроса.
# File lib/net/http.rb, line 2123 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 2097
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 1708 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 1914
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 1938 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 1135
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 1274 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 1286 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 2043 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 1320
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 2137 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 2110 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 2070 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 2001 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 1537
def peer_cert
if not use_ssl? or not @socket
return nil
end
@socket.io.peer_cert
end Возвращает цепочку сертификатов X509 (массив строк) для сокета клиента сессии, или nil если нет.
# File lib/net/http.rb, line 1972 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 2084
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 2029 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 1785 def proxy? !!(@proxy_from_env ? proxy_uri : @proxy_address) end
Возвращает true если прокси-сервер определён, false в противном случае; см. Прокси-сервер.
# File lib/net/http.rb, line 1807
def proxy_address
if @proxy_from_env then
proxy_uri&.hostname
else
@proxy_address
end
end Возвращает адрес прокси-сервера, если определён, nil в противном случае; см. Прокси-сервер.
# File lib/net/http.rb, line 1792 def proxy_from_env? @proxy_from_env end
Возвращает true если прокси-сервер определён в среде, false в противном случае; см. Прокси-сервер.
# File lib/net/http.rb, line 1838
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 1817
def proxy_port
if @proxy_from_env then
proxy_uri&.port
else
@proxy_port
end
end Возвращает номер порта прокси-сервера, если определён, nil в противном случае; см. Прокси-сервер.
# File lib/net/http.rb, line 1827
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 2015 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>
# File lib/net/http.rb, line 1343 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 2295
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 2176 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 2189 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 2216 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 1229 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 2259 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 1188 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 1565
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 1413 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 2150 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 2057 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 1435
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 1425 def use_ssl? @use_ssl end
Возвращает true, если self использует SSL, false в противном случае. См. Net::HTTP#use_ssl=.
# File lib/net/http.rb, line 1367 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 2464
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 2381
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 1585
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" \
"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 # File lib/net/http.rb, line 2472 def debug(msg) return unless @debug_output @debug_output << msg @debug_output << "\n" end
Добавляет сообщение в вывод отладки
# File lib/net/http.rb, line 1713 def do_finish @started = false @socket.close if @socket @socket = nil end
# File lib/net/http.rb, line 1579 def do_start connect @started = true end
# File lib/net/http.rb, line 1867
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 2404
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 2421
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 1695 def on_connect end
# File lib/net/http.rb, line 2318
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 2445
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 2430
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 2329
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 # File lib/net/http.rb, line 1852 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.