首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Net::HTTP

Parent:Protocol

Ruby的HTTP客户端API。

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

Net :: HTTP被设计为与URI密切协作。URI :: Generic#host,URI :: Generic#port和URI :: HTTP#request_uri被设计为与Net :: HTTP协同工作。

如果你只是执行几个GET请求,你应该尝试OpenURI。

简单的例子

所有的例子都假设你已经加载了Net :: HTTP:

代码语言:javascript
复制
require 'net/http'

这也需要'uri',所以你不需要单独要求。

下一节中的Net :: HTTP方法不保留连接。如果您正在执行许多HTTP请求,则不推荐使用它们。

GET

代码语言:javascript
复制
Net::HTTP.get('example.com', '/index.html') # => String

GET by URI

代码语言:javascript
复制
uri = URI('http://example.com/index.html?count=10')
Net::HTTP.get(uri) # => String

使用动态参数进行GET

代码语言:javascript
复制
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)

POST

代码语言:javascript
复制
uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
puts res.body

带多个值的POST

代码语言:javascript
复制
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用户代理的基础,它可以使用持久连接执行各种请求类型。

代码语言:javascript
复制
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

::立即创建一个连接到HTTP服务器,该服务器在块的持续时间内保持打开状态。如果服务器指示它支持持续连接,则该连接将在块中的多个请求中保持打开状态。

下面的“HTTP请求类”部分列出了Net :: HTTP支持的请求类型。

如果您希望跨多个HTTP请求重新使用连接而不自动关闭连接,则可以使用:: new而不是:: start。如果当前没有打开,请求将自动打开到服务器的连接。您可以完成手动关闭连接。

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

响应

代码语言:javascript
复制
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 :: HTTP类的实例。有关响应类的详细信息,请参见下面的“HTTP响应类”部分。

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

代码语言:javascript
复制
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')

POST

可以使用Net :: HTTP :: Post请求类进行POST。这个例子创建一个urlencoded POST主体:

代码语言:javascript
复制
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

这时Net :: HTTP不支持multipart / form-data。发送multipart / form-data使用Net :: HTTPGenericRequest#body =和Net :: HTTPHeader#content_type =:

代码语言:javascript
复制
req = Net::HTTP::Post.new(uri)
req.body = multipart_data
req.content_type = 'multipart/form-data'

其他可以包含PUT等主体的请求可以使用相应的请求类(Net :: HTTP :: Put)以相同的方式创建。

设置标题

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

代码语言:javascript
复制
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执行的

代码语言:javascript
复制
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。

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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验证。

代码语言:javascript
复制
uri = URI('https://example.com/')
Net::HTTP.get(uri) # => String

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

代理

如果Net :: HTTP存在,它将自动从http_proxy环境变量创建一个代理。 要禁止使用http_proxy,请将代理地址传递给零。

您也可以创建一个自定义代理:

代码语言:javascript
复制
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
}

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

压缩

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

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

HTTP请求类

这是HTTP请求类层次结构。

  • Net::HTTPRequest
代码语言:txt
复制
-  [Net::HTTP::Get](http/get)
代码语言:txt
复制
-  [Net::HTTP::Head](http/head)
代码语言:txt
复制
-  [Net::HTTP::Post](http/post)
代码语言:txt
复制
-  [Net::HTTP::Patch](http/patch)
代码语言:txt
复制
-  [Net::HTTP::Put](http/put)
代码语言:txt
复制
-  [Net::HTTP::Proppatch](http/proppatch)
代码语言:txt
复制
-  [Net::HTTP::Lock](http/lock)
代码语言:txt
复制
-  [Net::HTTP::Unlock](http/unlock)
代码语言:txt
复制
-  [Net::HTTP::Options](http/options)
代码语言:txt
复制
-  [Net::HTTP::Propfind](http/propfind)
代码语言:txt
复制
-  [Net::HTTP::Delete](http/delete)
代码语言:txt
复制
-  [Net::HTTP::Move](http/move)
代码语言:txt
复制
-  [Net::HTTP::Copy](http/copy)
代码语言:txt
复制
-  [Net::HTTP::Mkcol](http/mkcol)
代码语言:txt
复制
-  [Net::HTTP::Trace](http/trace)

HTTP响应类

这里是HTTP响应类层次结构。所有类都在Net模块中定义,并且是Net :: HTTPResponse的子类。

HTTPUnknownResponse

对于未处理的HTTP扩展

HTTPInformation

1xx

HTTPContinue

100

HTTPSwitchProtocol

101

HTTPSuccess

2xx

HTTPOK

200

HTTPCreated

201

HTTPAccepted

202

HTTPNonAuthoritativeInformation

203

HTTPNoContent

204

HTTPResetContent

205

HTTPPartialContent

206

HTTPMultiStatus

207

HTTPIMUsed

226

HTTPRedirection

3xx

HTTPMultipleChoices

300

HTTPMovedPermanently

301

HTTPFound

302

HTTPSeeOther

303

HTTPNotModified

304

HTTPUseProxy

305

HTTPTemporaryRedirect

307

HTTPClientError

4xx

HTTPBadRequest

400

HTTPUnauthorized

401

HTTPPaymentRequired

402

HTTPForbidden

403

HTTPNotFound

404

HTTPMethodNotAllowed

405

HTTPNotAcceptable

406

HTTPProxyAuthenticationRequired

407

HTTPRequestTimeOut

408

HTTPConflict

409

HTTPGone

410

HTTPLengthRequired

411

HTTPPreconditionFailed

412

HTTPRequestEntityTooLarge

413

HTTPRequestURITooLong

414

HTTPUnsupportedMediaType

415

HTTPRequestedRangeNotSatisfiable

416

HTTPExpectationFailed

417

HTTPUnprocessableEntity

422

HTTPLocked

423

HTTPFailedDependency

424

HTTPUpgradeRequired

426

HTTPPreconditionRequired

428

HTTPTooManyRequests

429

HTTPRequestHeaderFieldsTooLarge

431

HTTPUnavailableForLegalReasons

451

HTTPServerError

5xx

HTTPInternalServerError

500

HTTPNotImplemented

501

HTTPBadGateway

502

HTTPServiceUnavailable

503

HTTPGatewayTimeOut

504

HTTPVersionNotSupported

505

HTTPInsufficientStorage

507

HTTPNetworkAuthenticationRequired

511

当存在协议错误时,也会产生Net :: HTTPBadResponse异常。

常量

SSL_ATTRIBUTES SSL_IVNAMES

属性

proxy_addressR

代理主机的地址。如果Net :: HTTP不使用代理,则为零。

proxy_passR

用于访问代理的用户密码。如果Net :: HTTP不使用代理,则为零。

proxy_portR

代理主机的端口号。如果Net :: HTTP不使用代理,则为零。

proxy_userR

用于访问代理的用户名。如果Net :: HTTP不使用代理,则为零。

addressR

要连接的DNS主机名或IP地址。

ca_fileRW

以PEM格式设置CA认证文件的路径。

该文件可以包含多个CA证书。

ca_pathRW

设置包含PEM格式认证的CA认证目录的路径。

certRW

将OpenSSL :: X509 :: Certificate对象设置为客户端证书。 (这种方法出现在Michal Rokos的OpenSSL扩展中)。

cert_storeRW

设置X509 :: Store来验证对等证书。

ciphersRW

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

close_on_empty_responseRW

continue_timeoutR

秒等待100继续响应。 如果HTTP对象在这几秒钟内没有收到响应,它会发送请求主体。 默认值是零。

keep_alive_timeoutRW

秒重用前一个请求的连接。如果空闲时间少于此保持活动超时,则Net :: HTTP将重用先前通信使用的TCP / IP套接字。默认值是2秒。

keyRW

设置OpenSSL :: PKey :: RSA或OpenSSL :: PKey :: DSA对象。(这种方法出现在Michal Rokos的OpenSSL扩展中。)

local_hostRW

用于建立连接的本地主机。

local_portRW

用于建立连接的本地端口。

open_timeoutRW

等待连接打开的秒数。可以使用任何数字,包括小数秒的浮点数。如果HTTP对象在这几秒钟内无法打开连接,则会引发Net :: OpenTimeout异常。默认值是60秒。

portR

要连接的端口号。

proxy_addressW

proxy_from_envW

proxy_passW

proxy_portW

proxy_userW

read_timeoutR

等待一个数据块读取的秒数(通过一次读取(2)调用)。可以使用任何数字,包括小数秒的浮点数。如果HTTP对象在这么多秒内无法读取数据,则会引发Net :: ReadTimeout异常。默认值是60秒。

ssl_timeoutRW

Sets the SSL timeout seconds.

ssl_versionRW

设置SSL版本。请参阅OpenSSL :: SSL :: SSLContext#ssl_version =

verify_callbackRW

设置服务器认证验证的验证回调。

verify_depthRW

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

verify_modeRW

在SSL / TLS会话开始时为服务器设置认证验证标志。

OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.

公共类方法

Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) Show source

创建一个类似Net :: HTTP的HTTP代理类,但通过指定的代理执行所有访问。

这个类已经过时了。你可以直接将这些参数传递给:: new。有关参数的详细信息,请参阅:: new。

代码语言:javascript
复制
# File lib/net/http.rb, line 1004
def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)
  return self unless p_addr

  Class.new(self) {
    @is_proxy_class = true

    if p_addr == :ENV then
      @proxy_from_env = true
      @proxy_address = nil
      @proxy_port    = nil
    else
      @proxy_from_env = false
      @proxy_address = p_addr
      @proxy_port    = p_port || default_port
    end

    @proxy_user = p_user
    @proxy_pass = p_pass
  }
end

default_port() Show source

用于HTTP请求的默认端口; 默认为80。

代码语言:javascript
复制
# File lib/net/http.rb, line 542
def HTTP.default_port
  http_default_port()
end

get(uri_or_host, path = nil, port = nil) Show source

向目标发送GET请求并以字符串形式返回HTTP响应。 目标可以指定为(uri),也可以指定为(host,path,port = 80); 所以:

代码语言:javascript
复制
print Net::HTTP.get(URI('http://www.example.com/index.html'))

或是:

代码语言:javascript
复制
print Net::HTTP.get('www.example.com', '/index.html')
代码语言:javascript
复制
# File lib/net/http.rb, line 460
def HTTP.get(uri_or_host, path = nil, port = nil)
  get_response(uri_or_host, path, port).body
end

get_print(uri_or_host, path = nil, port = nil) Show source

从目标获取正文文本并将其输出到$ stdout。 目标可以指定为(uri),也可以指定为(host,path,port = 80); 所以:

代码语言:javascript
复制
Net::HTTP.get_print URI('http://www.example.com/index.html')

或是:

代码语言:javascript
复制
Net::HTTP.get_print 'www.example.com', '/index.html'
代码语言:javascript
复制
# File lib/net/http.rb, line 441
def HTTP.get_print(uri_or_host, path = nil, port = nil)
  get_response(uri_or_host, path, port) {|res|
    res.read_body do |chunk|
      $stdout.print chunk
    end
  }
  nil
end

get_response(uri_or_host, path = nil, port = nil, &block) Show source

将GET请求发送到目标并将HTTP响应作为Net :: HTTPResponse对象返回。 目标可以指定为(uri),也可以指定为(host,path,port = 80); 所以:

代码语言:javascript
复制
res = Net::HTTP.get_response(URI('http://www.example.com/index.html'))
print res.body

或是:

代码语言:javascript
复制
res = Net::HTTP.get_response('www.example.com', '/index.html')
print res.body
代码语言:javascript
复制
# File lib/net/http.rb, line 476
def HTTP.get_response(uri_or_host, path = nil, port = nil, &block)
  if path
    host = uri_or_host
    new(host, port || HTTP.default_port).start {|http|
      return http.request_get(path, &block)
    }
  else
    uri = uri_or_host
    start(uri.hostname, uri.port,
          :use_ssl => uri.scheme == 'https') {|http|
      return http.request_get(uri, &block)
    }
  end
end

http_default_port() Show source

用于HTTP请求的默认端口; 默认为80。

代码语言:javascript
复制
# File lib/net/http.rb, line 547
def HTTP.http_default_port
  80
end

https_default_port() Show source

用于HTTPS请求的默认端口; 默认为443。

代码语言:javascript
复制
# File lib/net/http.rb, line 552
def HTTP.https_default_port
  443
end

is_version_1_2?()

别名为:version_1_2?

new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) Show source

无需打开TCP连接或HTTP会话即可创建新的Net :: HTTP对象。

地址应该是DNS主机名或IP地址,端口是服务器运行的端口。 如果没有给出端口,则使用HTTP或HTTPS的默认端口。

如果没有给出任何p_参数,则代理主机和端口将取自http_proxy环境变量(或其大写等效项)(如果存在)。 如果代理需要认证,您必须手动提供。 有关来自环境的代理检测的详细信息,请参阅URI :: Generic#find_proxy。 要禁用代理检测,请将p_addr设置为零。

如果要连接到自定义代理,请使用p_addr代理主机的DNS名称或IP地址,p_port用于访问代理的端口,如果需要授权才能使用代理,则使用p_user和p_pass来输入用户名和密码。

调用超类方法

代码语言:javascript
复制
# File lib/net/http.rb, line 633
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = 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
    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

还有别名:newobj

new(address, port = nil) Show source

为指定的服务器地址创建新的Net :: HTTP对象,无需打开TCP连接或初始化HTTP会话。本address应该是DNS主机名或IP地址。

代码语言:javascript
复制
# File lib/net/http.rb, line 657
def initialize(address, port = nil)
  @address = address
  @port    = (port || HTTP.default_port)
  @local_host = nil
  @local_port = nil
  @curr_http_version = HTTPVersion
  @keep_alive_timeout = 2
  @last_communicated = nil
  @close_on_empty_response = false
  @socket  = nil
  @started = false
  @open_timeout = 60
  @read_timeout = 60
  @continue_timeout = nil
  @debug_output = nil

  @proxy_from_env = false
  @proxy_uri      = nil
  @proxy_address  = nil
  @proxy_port     = nil
  @proxy_user     = nil
  @proxy_pass     = nil

  @use_ssl = false
  @ssl_context = nil
  @ssl_session = nil
  @sspi_enabled = false
  SSL_IVNAMES.each do |ivname|
    instance_variable_set ivname, nil
  end
end

newobj(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)

别名为:new

post(url, data, header = nil) Show source

将数据发布到指定的URI对象。

例:

代码语言:javascript
复制
require 'net/http'
require 'uri'

Net::HTTP.post URI('http://www.example.com/api/search'),
               { "q" => "ruby", "max" => "50" }.to_json,
               "Content-Type" => "application/json"
代码语言:javascript
复制
# File lib/net/http.rb, line 502
def HTTP.post(url, data, header = nil)
  start(url.hostname, url.port,
        :use_ssl => url.scheme == 'https' ) {|http|
    http.post(url.path, data, header)
  }
end

post_form(url, params) Show source

将HTML表单数据发布到指定的URI对象。表单数据必须作为从String到String的哈希映射来提供。例:

代码语言:javascript
复制
{ "cmd" => "search", "q" => "ruby", "max" => "50" }

此方法也会执行基本身份验证iff url.user。 但用于身份验证的用户信息已弃用(RFC3986)。 所以这个功能将被删除。

例:

代码语言:javascript
复制
require 'net/http'
require 'uri'

Net::HTTP.post_form URI('http://www.example.com/search.cgi'),
                    { "q" => "ruby", "max" => "50" }
代码语言:javascript
复制
# File lib/net/http.rb, line 527
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?() Show source

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

代码语言:javascript
复制
# File lib/net/http.rb, line 1027
def proxy_class?
  defined?(@is_proxy_class) ? @is_proxy_class : false
end

start(address, port, p_addr, p_port, p_user, p_pass, &block) Show source

start(address, port=nil, p_addr=nil, p_port=nil, p_user=nil, p_pass=nil, opt, &block)

创建一个新的Net :: HTTP对象,然后另外打开TCP连接和HTTP会话。

参数如下:

地址

主机名或服务器的IP地址

端口

服务器的端口

p_addr

代理地址

p_port

代理端口

p_user

代理用户

p_pass

通过代理

opt

可选散列

选择由其访问者设置以下值。键值是#ca_file,#ca_path,cert,#cert_store,ciphers,#close_on_empty_response,key,#open_timeout,#read_timeout,#ssl_timeout,#ssl_version,use_ssl,#verify_callback,#verify_depth和verify_mode。

如果将use_ssl设置为true,则可以使用https,并将#verify_mode的默认值设置为OpenSSL :: SSL :: VERIFY_PEER。

如果给出可选块,则新创建的Net :: HTTP对象将传递给它并在块完成时关闭。在这种情况下,此方法的返回值是块的返回值。如果未给出块,则此方法的返回值是新创建的Net :: HTTP对象本身,调用者负责在完成时使用finish()方法关闭它。

代码语言:javascript
复制
# File lib/net/http.rb, line 590
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
  port = https_default_port if !port && opt && opt[:use_ssl]
  http = new(address, port, p_addr, p_port, p_user, p_pass)

  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() Show source

打开net / http 1.2(Ruby 1.8)功能。在Ruby 1.8或更高版本中默认为ON。

代码语言:javascript
复制
# File lib/net/http.rb, line 407
def HTTP.version_1_2
  true
end

version_1_2?() Show source

如果net / http处于版本1.2模式,则返回true。默认为true。

代码语言:javascript
复制
# File lib/net/http.rb, line 413
def HTTP.version_1_2?
  true
end

另外别名为:is_version_1_2?

公共实例方法

active?()

别名为:started?

continue_timeout=(sec) Show source

#continue_timeout属性的setter。

代码语言:javascript
复制
# File lib/net/http.rb, line 749
def continue_timeout=(sec)
  @socket.continue_timeout = sec if @socket
  @continue_timeout = sec
end

copy(path, initheader = nil) Show source

作为HTTPResponse对象发送COPY请求到路径并获得响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1274
def copy(path, initheader = nil)
  request(Copy.new(path, initheader))
end

delete(path, initheader = {'Depth' => 'Infinity'}) Show source

作为HTTPResponse对象发送DELETE请求到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1262
def delete(path, initheader = {'Depth' => 'Infinity'})
  request(Delete.new(path, initheader))
end

finish() Show source

完成HTTP会话并关闭TCP连接。如果会话尚未启动,则引发IOError。

代码语言:javascript
复制
# File lib/net/http.rb, line 973
def finish
  raise IOError, 'HTTP session not yet started' unless started?
  do_finish
end

get(path, initheader = nil, dest = nil) { |body_segment| ... } Show source

从连接到主机的路径中检索数据,该数据可能是绝对路径字符串或URI以从中提取路径。

initheader必须是{'Accept'=>'/',...}的哈希,并且它默认为一个空的散列。 如果initheader没有“accept-encoding”键,那么使用“gzip; q = 1.0,deflate; q = 0.6,identity; q = 0.3”的值,这样就优先使用gzip压缩 压缩,优先使用压缩。 Ruby没有库来支持压缩(Lempel-Ziv)压缩,所以不支持。 其目的是在默认情况下减少带宽。 如果此例程设置了压缩,那么它也会执行解压缩,并移除标题以避免混淆。 否则它会在发现它时留下主体。

这个方法返回一个Net :: HTTPResponse对象。

如果使用块调用,则从套接字读取时,将实体主体的每个片段依次视为字符串。请注意,在这种情况下,返回的响应对象将包含(有意义的)正文。

dest争论已经过时。它仍然有效,但你不能使用它。

此方法从不引发异常。

代码语言:javascript
复制
response = http.get('/index.html')

# using block
File.open('result.txt', 'w') {|f|
  http.get('/~foo/') do |str|
    f.write str
  end
}
代码语言:javascript
复制
# File lib/net/http.rb, line 1162
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) Show source

获取连接主机上的路径头。 标头是一个哈希像{'接受'=>'/',...}。

这个方法返回一个Net :: HTTPResponse对象。

此方法从不引发异常。

代码语言:javascript
复制
response = nil
Net::HTTP.start('some.www.server', 80) {|http|
  response = http.head('/index.html')
}
p response['content-type']
代码语言:javascript
复制
# File lib/net/http.rb, line 1184
def head(path, initheader = nil)
  request(Head.new(path, initheader))
end

head2(path, initheader = nil, &block)

别名为:request_head

inspect() Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 689
def inspect
  "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
end

lock(path, body, initheader = nil) Show source

作为HTTPResponse对象向路径发送LOCK请求并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1238
def lock(path, body, initheader = nil)
  request(Lock.new(path, initheader), body)
end

mkcol(path, body = nil, initheader = nil) Show source

作为HTTPResponse对象发送MKCOL请求到路径并获得响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1280
def mkcol(path, body = nil, initheader = nil)
  request(Mkcol.new(path, initheader), body)
end

move(path, initheader = nil) Show source

作为HTTPResponse对象,将MOVE请求发送到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1268
def move(path, initheader = nil)
  request(Move.new(path, initheader))
end

options(path, initheader = nil) Show source

将OPTIONS请求发送到路径并获取响应,作为HTTPResponse对象。

代码语言:javascript
复制
# File lib/net/http.rb, line 1250
def options(path, initheader = nil)
  request(Options.new(path, initheader))
end

patch(path, data, initheader = nil, dest = nil) { |body_segment| ... } Show source

作为HTTPResponse对象发送PATCH请求到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1222
def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
  send_entity(path, data, initheader, dest, Patch, &block)
end

peer_cert() Show source

返回服务器提供的X.509证书。

代码语言:javascript
复制
# File lib/net/http.rb, line 855
def peer_cert
  if not use_ssl? or not @socket
    return nil
  end
  @socket.io.peer_cert
end

post(path, data, initheader = nil, dest = nil) { |body_segment| ... } Show source

发布数据(必须是字符串)到路径。 标头必须是{'Accept'=>'/',...}。

这个方法返回一个Net :: HTTPResponse对象。

如果使用块调用,则从套接字读取时,将实体主体的每个片段依次视为字符串。请注意,在这种情况下,返回的响应对象将包含(有意义的)正文。

dest已经过时。它仍然有效,但你不能使用它。

此方法从不引发异常。

代码语言:javascript
复制
response = http.post('/cgi-bin/search.rb', 'query=foo')

# using block
File.open('result.txt', 'w') {|f|
  http.post('/cgi-bin/search.rb', 'query=foo') do |str|
    f.write str
  end
}

您应该为POST设置Content-Type:标题字段。如果没有给出Content-Type:字段,则该方法默认使用“application / x-www-form-urlencoded”。

代码语言:javascript
复制
# File lib/net/http.rb, line 1216
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'}) Show source

作为HTTPResponse对象发送PROPFIND请求到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1256
def propfind(path, body = nil, initheader = {'Depth' => '0'})
  request(Propfind.new(path, initheader), body)
end

proppatch(path, body, initheader = nil) Show source

将PROPPATCH请求发送到路径并获取响应,作为HTTPResponse对象。

代码语言:javascript
复制
# File lib/net/http.rb, line 1232
def proppatch(path, body, initheader = nil)
  request(Proppatch.new(path, initheader), body)
end

proxy?() Show source

如果此连接的请求将被代理,则为true

代码语言:javascript
复制
# File lib/net/http.rb, line 1046
def proxy?
  !!(@proxy_from_env ? proxy_uri : @proxy_address)
end

proxy_address() Show source

代理服务器的地址(如果已配置)。

代码语言:javascript
复制
# File lib/net/http.rb, line 1065
def proxy_address
  if @proxy_from_env then
    proxy_uri&.hostname
  else
    @proxy_address
  end
end

另外别名为:proxyaddr

proxy_from_env?() Show source

如果此连接的代理是根据环境确定的,则为true

代码语言:javascript
复制
# File lib/net/http.rb, line 1051
def proxy_from_env?
  @proxy_from_env
end

proxy_pass() Show source

代理密码(如果已配置)

代码语言:javascript
复制
# File lib/net/http.rb, line 1088
def proxy_pass
  @proxy_pass
end

proxy_port() Show source

代理服务器的端口(如果已配置)。

代码语言:javascript
复制
# File lib/net/http.rb, line 1074
def proxy_port
  if @proxy_from_env then
    proxy_uri&.port
  else
    @proxy_port
  end
end

另外别名为:proxyport

proxy_user() Show source

代理用户名(如果已配置)

代码语言:javascript
复制
# File lib/net/http.rb, line 1083
def proxy_user
  @proxy_user
end

proxyaddr()

别名为:proxy_address

proxyport()

别名为:proxy_port

read_timeout=(sec) Show source

#read_timeout属性的setter。

代码语言:javascript
复制
# File lib/net/http.rb, line 738
def read_timeout=(sec)
  @socket.read_timeout = sec if @socket
  @read_timeout = sec
end

request(req, body = nil) { |response| ... } Show source

将HTTPRequest对象req发送到HTTP服务器。

如果req是包含数据的Net :: HTTP :: Post或Net :: HTTP :: Put请求,则还会发送数据。为Net :: HTTP :: Head或Net :: HTTP :: Get请求提供数据会导致ArgumentError。

返回一个HTTPResponse对象。

当用块调用时,将HTTPResponse对象传递给块。答复的主体将不会被阅读; 如果需要,块可以使用Net :: HTTPResponse#read_body处理它。

此方法从不引发Net :: *异常。

代码语言:javascript
复制
# File lib/net/http.rb, line 1404
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| ... } Show source

发送一个GET请求给path。以Net :: HTTPResponse对象的形式返回响应。

当用块调用时,将HTTPResponse对象传递给块。答复的主体将不会被阅读; 如果需要,块可以使用Net :: HTTPResponse#read_body处理它。

返回响应。

此方法从不引发Net :: *异常。

代码语言:javascript
复制
response = http.request_get('/index.html')
# The entity body is already read in this case.
p response['content-type']
puts response.body

# Using a block
http.request_get('/index.html') {|response|
  p response['content-type']
  response.read_body do |str|   # read body now
    print str
  end
}
代码语言:javascript
复制
# File lib/net/http.rb, line 1315
def request_get(path, initheader = nil, &block) # :yield: +response+
  request(Get.new(path, initheader), &block)
end

另外别名为:get2

request_head(path, initheader = nil, &block) Show source

将HEAD请求发送到pathNet :: HTTPResponse对象并将其作为Net :: HTTPResponse对象返回。

返回响应。

此方法从不引发Net :: *异常。

代码语言:javascript
复制
response = http.request_head('/index.html')
p response['content-type']
代码语言:javascript
复制
# File lib/net/http.rb, line 1329
def request_head(path, initheader = nil, &block)
  request(Head.new(path, initheader), &block)
end

还有别名:head2

request_post(path, data, initheader = nil) { |response| ... } Show source

发送POST请求到path

以Net :: HTTPResponse对象的形式返回响应。

当用块调用时,该块将传递一个HTTPResponse对象。该回应的主体将不会被阅读; 如果需要,块可以使用Net :: HTTPResponse#read_body处理它。

返回响应。

此方法从不引发Net :: *异常。

代码语言:javascript
复制
# example
response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
p response.status
puts response.body          # body is already read in this case

# using block
http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
  p response.status
  p response['content-type']
  response.read_body do |str|   # read body now
    print str
  end
}
代码语言:javascript
复制
# File lib/net/http.rb, line 1359
def request_post(path, data, initheader = nil, &block) # :yield: +response+
  request Post.new(path, initheader), data, &block
end

另外别名为:post2

send_request(name, path, data = nil, header = nil) Show source

向HTTP服务器发送HTTP请求。 如果给出数据,也发送一个DATA字符串。

返回一个Net :: HTTPResponse对象。

此方法从不引发Net :: *异常。

代码语言:javascript
复制
response = http.send_request('GET', '/index.html')
puts response.body
代码语言:javascript
复制
# File lib/net/http.rb, line 1383
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) Show source

警告

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

设置输出流以进行调试。

代码语言:javascript
复制
http = Net::HTTP.new(hostname)
http.set_debug_output $stderr
http.start { .... }
代码语言:javascript
复制
# File lib/net/http.rb, line 702
def set_debug_output(output)
  warn 'Net::HTTP#set_debug_output called after HTTP started' if started?
  @debug_output = output
end

start() { |http| ... } Show source

打开TCP连接和HTTP会话。

当使用块调用此方法时,它将Net :: HTTP对象传递给该块,并在该块执行后关闭TCP连接和HTTP会话。

当用块调用时,它返回块的返回值; 否则,它返回自我。

代码语言:javascript
复制
# File lib/net/http.rb, line 871
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?() Show source

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

代码语言:javascript
复制
# File lib/net/http.rb, line 761
def started?
  @started
end

还有别名:active?

trace(path, initheader = nil) Show source

作为HTTPResponse对象发送TRACE请求到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1286
def trace(path, initheader = nil)
  request(Trace.new(path, initheader))
end

unlock(path, body, initheader = nil) Show source

作为HTTPResponse对象发送UNLOCK请求到路径并获取响应。

代码语言:javascript
复制
# File lib/net/http.rb, line 1244
def unlock(path, body, initheader = nil)
  request(Unlock.new(path, initheader), body)
end

use_ssl=(flag) Show source

打开/关闭SSL。该标志必须在开始会话之前设置。如果在会话启动后更改use_ssl值,则Net :: HTTP对象会引发IOError。

代码语言:javascript
复制
# File lib/net/http.rb, line 778
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?() Show source

如果SSL / TLS正与HTTP一起使用,则返回true。

代码语言:javascript
复制
# File lib/net/http.rb, line 770
def use_ssl?
  @use_ssl
end

私有实例方法

D(msg) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1573
def D(msg)
  return unless @debug_output
  @debug_output << msg
  @debug_output << "\n"
end

addr_port() Show source

utils

代码语言:javascript
复制
# File lib/net/http.rb, line 1565
def addr_port
  if use_ssl?
    address() + (port == HTTP.https_default_port ? '' : ":#{port()}")
  else
    address() + (port == HTTP.http_default_port ? '' : ":#{port()}")
  end
end

begin_transport(req) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1482
def begin_transport(req)
  if @socket.closed?
    connect
  elsif @last_communicated
    if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
      D 'Conn close because of keep_alive_timeout'
      @socket.close
      connect
    elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
      D "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() Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 891
def connect
  if proxy? then
    conn_address = proxy_address
    conn_port    = proxy_port
  else
    conn_address = address
    conn_port    = port
  end

  D "opening connection to #{conn_address}:#{conn_port}..."
  s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
    begin
      TCPSocket.open(conn_address, conn_port, @local_host, @local_port)
    rescue => e
      raise e, "Failed to open TCP connection to " +
        "#{conn_address}:#{conn_port} (#{e.message})"
    end
  }
  s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
  D "opened"
  if use_ssl?
    if proxy?
      plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
                                  continue_timeout: @continue_timeout,
                                  debug_output: @debug_output)
      buf = "CONNECT #{@address}:#{@port} HTTP/#{HTTPVersion}\r\n"
      buf << "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) and
        value = instance_variable_get(ivname)
        ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
      end
    end
    @ssl_context = OpenSSL::SSL::SSLContext.new
    @ssl_context.set_params(ssl_parameters)
    D "starting SSL for #{conn_address}:#{conn_port}..."
    s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
    s.sync_close = true
    # Server Name Indication (SNI) RFC 3546
    s.hostname = @address if s.respond_to? :hostname=
    if @ssl_session and
       Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
      s.session = @ssl_session if @ssl_session
    end
    ssl_socket_connect(s, @open_timeout)
    if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
      s.post_connection_check(@address)
    end
    @ssl_session = s.session
    D "SSL established"
  end
  @socket = BufferedIO.new(s, read_timeout: @read_timeout,
                           continue_timeout: @continue_timeout,
                           debug_output: @debug_output)
  on_connect
rescue => exception
  if s
    D "Conn close because of connect error #{exception}"
    s.close
  end
  raise
end

do_finish() Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 978
def do_finish
  @started = false
  @socket.close if @socket
  @socket = nil
end

do_start() Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 885
def do_start
  connect
  @started = true
end

edit_path(path) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1107
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) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1505
def end_transport(req, res)
  @curr_http_version = res.http_version
  @last_communicated = nil
  if @socket.closed?
    D 'Conn socket closed'
  elsif not res.body and @close_on_empty_response
    D 'Conn close'
    @socket.close
  elsif keep_alive?(req, res)
    D 'Conn keep-alive'
    @last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  else
    D 'Conn close'
    @socket.close
  end
end

keep_alive?(req, res) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1522
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() Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 967
def on_connect
end

send_entity(path, data, initheader, dest, type, &block) Show source

执行使用表示并返回其正文的请求。

代码语言:javascript
复制
# File lib/net/http.rb, line 1427
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) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1546
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) Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1531
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| ... } Show source

代码语言:javascript
复制
# File lib/net/http.rb, line 1438
def transport_request(req)
  count = 0
  begin
    begin_transport req
    res = catch(:response) {
      req.exec @socket, @curr_http_version, edit_path(req.path)
      begin
        res = HTTPResponse.read_new(@socket)
        res.decode_content = req.decode_content
      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,
         # avoid a dependency on OpenSSL
         defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError,
         Timeout::Error => exception
    if count == 0 && IDEMPOTENT_METHODS_.include?(req.method)
      count += 1
      @socket.close if @socket
      D "Conn close because of error #{exception}, and retry"
      retry
    end
    D "Conn close because of error #{exception}"
    @socket.close if @socket
    raise
  end

  end_transport req, res
  res
rescue => exception
  D "Conn close because of error #{exception}"
  @socket.close if @socket
  raise exception
end

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com