Ruby 2.4
Net::HTTP

Net::HTTP

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:

require 'net/http'

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

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

GET

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

GET by URI

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

使用动态参数进行GET

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

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

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

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

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

对于所有Net :: HTTP请求对象和快捷方式请求方法,您可以提供请求路径的字符串或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 :: HTTP类的实例。有关响应类的详细信息,请参见下面的“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')

POST

可以使用Net :: HTTP :: Post请求类进行POST。这个例子创建一个urlencoded 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

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

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节。

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

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

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_proxy环境变量创建一个代理。 要禁止使用http_proxy,请将代理地址传递给零。

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

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

- [Net::HTTP::Get](http/get)

- [Net::HTTP::Head](http/head)

- [Net::HTTP::Post](http/post)

- [Net::HTTP::Patch](http/patch)

- [Net::HTTP::Put](http/put)

- [Net::HTTP::Proppatch](http/proppatch)

- [Net::HTTP::Lock](http/lock)

- [Net::HTTP::Unlock](http/unlock)

- [Net::HTTP::Options](http/options)

- [Net::HTTP::Propfind](http/propfind)

- [Net::HTTP::Delete](http/delete)

- [Net::HTTP::Move](http/move)

- [Net::HTTP::Copy](http/copy)

- [Net::HTTP::Mkcol](http/mkcol)

- [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。

# 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。

# 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); 所以:

print Net::HTTP.get(URI('http://www.example.com/index.html'))

或是:

print Net::HTTP.get('www.example.com', '/index.html')

# 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); 所以:

Net::HTTP.get_print URI('http://www.example.com/index.html')

或是:

Net::HTTP.get_print 'www.example.com', '/index.html'

# 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); 所以:

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

或是:

res = Net::HTTP.get_response('www.example.com', '/index.html') print res.body

# 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。

# File lib/net/http.rb, line 547 def HTTP.http_default_port 80 end

https_default_port() Show source

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

# 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来输入用户名和密码。

调用超类方法

# 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地址。

# 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对象。

例:

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"

# 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的哈希映射来提供。例:

{ "cmd" => "search", "q" => "ruby", "max" => "50" }

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

例:

require 'net/http' require 'uri' Net::HTTP.post_form URI('http://www.example.com/search.cgi'), { "q" => "ruby", "max" => "50" }

# 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。

# 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。

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

# 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。

# 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。

# 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。

# 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请求到路径并获得响应。

# 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请求到路径并获取响应。

# 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。

# 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争论已经过时。它仍然有效,但你不能使用它。

此方法从不引发异常。

response = http.get('/index.html') # using block File.open('result.txt', 'w') {|f| http.get('/~foo/') do |str| f.write str end }

# 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对象。

此方法从不引发异常。

response = nil Net::HTTP.start('some.www.server', 80) {|http| response = http.head('/index.html') } p response['content-type']

# 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

# 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请求并获取响应。

# 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请求到路径并获得响应。

# 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请求发送到路径并获取响应。

# 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对象。

# 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请求到路径并获取响应。

# 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证书。

# 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已经过时。它仍然有效,但你不能使用它。

此方法从不引发异常。

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”。

# 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请求到路径并获取响应。

# 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对象。

# File lib/net/http.rb, line 1232 def proppatch(path, body, initheader = nil) request(Proppatch.new(path, initheader), body) end

proxy?() Show source

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

# File lib/net/http.rb, line 1046 def proxy? !!(@proxy_from_env ? proxy_uri : @proxy_address) end

proxy_address() Show source

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

# 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

# File lib/net/http.rb, line 1051 def proxy_from_env? @proxy_from_env end

proxy_pass() Show source

代理密码(如果已配置)

# File lib/net/http.rb, line 1088 def proxy_pass @proxy_pass end

proxy_port() Show source

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

# 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

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

# 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。

# 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 :: *异常。

# 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 :: *异常。

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 }

# 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 :: *异常。

response = http.request_head('/index.html') p response['content-type']

# 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 :: *异常。

# 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 }

# 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 :: *异常。

response = http.send_request('GET', '/index.html') puts response.body

# 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

警告

设置输出流以进行调试。

http = Net::HTTP.new(hostname) http.set_debug_output $stderr http.start { .... }

# 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会话。

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

# 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。

# File lib/net/http.rb, line 761 def started? @started end

还有别名:active?

trace(path, initheader = nil) Show source

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

# 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请求到路径并获取响应。

# 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。

# 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。

# File lib/net/http.rb, line 770 def use_ssl? @use_ssl end

私有实例方法

D(msg) Show source

# 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

# 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

# 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

# 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

# File lib/net/http.rb, line 978 def do_finish @started = false @socket.close if @socket @socket = nil end

do_start() Show source

# File lib/net/http.rb, line 885 def do_start connect @started = true end

edit_path(path) Show source

# 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

# 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

# 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

# File lib/net/http.rb, line 967 def on_connect end

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

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

# 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

# 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

# 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

# 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