网络::HTTP

Net::HTTP 提供了一个丰富的库,可用于构建 HTTP 用户代理。有关 HTTP 的更多详细信息,请参阅RFC2616

Net::HTTP 旨在与 URI 密切合作。,并设计为与 Net::HTTP 一起使用。URI::HTTP#hostURI::HTTP#portURI::HTTP#request_uri

如果您只执行几个 GET 请求,则应尝试 OpenURI。

简单示例

所有示例都假定您已使用以下命令加载了 Net::HTTP:

require 'net/http'

这也需要“uri”,因此您不需要单独要求它。

下一节中的 Net::HTTP 方法不保留连接。如果要执行许多 HTTP 请求,则不建议使用它们。

获取

Net::HTTP.get('example.com', '/index.html') # => String

按 URI 获取

uri = URI('http://example.com/index.html?count=10')
Net::HTTP.get(uri) # => String

使用动态参数获取

uri = URI('http://example.com/index.html')
params = { :limit => 10, :page => 3 }
uri.query = URI.encode_www_form(params)

res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)

发布

uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
puts res.body

具有多个值的 POST

uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
puts res.body

如何使用 Net::HTTP

以下示例代码可用作 HTTP 用户代理的基础,该用户代理可以使用持久连接执行各种请求类型。

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

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

  response = http.request request # Net::HTTPResponse object
end

Net::HTTP::start 会立即创建与 HTTP 服务器的连接,该服务器在块期间保持打开状态。如果服务器指示它支持持久连接,则该连接将对块中的多个请求保持打开状态。

如果您希望在多个 HTTP 请求中重用连接而不自动关闭它,则可以使用 ::new,然后调用和手动。#start#finish

Net::HTTP 支持的请求类型在下面的“HTTP 请求类”一节中列出。

对于所有 Net::HTTP 请求对象和快捷方式请求方法,您可以为请求路径提供 String 或 Net::HTTP 将从中提取请求路径的 URI。

响应数据

uri = URI('http://example.com/index.html')
res = Net::HTTP.get_response(uri)

# Headers
res['Set-Cookie']            # => String
res.get_fields('set-cookie') # => Array
res.to_hash['set-cookie']    # => Array
puts "Headers: #{res.to_hash.inspect}"

# Status
puts res.code       # => '200'
puts res.message    # => 'OK'
puts res.class.name # => 'HTTPOK'

# Body
puts res.body if res.response_body_permitted?

重定向后

每个 Net::HTTPResponse 对象都属于其响应代码的类。

例如,所有 2XX 响应都是 Net::HTTPSuccess 子类的实例,3XX 响应是 Net::HTTPRedirection 子类的实例,200 响应是 Net::HTTPOK 类的实例。有关响应类的详细信息,请参阅下面的“HTTP 响应类”部分。

使用 case 语句,您可以正确处理各种类型的响应:

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

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

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

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

发布

可以使用 Net::HTTP::P ost 请求类进行 POST。此示例创建一个 URL 编码的 POST 正文:

uri = URI('http://www.example.com/todo.cgi')
req = Net::HTTP::Post.new(uri)
req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')

res = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(req)
end

case res
when Net::HTTPSuccess, Net::HTTPRedirection
  # OK
else
  res.value
end

要发送 multipart/form-data,请使用:Net::HTTPHeader#set_form

req = Net::HTTP::Post.new(uri)
req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data')

可以使用相应的请求类 (Net::HTTP::P ut) 以相同的方式创建可以包含正文(如 PUT)的其他请求。

设置标题

下面的示例使用 If-Modified-Since 标头执行条件 GET。如果文件自标头中的时间以来未被修改,则将返回“未修改”响应。有关详细信息,请参阅 RFC 2616 第 9.3 节。

uri = URI('http://example.com/cached_response')
file = File.stat 'cached_response'

req = Net::HTTP::Get.new(uri)
req['If-Modified-Since'] = file.mtime.rfc2822

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

open 'cached_response', 'w' do |io|
  io.write res.body
end if res.is_a?(Net::HTTPSuccess)

基本身份验证

基本身份验证根据RFC2617执行。

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

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

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

流式响应正文

默认情况下,Net::HTTP 将整个响应读入内存。如果您正在处理大型文件或希望实现进度条,则可以改为将正文直接流式传输到 IO。

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

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

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

HTTPS的

通过以下方式为 HTTP 连接启用 HTTPS。Net::HTTP#use_ssl=

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

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

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

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

在以前的 Ruby 版本中,您需要需要 'net/https' 才能使用 HTTPS。这不再是真的。

代理

如果存在,Net::HTTP 将自动从环境变量创建代理。要禁用 ,请传递代理地址。http_proxyhttp_proxynil

您还可以创建自定义代理:

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

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

有关更多详细信息和示例,请参阅 Net::HTTP.new,例如需要用户名和密码的代理。

压缩

Net::HTTP 会自动添加 Accept-Encoding 来压缩响应正文,并自动解压缩 gzip 和 deflate 响应,除非发送了 Range 标头。

可以通过 Accept-Encoding: 标识标头禁用压缩。

By alex

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注