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