class Net::HTTPSession

类 Net::HTTP 提供了一个丰富的库,该库在客户端-服务器模型中实现了使用 HTTP 请求-响应协议的客户端。有关 HTTP 的信息,请参阅

关于示例

策略

  • 如果您只需要发出少量的 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

在 Internet 上,URI(统一资源标识符)是一个标识特定资源的字符串。它包含以下部分或全部:方案、主机名、路径、查询和片段;请参阅URI 语法

Ruby 的 URI::Generic 对象表示一个 Internet URI。它提供了 schemehostnamepathqueryfragment 等方法。

方案

一个 Internet 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.start;该方法通过以下方式自动处理会话:

  • 在执行块之前调用start

  • 执行块。

  • 在执行块之后调用finish

在块中,您可以使用这些实例方法,每个方法都会发送单个请求:

使用 Net::HTTP.start 和 Net::HTTP.finish 的会话

您可以使用方法startfinish手动管理会话

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 请求的此类方法:

发送 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

通过Net::HTTP#use_ssl=启用 HTTP 连接的 HTTPS

Net::HTTP.start(hostname, :use_ssl => true) do |http|
  req = Net::HTTP::Get.new(uri)
  res = http.request(req)
end

或者,如果您只想发出 GET 请求,则可以传入一个具有 HTTPS URL 的 URI 对象。如果 URI 对象具有“https”URI 方案,则 Net::HTTP 会自动启用 TLS 验证

uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com/>
Net::HTTP.get(uri)

代理服务器

HTTP 对象可以具有一个代理服务器

您可以使用方法Net::HTTP.new或方法Net::HTTP.start创建一个带有代理服务器的 HTTP 对象。

代理可以通过参数 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:[email protected]: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"

这会请求服务器在有响应主体的情况下对其进行 zip 编码;服务器不一定必须这样做。

如果响应具有标头 'Content-Range',则 Net::HTTP 不会自动解压缩响应主体。

否则,是否进行解压缩取决于头部 Content-Encoding 的值。

  • 'deflate''gzip''x-gzip':解压缩主体并删除头部。

  • 'none''identity':不解压缩主体,但删除头部。

  • 任何其他值:保持主体和头部不变。

本页内容

首先,介绍其他地方的内容。 类 Net::HTTP

  • 继承自 Object 类。

这是方法和属性的分类摘要。

Net::HTTP 对象

  • ::new:创建一个新的实例。

  • #inspect:返回 self 的字符串表示形式。

会话

  • ::start:在新 Net::HTTP 对象中开始一个新会话。

  • #started?:返回是否处于会话中。

  • #finish:结束活动会话。

  • #start:在现有 Net::HTTP 对象 (self) 中开始一个新会话。

连接

请求

  • ::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 请求并返回响应对象。

响应

代理

安全

  • :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=:设置新会话是否使用传输层安全协议。

  • #use_ssl?:返回 self 是否使用 SSL。

  • :verify_callback:返回服务器证书验证的回调。

  • :verify_callback=:设置服务器证书验证的回调。

  • :verify_depth:返回证书链验证的最大深度。

  • :verify_depth=:设置证书链验证的最大深度。

  • :verify_hostname:返回在 SSL/TLS 会话开始时用于服务器证书验证的标志。

  • :verify_hostname=:设置在 SSL/TLS 会话开始时用于服务器证书验证的标志。

  • :verify_mode:返回在 SSL/TLS 会话开始时用于服务器证书验证的标志。

  • :verify_mode=:设置在 SSL/TLS 会话开始时用于服务器证书验证的标志。

地址和端口

HTTP 版本

调试

属性

default_configuration[RW]

允许设置创建新连接时将使用的默认配置。

示例

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
proxy_address[R]

返回代理主机的地址,如果没有则返回 nil;参见 Net::HTTP 的代理服务器

proxy_pass[R]

返回访问代理的密码,如果没有则返回 nil;参见 Net::HTTP 的代理服务器

proxy_port[R]

返回代理主机的端口号,如果没有则返回 nil;参见 Net::HTTP 的代理服务器

proxy_use_ssl[R]

与代理通信时使用 SSL。 如果 Net::HTTP 不使用代理,则为 nil。

proxy_user[R]

返回访问代理的用户名,如果没有则返回 nil;参见 Net::HTTP 的代理服务器

address[R]

返回在 ::new 中作为参数 address 给出的字符串主机名或主机 IP。

ca_file[RW]

设置或返回 PEM 格式的 CA 证书文件的路径。

ca_path[RW]

设置或返回包含 PEM 格式证书文件的 CA 目录的路径。

cert[RW]

设置或返回用于客户端证书的 OpenSSL::X509::Certificate 对象。

cert_store[RW]

设置或返回用于验证对等证书的 X509::Store。

ciphers[RW]

设置或返回可用的 SSL 密码。请参阅 :SSL::SSLContext#ciphers=

close_on_empty_response[RW]

设置或返回当响应为空时是否关闭连接;初始值为 false

continue_timeout[R]

返回继续超时值;请参阅 continue_timeout=。

extra_chain_cert[RW]

设置或返回要添加到证书链的额外 X509 证书。请参阅 :SSL::SSLContext#add_certificate

ignore_eof[RW]

设置或返回在使用 Content-Length 标头读取响应主体时是否忽略文件结尾;初始值为 true

keep_alive_timeout[RW]

设置或返回在发送请求后保持连接打开的秒数(整数或浮点数);初始值为 2。如果在给定的时间间隔内发出新请求,则会使用仍然打开的连接;否则,连接将已关闭并打开新连接。

key[RW]

设置或返回 OpenSSL::PKey::RSA 或 OpenSSL::PKey::DSA 对象。

local_host[RW]

设置或返回用于建立连接的本地主机字符串;初始值为 nil

local_port[RW]

设置或返回用于建立连接的本地端口整数;初始值为 nil

max_retries[R]

返回重试幂等请求的最大次数;请参阅 max_retries=

max_version[RW]

设置或返回最大 SSL 版本。请参阅 :SSL::SSLContext#max_version=

min_version[RW]

设置或返回最小 SSL 版本。请参阅 :SSL::SSLContext#min_version=

open_timeout[RW]

设置或返回等待连接打开的秒数(整数或浮点数);初始值为 60。如果在给定的时间间隔内未建立连接,则会引发异常。

port[R]

返回在 ::new 中作为参数 port 给出的整数端口号。

proxy_address[W]

设置代理地址;参见 代理服务器

proxy_from_env[W]

设置是否从环境变量 ‘ENV['http_proxy']’ 确定代理;参见 使用 ENV[‘http_proxy’] 的代理

proxy_pass[W]

设置代理密码;参见 代理服务器

proxy_port[W]

设置代理端口;参见 代理服务器

proxy_use_ssl[W]
proxy_user[W]

设置代理用户;参见 代理服务器

read_timeout[R]

返回等待读取一个块(通过一个 read(2) 调用)的秒数(整数或浮点数);请参阅 read_timeout=

response_body_encoding[R]

返回用于响应主体的编码;请参阅 response_body_encoding=

ssl_timeout[RW]

设置或返回 SSL 超时秒数。

ssl_version[RW]

设置或返回 SSL 版本。请参阅 :SSL::SSLContext#ssl_version=

verify_callback[RW]

设置或返回服务器证书验证的回调。

verify_depth[RW]

设置或返回证书链验证的最大深度。

verify_hostname[RW]

设置或返回是否验证服务器证书对于主机名是否有效。请参阅 :SSL::SSLContext#verify_hostname=

verify_mode[RW]

设置或返回在 SSL/TLS 会话开始时用于服务器证书验证的标志。可接受的值为 OpenSSL::SSL::VERIFY_NONE 或 OpenSSL::SSL::VERIFY_PEER。

write_timeout[R]

返回等待写入一个块(通过一个 write(2) 调用)的秒数(整数或浮点数);请参阅 write_timeout=

公共类方法

default_port() 点击以切换源代码

返回整数 80,用于 HTTP 请求的默认端口

Net::HTTP.default_port # => 80
# File net/http.rb, line 935
def HTTP.default_port
  http_default_port()
end
Net::HTTP.get(主机名, 路径, 端口 = 80) → body 点击以切换源代码
Net::HTTP:get(uri, headers = {}, port = uri.port) → body

发送 GET 请求并返回 HTTP 响应主体作为字符串。

使用字符串参数 hostnamepath

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)

相关

# File 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
Net::HTTP.get_print(主机名, 路径, 端口 = 80) → nil 点击以切换源代码
Net::HTTP:get_print(uri, headers = {}, port = uri.port) → nil

类似于 Net::HTTP.get,但将返回的主体写入 $stdout;返回 nil

# File 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_response(主机名, 路径, 端口 = 80) → http_response 点击以切换源代码
Net::HTTP:get_response(uri, headers = {}, port = uri.port) → http_response

类似于 Net::HTTP.get,但返回一个 Net::HTTPResponse 对象而不是主体字符串。

# File 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
http_default_port() 点击以切换源代码

返回整数 80,用于 HTTP 请求的默认端口

Net::HTTP.http_default_port # => 80
# File net/http.rb, line 943
def HTTP.http_default_port
  80
end
https_default_port() 点击以切换源代码

返回整数 443,用于 HTTPS 请求的默认端口

Net::HTTP.https_default_port # => 443
# File net/http.rb, line 951
def HTTP.https_default_port
  443
end
is_version_1_2?()
别名为: version_1_2?
new(地址, 端口 = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil) 点击以切换源代码

返回一个新的 Net::HTTP 对象 http(但不打开 TCP 连接或 HTTP 会话)。

仅提供字符串参数 address(且 ENV['http_proxy'] 未定义或为 nil),则返回的 http

示例

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_addrp_no_proxy,请参阅 代理服务器

调用超类方法
# File 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
也别名为: newobj
newobj(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil)
别名: new
post(url, data, header = nil) 点击切换源代码

向主机发送数据;返回一个 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
}

相关

# File 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
post_form(url, params) 点击切换源代码

向主机发送数据;返回一个 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 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
proxy_class?() 点击切换源代码

如果 self 是由 HTTP::Proxy 创建的类,则返回 true。

# File net/http.rb, line 1826
def proxy_class?
  defined?(@is_proxy_class) ? @is_proxy_class : false
end
put(url, data, header = nil) 点击切换源代码

向服务器发送 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
}

相关

# File 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
start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) → http 点击切换源代码
start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) {|http| ... } → object

通过 Net::HTTP.new 创建一个新的 Net::HTTP 对象 http

  • 有关参数 addressport,请参见 Net::HTTP.new

  • 有关代理定义参数 p_addrp_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 哈希,其中每个键是要调用的方法或访问器,其值是要设置的值。

键可能包括

注意:如果 portnilopts[:use_ssl] 是真值,则传递给 new 的值是 Net::HTTP.https_default_port,而不是 port

# File 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
version_1_2() 点击切换源代码

返回 true;为了兼容性而保留。

# File net/http.rb, line 738
def HTTP.version_1_2
  true
end
version_1_2?() 点击切换源代码

返回 true;为了兼容性而保留。

# File net/http.rb, line 743
def HTTP.version_1_2?
  true
end
也别名为: is_version_1_2?

公共实例方法

active?()
别名: started?
continue_timeout=(sec) 点击切换源代码

设置继续超时值,即等待预期的 100 Continue 响应的秒数。如果 HTTP 对象在此秒数内未收到响应,则会发送请求正文。

# File net/http.rb, line 1451
def continue_timeout=(sec)
  @socket.continue_timeout = sec if @socket
  @continue_timeout = sec
end
copy(path, initheader = nil) 点击切换源代码

向服务器发送 COPY 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Copy 对象。

http = Net::HTTP.new(hostname)
http.copy('/todos/1')
# File net/http.rb, line 2195
def copy(path, initheader = nil)
  request(Copy.new(path, initheader))
end
delete(path, initheader = {'Depth' => 'Infinity'}) 点击切换源代码

向服务器发送 DELETE 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Delete 对象。

http = Net::HTTP.new(hostname)
http.delete('/todos/1')
# File net/http.rb, line 2169
def delete(path, initheader = {'Depth' => 'Infinity'})
  request(Delete.new(path, initheader))
end
finish() 点击切换源代码

结束 HTTP 会话

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

如果未处于会话中,则引发 IOError。

# File net/http.rb, line 1770
def finish
  raise IOError, 'HTTP session not yet started' unless started?
  do_finish
end
get(path, initheader = nil) {|res| ... } 点击切换源代码

向服务器发送 GET 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Get 对象。

如果给定了块,则使用响应正文调用该块

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>

相关

# File 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
get2(path, initheader = nil)
别名: request_get
head(path, initheader = nil) 点击切换源代码

向服务器发送 HEAD 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Head 对象。

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 net/http.rb, line 2005
def head(path, initheader = nil)
  request(Head.new(path, initheader))
end
head2(path, initheader = nil, &block)
别名: request_head
inspect() 点击切换源代码

返回 self 的字符串表示形式

Net::HTTP.new(hostname).inspect
# => "#<Net::HTTP jsonplaceholder.typicode.com:80 open=false>"
# File net/http.rb, line 1205
def inspect
  "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
end
ipaddr() 点击切换源代码

返回连接的 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 net/http.rb, line 1345
def ipaddr
  started? ?  @socket.io.peeraddr[3] : @ipaddr
end
ipaddr=(addr) 点击切换源代码

设置连接的 IP 地址。

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

如果会话已开始,则可能无法设置 IP 地址。

# File net/http.rb, line 1357
def ipaddr=(addr)
  raise IOError, "ipaddr value changed, but session already started" if started?
  @ipaddr = addr
end
lock(path, body, initheader = nil) 点击切换源代码

向服务器发送 LOCK 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 body 和初始标头哈希 initheader 创建的 Net::HTTP::Lock 对象。

data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.lock('/todos/1', data)
# File net/http.rb, line 2115
def lock(path, body, initheader = nil)
  request(Lock.new(path, initheader), body)
end
max_retries=(retries) 点击切换源代码

设置在发生 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 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
mkcol(path, body = nil, initheader = nil) 点击切换源代码

向服务器发送 MKCOL 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 body 和初始标头哈希 initheader 创建的 Net::HTTP::Mkcol 对象。

data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http.mkcol('/todos/1', data)
http = Net::HTTP.new(hostname)
# File net/http.rb, line 2209
def mkcol(path, body = nil, initheader = nil)
  request(Mkcol.new(path, initheader), body)
end
move(path, initheader = nil) 点击切换源代码

向服务器发送 MOVE 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Move 对象。

http = Net::HTTP.new(hostname)
http.move('/todos/1')
# File net/http.rb, line 2182
def move(path, initheader = nil)
  request(Move.new(path, initheader))
end
options(path, initheader = nil) 点击切换源代码

向服务器发送 Options 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Options 对象。

http = Net::HTTP.new(hostname)
http.options('/')
# File net/http.rb, line 2142
def options(path, initheader = nil)
  request(Options.new(path, initheader))
end
patch(path, data, initheader = nil) {|res| ... } 点击切换源代码

向服务器发送 PATCH 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 data 和初始标头哈希 initheader 创建的 Net::HTTP::Patch 对象。

如果给定了块,则使用响应正文调用该块

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 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
peer_cert() 点击切换源代码

返回会话的套接字对等方的 X509 证书链(字符串数组),如果没有则返回 nil

# File net/http.rb, line 1593
def peer_cert
  if not use_ssl? or not @socket
    return nil
  end
  @socket.io.peer_cert
end
post(path, data, initheader = nil) {|res| ... } 点击切换源代码

向服务器发送 POST 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 data 和初始标头哈希 initheader 创建的 Net::HTTP::Post 对象。

如果给定了块,则使用响应正文调用该块

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>

相关

# File 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
post2(path, data, initheader = nil)
别名: request_post
propfind(path, body = nil, initheader = {'Depth' => '0'}) 点击切换源代码

向服务器发送 PROPFIND 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 body 和初始标头哈希 initheader 创建的 Net::HTTP::Propfind 对象。

data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.propfind('/todos/1', data)
# File net/http.rb, line 2156
def propfind(path, body = nil, initheader = {'Depth' => '0'})
  request(Propfind.new(path, initheader), body)
end
proppatch(path, body, initheader = nil) 点击切换源代码

向服务器发送 PROPPATCH 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 body 和初始标头哈希 initheader 创建的 Net::HTTP::Proppatch 对象。

data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.proppatch('/todos/1', data)
# File net/http.rb, line 2101
def proppatch(path, body, initheader = nil)
  request(Proppatch.new(path, initheader), body)
end
proxy?() 点击切换源代码

如果定义了代理服务器,则返回 true,否则返回 false;请参见 代理服务器

# File net/http.rb, line 1852
def proxy?
  !!(@proxy_from_env ? proxy_uri : @proxy_address)
end
proxy_address() 点击切换源代码

返回代理服务器的地址(如果已定义),否则返回 nil;请参见 代理服务器

# File net/http.rb, line 1874
def proxy_address
  if @proxy_from_env then
    proxy_uri&.hostname
  else
    @proxy_address
  end
end
也别名为: proxyaddr
proxy_from_env?() 点击切换源代码

如果代理服务器在环境中定义,则返回 true,否则返回 false;请参阅 代理服务器

# File net/http.rb, line 1859
def proxy_from_env?
  @proxy_from_env
end
proxy_pass() 单击以切换源代码

如果定义了代理服务器密码,则返回该密码,否则返回 nil;请参阅 代理服务器

# File 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
proxy_port() 单击以切换源代码

如果定义了代理服务器端口号,则返回该端口号,否则返回 nil;请参阅 代理服务器

# File net/http.rb, line 1884
def proxy_port
  if @proxy_from_env then
    proxy_uri&.port
  else
    @proxy_port
  end
end
别名为:proxyport
proxy_user() 单击以切换源代码

如果定义了代理服务器用户名,则返回该用户名,否则返回 nil;请参阅 代理服务器

# File 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
proxyaddr()
别名为:proxy_address
proxyport()
别名为:proxy_port
put(path, data, initheader = nil) 单击以切换源代码

向服务器发送 PUT 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 data 和初始标头哈希 initheader 创建的 Net::HTTP::Put 对象。

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 net/http.rb, line 2087
def put(path, data, initheader = nil)
  request(Put.new(path, initheader), data)
end
read_timeout=(sec) 单击以切换源代码

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 net/http.rb, line 1414
def read_timeout=(sec)
  @socket.read_timeout = sec if @socket
  @read_timeout = sec
end
request(req, body = nil) { |response| ... } 单击以切换源代码

向服务器发送给定的请求 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 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
request_get(path, initheader = nil) { |response| ... } 单击以切换源代码

向服务器发送 GET 请求;将响应格式化为 Net::HTTPResponse 对象。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Get 对象。

如果没有给定块,则返回响应对象

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 net/http.rb, line 2248
def request_get(path, initheader = nil, &block) # :yield: +response+
  request(Get.new(path, initheader), &block)
end
别名为:get2
request_head(path, initheader = nil, &block) 单击以切换源代码

向服务器发送 HEAD 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Head 对象。

http = Net::HTTP.new(hostname)
http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
# File net/http.rb, line 2261
def request_head(path, initheader = nil, &block)
  request(Head.new(path, initheader), &block)
end
别名为:head2
request_post(path, data, initheader = nil) { |response| ... } 单击以切换源代码

向服务器发送 POST 请求;将响应格式化为 Net::HTTPResponse 对象。

该请求基于从字符串 path、字符串 data 和初始标头哈希 initheader 创建的 Net::HTTP::Post 对象。

如果没有给定块,则返回响应对象

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 net/http.rb, line 2288
def request_post(path, data, initheader = nil, &block) # :yield: +response+
  request Post.new(path, initheader), data, &block
end
别名为:post2
response_body_encoding=(value) 单击以切换源代码

设置用于响应主体的编码;返回编码。

给定的 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 net/http.rb, line 1299
def response_body_encoding=(value)
  value = Encoding.find(value) if value.is_a?(String)
  @response_body_encoding = value
end
send_request(name, path, data = nil, header = nil) 单击以切换源代码

向服务器发送 HTTP 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 data 和初始标头哈希 header 创建的 Net::HTTPRequest 对象。该对象是 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 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
set_debug_output(output) 单击以切换源代码

警告 此方法会打开严重的安全漏洞。切勿在生产代码中使用此方法。

设置调试的输出流

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 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
start() { |http| ... } 单击以切换源代码

启动 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 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
started?() 单击以切换源代码

如果已启动 HTTP 会话,则返回 true

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 net/http.rb, line 1484
def started?
  @started
end
别名为:active?
trace(path, initheader = nil) 单击以切换源代码

向服务器发送 TRACE 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path 和初始标头哈希 initheader 创建的 Net::HTTP::Trace 对象。

http = Net::HTTP.new(hostname)
http.trace('/todos/1')
# File net/http.rb, line 2222
def trace(path, initheader = nil)
  request(Trace.new(path, initheader))
end
unlock(path, body, initheader = nil) 单击以切换源代码

向服务器发送 UNLOCK 请求;返回 Net::HTTPResponse 子类的实例。

该请求基于从字符串 path、字符串 body 和初始标头哈希 initheader 创建的 Net::HTTP::Unlock 对象。

data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
http = Net::HTTP.new(hostname)
http.unlock('/todos/1', data)
# File net/http.rb, line 2129
def unlock(path, body, initheader = nil)
  request(Unlock.new(path, initheader), body)
end
use_ssl=(flag) 单击以切换源代码

设置新会话是否使用 传输层安全性

如果在会话期间尝试更改,则会引发 IOError。

如果端口不是 HTTPS 端口,则会引发 OpenSSL::SSL::SSLError。

# File 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
use_ssl?() 单击以切换源代码

如果 self 使用 SSL,则返回 true,否则返回 false。请参阅 Net::HTTP#use_ssl=

# File net/http.rb, line 1496
def use_ssl?
  @use_ssl
end
write_timeout=(sec) 单击以切换源代码

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 net/http.rb, line 1438
def write_timeout=(sec)
  @socket.write_timeout = sec if @socket
  @write_timeout = sec
end

私有实例方法

D(msg)
别名为:debug
addr_port() 单击以切换源代码

实用工具

# File 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
begin_transport(req) 单击以切换源代码
# File 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
connect() 单击以切换源代码
# File 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
debug(msg) 单击以切换源代码

向调试输出添加消息

# File net/http.rb, line 2547
def debug(msg)
  return unless @debug_output
  @debug_output << msg
  @debug_output << "\n"
end
别名为:D
do_finish() 单击以切换源代码
# File net/http.rb, line 1775
def do_finish
  @started = false
  @socket.close if @socket
  @socket = nil
end
do_start() 单击以切换源代码
# File net/http.rb, line 1635
def do_start
  connect
  @started = true
end
edit_path(path) 单击以切换源代码
# File 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
end_transport(req, res) 单击以切换源代码
# File 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
keep_alive?(req, res) 单击以切换源代码
# File 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
on_connect() 单击以切换源代码
# File net/http.rb, line 1757
def on_connect
end
send_entity(path, data, initheader, dest, type, &block) 单击以切换源代码

执行使用表示的请求并返回其主体。

# File 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
sspi_auth(req) 单击以切换源代码
# File 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
sspi_auth?(res) 单击以切换源代码
# File 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
transport_request(req) { |res| ... } 单击以切换源代码
# File 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
unescape(value) 单击以切换源代码
# File net/http.rb, line 1919
def unescape(value)
  require 'cgi/util'
  CGI.unescape(value)
end