模块 Net

常量

HTTPGatewayTimeOut

网关超时响应的响应类(状态码 504)。

服务器充当网关或代理,但未及时收到上游服务器的响应。

参考

HTTPMovedTemporarily

已找到响应的响应类(状态码 302)。

已找到响应表示客户端应查看(浏览到)另一个 URL。

参考

HTTPMultipleChoice

多重选择响应的响应类(状态码 300)。

多重选择响应表示服务器为客户端可能选择的资源提供了多个选项。

参考

HTTPRequestEntityTooLarge

有效负载过大响应的响应类(状态码 413)。

请求大于服务器愿意或能够处理的大小。

参考

HTTPRequestTimeOut

请求超时响应的响应类(状态码 408)。

服务器等待请求超时。

参考

HTTPRequestURITooLarge

URI 过长响应的响应类(状态码 414)。

提供的 URI 对于服务器来说过长,无法处理。

参考

HTTPRequestURITooLong

URI 过长响应的响应类(状态码 414)。

提供的 URI 对于服务器来说过长,无法处理。

参考

HTTPRequestedRangeNotSatisfiable

范围不可满足响应的响应类(状态码 416)。

请求实体具有服务器或资源不支持的媒体类型。

参考

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

在互联网上,URI(通用资源标识符)是一个字符串,用于标识特定的资源。它由以下部分或全部组成:scheme、hostname、path、query 和 fragment;请参阅URI 语法

Ruby URI::Generic 对象表示互联网 URI。它提供 `scheme`、`hostname`、`path`、`query` 和 `fragment` 等方法。

Scheme

互联网 URI 具有一个scheme

Net::HTTP 中支持的两个 scheme 是 '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。

在该块中,您可以使用以下实例方法,每种方法都发送单个请求

  • HTTP 方法:

    • get、request_get:GET。

    • head、request_head:HEAD。

    • post、request_post:POST。

    • delete:DELETE。

    • options:OPTIONS。

    • trace:TRACE。

    • patch:PATCH。

  • WebDAV 方法:

    • copy:COPY。

    • lock:LOCK。

    • mkcol:MKCOL。

    • move:MOVE。

    • propfind:PROPFIND。

    • proppatch:PROPPATCH。

    • unlock:UNLOCK。

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

您可以使用方法 start 和 finish 手动管理会话

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

单请求会话

某些便捷方法通过以下方式自动处理会话

  • 创建 HTTP 对象

  • 启动会话。

  • 发送单个请求。

  • 完成会话。

  • 销毁对象。

发送 GET 请求的此类方法

  • ::get:返回字符串响应正文。

  • ::get_print:将字符串响应正文写入 $stdout。

  • ::get_response:返回Net::HTTPResponse对象。

发送 POST 请求的此类方法

  • ::post:将数据发布到主机。

  • ::post_form:将表单数据发布到主机。

HTTP 请求和响应

上面的许多方法都是便捷方法,每种方法都发送请求并返回一个字符串,而无需直接使用 Net::HTTPRequest 和 Net::HTTPResponse 对象。

但是,您可以直接创建请求对象、发送请求并检索响应对象;请参阅

跟随重定向

每个返回的响应都是Net::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 scheme,则 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 版本

调试