類別 Net::HTTPGenericRequest

HTTPGenericRequest 是 Net::HTTPRequest 類別的父類別。

不要直接使用此類別;請改用 Net::HTTPRequest 的子類別。

關於範例

此處的範例假設已載入 net/http(也需要載入 uri

require 'net/http'

此處的許多程式碼範例使用下列範例網站

有些範例也假設下列變數

uri = URI('https://jsonplaceholder.typicode.com/')
uri.freeze # Examples may not modify.
hostname = uri.hostname # => "jsonplaceholder.typicode.com"
path = uri.path         # => "/"
port = uri.port         # => 443

因此範例要求可以寫成

Net::HTTP.get(uri)
Net::HTTP.get(hostname, '/index.html')
Net::HTTP.start(hostname) do |http|
  http.get('/todos/1')
  http.get('/todos/2')
end

需要修改的 URI 範例會先複製 uri,然後修改複製的內容

_uri = uri.dup
_uri.path = '/todos/1'

屬性

body[R]

傳回要求的字串主體,如果沒有則傳回 nil

req = Net::HTTP::Post.new(uri)
req.body # => nil
req.body = '{"title": "foo","body": "bar","userId": 1}'
req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}"
body_stream[R]

傳回要求的主體串流物件,如果沒有則傳回 nil

req = Net::HTTP::Post.new(uri)          # => #<Net::HTTP::Post POST>
req.body_stream                         # => nil
require 'stringio'
req.body_stream = StringIO.new('xyzzy') # => #<StringIO:0x0000027d1e5affa8>
req.body_stream                         # => #<StringIO:0x0000027d1e5affa8>
decode_content[R]

如果要求的標頭 'Accept-Encoding' 已手動設定或刪除(表示使用者打算在回應中處理編碼),則傳回 false,否則傳回 true

req = Net::HTTP::Get.new(uri) # => #<Net::HTTP::Get GET>
req['Accept-Encoding']        # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
req.decode_content            # => true
req['Accept-Encoding'] = 'foo'
req.decode_content            # => false
req.delete('Accept-Encoding')
req.decode_content            # => false
method[R]

傳回要求的字串方法名稱

Net::HTTP::Get.new(uri).method  # => "GET"
Net::HTTP::Post.new(uri).method # => "POST"
path[R]

傳回要求的字串路徑

Net::HTTP::Get.new(uri).path # => "/"
Net::HTTP::Post.new('example.com').path # => "example.com"
uri[R]

傳回要求的 URI 物件,如果沒有則傳回 nil

Net::HTTP::Get.new(uri).uri
# => #<URI::HTTPS https://jsonplaceholder.typicode.com/>
Net::HTTP::Get.new('example.com').uri # => nil

公開實例方法

body=(str) 按一下以切換來源

設定要求主體

req = Net::HTTP::Post.new(uri)
req.body # => nil
req.body = '{"title": "foo","body": "bar","userId": 1}'
req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}"
# File lib/net/http/generic_request.rb, line 154
def body=(str)
  @body = str
  @body_stream = nil
  @body_data = nil
  str
end
body_stream=(輸入) 按一下以切換來源

設定要求主體串流

req = Net::HTTP::Post.new(uri)          # => #<Net::HTTP::Post POST>
req.body_stream                         # => nil
require 'stringio'
req.body_stream = StringIO.new('xyzzy') # => #<StringIO:0x0000027d1e5affa8>
req.body_stream                         # => #<StringIO:0x0000027d1e5affa8>
# File lib/net/http/generic_request.rb, line 179
def body_stream=(input)
  @body = nil
  @body_stream = input
  @body_data = nil
  input
end
inspect() 按一下以切換來源

傳回要求的字串表示形式

Net::HTTP::Post.new(uri).inspect # => "#<Net::HTTP::Post POST>"
# File lib/net/http/generic_request.rb, line 101
def inspect
  "\#<#{self.class} #{@method}>"
end
request_body_permitted?() 按一下以切換來源

傳回要求是否可能具有主體

Net::HTTP::Post.new(uri).request_body_permitted? # => true
Net::HTTP::Get.new(uri).request_body_permitted?  # => false
# File lib/net/http/generic_request.rb, line 120
def request_body_permitted?
  @request_has_body
end
response_body_permitted?() 按一下以切換來源

傳回回應是否可能具有主體

Net::HTTP::Post.new(uri).response_body_permitted? # => true
Net::HTTP::Head.new(uri).response_body_permitted? # => false
# File lib/net/http/generic_request.rb, line 129
def response_body_permitted?
  @response_has_body
end

私人實例方法

encode_multipart_form_data(out, params, opt) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 312
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 368
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 363
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 260
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 286
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 269
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
    IO.copy_stream(f, sock)
  end
end
supply_default_content_type() 按一下以切換來源
# File lib/net/http/generic_request.rb, line 376
def supply_default_content_type
  return if content_type()
  warn 'net/http: Content-Type did not set; using application/x-www-form-urlencoded', uplevel: 1 if $VERBOSE
  set_content_type 'application/x-www-form-urlencoded'
end
wait_for_continue(sock, ver) 按一下以切換來源

等待來自伺服器的回應,最長等待持續時間,前提是我們使用 HTTP 1.1 並且預期 100-continue 回應。

# File lib/net/http/generic_request.rb, line 386
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) 按一下以切換來源
# File lib/net/http/generic_request.rb, line 399
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