Ruby 2.4
Net::HTTP

Net::HTTPGenericRequest

class Net::HTTPGenericRequest

Parent:ObjectIncluded modules:Net::HTTPHeader

HTTPGenericRequest 是 HTTPRequest 类的父代。不要直接使用它; 使用 HTTPRequest 的子类。

在 HTTPHeader 模块中混合以提供对 HTTP 标题的更容易的访问。

属性

bodyR

body_streamR

decode_contentR

如果用户设置Accept-Encoding标头,则自动设置为false。这表明他们希望自己处理内容编码。

methodR

pathR

uriR

公共类方法

new(m, reqbody, resbody, uri_or_path, initheader = nil) Show source

# File lib/net/http/generic_request.rb, line 10 def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) @method = m @request_has_body = reqbody @response_has_body = resbody if URI === uri_or_path then @uri = uri_or_path.dup host = @uri.hostname.dup host << ":".freeze << @uri.port.to_s if @uri.port != @uri.default_port @path = uri_or_path.request_uri raise ArgumentError, "no HTTP request path given" unless @path else @uri = nil host = nil raise ArgumentError, "no HTTP request path given" unless uri_or_path raise ArgumentError, "HTTP request path is empty" if uri_or_path.empty? @path = uri_or_path.dup end @decode_content = false if @response_has_body and Net::HTTP::HAVE_ZLIB then if !initheader || !initheader.keys.any? { |k| %w[accept-encoding range].include? k.downcase } then @decode_content = true initheader = initheader ? initheader.dup : {} initheader["accept-encoding"] = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" end end initialize_http_header initheader self['Accept'] ||= '*/*' self['User-Agent'] ||= 'Ruby' self['Host'] ||= host if host @body = nil @body_stream = nil @body_data = nil end

公共实例方法

body=(str) Show source

# File lib/net/http/generic_request.rb, line 90 def body=(str) @body = str @body_stream = nil @body_data = nil str end

body_exist?() Show source

# File lib/net/http/generic_request.rb, line 83 def body_exist? warn "Net::HTTPRequest#body_exist? is obsolete; use response_body_permitted?" if $VERBOSE response_body_permitted? end

body_stream=(input) Show source

# File lib/net/http/generic_request.rb, line 99 def body_stream=(input) @body = nil @body_stream = input @body_data = nil input end

inspect() Show source

# File lib/net/http/generic_request.rb, line 61 def inspect "\#<#{self.class} #{@method}>" end

request_body_permitted?() Show source

# File lib/net/http/generic_request.rb, line 75 def request_body_permitted? @request_has_body end

response_body_permitted?() Show source

# File lib/net/http/generic_request.rb, line 79 def response_body_permitted? @response_has_body end

私有实例方法

encode_multipart_form_data(out, params, opt) Show source

# File lib/net/http/generic_request.rb, line 235 def encode_multipart_form_data(out, params, opt) charset = opt[:charset] boundary = opt[:boundary] require 'securerandom' unless defined?(SecureRandom) boundary ||= SecureRandom.urlsafe_base64(40) chunked_p = chunked? buf = '' params.each do |key, value, h={}| key = quote_string(key, charset) filename = h.key?(:filename) ? h[:filename] : value.respond_to?(:to_path) ? File.basename(value.to_path) : nil buf << "--#{boundary}\r\n" if filename filename = quote_string(filename, charset) type = h[:content_type] || 'application/octet-stream' buf << "Content-Disposition: form-data; " "name=\"#{key}\"; filename=\"#{filename}\"\r\n" "Content-Type: #{type}\r\n\r\n" if !out.respond_to?(:write) || !value.respond_to?(:read) # if +out+ is not an IO or +value+ is not an IO buf << (value.respond_to?(:read) ? value.read : value) elsif value.respond_to?(:size) && chunked_p # if +out+ is an IO and +value+ is a File, use IO.copy_stream flush_buffer(out, buf, chunked_p) out << "%x\r\n" % value.size if chunked_p IO.copy_stream(value, out) out << "\r\n" if chunked_p else # +out+ is an IO, and +value+ is not a File but an IO flush_buffer(out, buf, chunked_p) 1 while flush_buffer(out, value.read(4096), chunked_p) end else # non-file field: # HTML5 says, "The parts of the generated multipart/form-data # resource that correspond to non-file fields must not have a # Content-Type header specified." buf << "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n" buf << (value.respond_to?(:read) ? value.read : value) end buf << "\r\n" end buf << "--#{boundary}--\r\n" flush_buffer(out, buf, chunked_p) out << "0\r\n\r\n" if chunked_p end

flush_buffer(out, buf, chunked_p) Show source

# File lib/net/http/generic_request.rb, line 291 def flush_buffer(out, buf, chunked_p) return unless buf out << "%x\r\n"%buf.bytesize if chunked_p out << buf out << "\r\n" if chunked_p buf.clear end

quote_string(str, charset) Show source

# File lib/net/http/generic_request.rb, line 286 def quote_string(str, charset) str = str.encode(charset, fallback:->(c){'&#%d;'%c.encode("UTF-8").ord}) if charset str.gsub(/[\"]/, '\\\&') end

send_request_with_body(sock, ver, path, body) Show source

# File lib/net/http/generic_request.rb, line 181 def send_request_with_body(sock, ver, path, body) self.content_length = body.bytesize delete 'Transfer-Encoding' supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout sock.write body end

send_request_with_body_data(sock, ver, path, params) Show source

# File lib/net/http/generic_request.rb, line 209 def send_request_with_body_data(sock, ver, path, params) if /\Amultipart\/form-data\z/i !~ self.content_type self.content_type = 'application/x-www-form-urlencoded' return send_request_with_body(sock, ver, path, URI.encode_www_form(params)) end opt = @form_option.dup require 'securerandom' unless defined?(SecureRandom) opt[:boundary] ||= SecureRandom.urlsafe_base64(40) self.set_content_type(self.content_type, boundary: opt[:boundary]) if chunked? write_header sock, ver, path encode_multipart_form_data(sock, params, opt) else require 'tempfile' file = Tempfile.new('multipart') file.binmode encode_multipart_form_data(file, params, opt) file.rewind self.content_length = file.size write_header sock, ver, path IO.copy_stream(file, sock) file.close(true) end end

send_request_with_body_stream(sock, ver, path, f) Show source

# File lib/net/http/generic_request.rb, line 190 def send_request_with_body_stream(sock, ver, path, f) unless content_length() or chunked? raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'" end supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout if chunked? chunker = Chunker.new(sock) IO.copy_stream(f, chunker) chunker.finish else # copy_stream can sendfile() to sock.io unless we use SSL. # If sock.io is an SSLSocket, copy_stream will hit SSL_write() IO.copy_stream(f, sock.io) end end

supply_default_content_type() Show source

# File lib/net/http/generic_request.rb, line 299 def supply_default_content_type return if content_type() warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE set_content_type 'application/x-www-form-urlencoded' end

wait_for_continue(sock, ver) Show source

如果我们使用HTTP 1.1并期待100次继续响应,则等待服务器响应的延迟超时。

# File lib/net/http/generic_request.rb, line 309 def wait_for_continue(sock, ver) if ver >= '1.1' and @header['expect'] and @header['expect'].include?('100-continue') if sock.io.to_io.wait_readable(sock.continue_timeout) res = Net::HTTPResponse.read_new(sock) unless res.kind_of?(Net::HTTPContinue) res.decode_content = @decode_content throw :response, res end end end end

write_header(sock, ver, path) Show source

# File lib/net/http/generic_request.rb, line 322 def write_header(sock, ver, path) reqline = "#{@method} #{path} HTTP/#{ver}" if /[\r\n]/ =~ reqline raise ArgumentError, "A Request-Line must not contain CR or LF" end buf = "" buf << reqline << "\r\n" each_capitalized do |k,v| buf << "#{k}: #{v}\r\n" end buf << "\r\n" sock.write buf end