【问题标题】:Getting Headers from a Ruby Net::HTTP Request before making the request在发出请求之前从 Ruby Net::HTTP 请求中获取标头
【发布时间】:2023-03-28 23:16:02
【问题描述】:

在 Ruby 中,我如何才能在 net/http(s) 或 open-uri 请求实际发出请求之前获取 HTTP 请求标头。

在某些情况下,在 URI 中创建签名字符串时会使用标头。当然,有一些方法可以获取将要发送的请求标头。例如,这些应包括“主机:”标头。

【问题讨论】:

    标签: ruby net-http open-uri


    【解决方案1】:

    这是我为提供帮助而编写的一些代码。

    def get_request_headers(request)
      http_method = request.method
      path = request.path
    
      request.to_hash.merge("method" => [http_method]).merge("path" => [path])
    end
    

    所以现在,你可以运行这样的东西了。

    url = URI("http://www.google.com")
    
    request, response = Net::HTTP.start(uri(ico).host) do |http|
      request = Net::HTTP::Get.new(uri(ico))
      response = http.request request
    
      [request, response]
    end
    
    get_request_headers(request)
    => {"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"], "accept"=>["*/*"], "user-agent"=>["Ruby"], "host"=>["www.google.com"], "method"=>["GET"], "path"=>["/"]}
    

    request.to_hash 免费为我们提供一些标头,但更多信息存储在请求和响应类的实例变量中。

    使用以下代码,您可以检查是否还有其他要合并到基本请求哈希中的内容。

    request.instance_variables.each do |variable|
      puts "#{variable}: #{request.instance_variable_get(variable)}"
    end
    
    => @method: GET
    => @request_has_body: false
    => @response_has_body: true
    => @uri: http://www.google.com
    => @path: /
    => @decode_content: true
    => @header: {"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"], "accept"=>["*/*"], "user-agent"=>["Ruby"], "host"=>["www.google.com"]}
    => @body: 
    => @body_stream: 
    => @body_data: 
    => [:@method, :@request_has_body, :@response_has_body, :@uri, :@path, :@decode_content, :@header, :@body, :@body_stream, :@body_data]
    

    请注意,我已经为 get_request_headers 方法提取了 method 和 path。

    最后,你可以对响应做同样的事情。

    def get_response_headers(response)
      code = response.code
      http_version = response.http_version
      message = response.message
    
      response.to_hash.merge("code" => [code]).merge("http_version" => [http_version]).merge("message" => [message])
    end
    
    get_response_headers(response)
    => {"date"=>["Thu, 06 May 2021 14:34:27 GMT"], "expires"=>["-1"], "cache-control"=>["private, max-age=0"], "content-type"=>["text/html; charset=ISO-8859-1"], "p3p"=>["CP=\"This is not a P3P policy! See g.co/p3phelp for more info.\""], "server"=>["gws"], "content-length"=>["6067"], "x-xss-protection"=>["0"], "x-frame-options"=>["SAMEORIGIN"], "set-cookie"=>["NID=215=dYowhmNSD9_CnKYLtsFI3uWVGy8ca8PKJTE8VY6_92q7tU5Y_AOWLsaabXxlSPBjc2QjOr4xXVX5SGMCrccTCnBR9pbdsKkrpVTV5TMqrV6H09ChxGjBr5mHVdZkgjOxswiXu72TF3eAX0uhXqloDb-5gmZ6NJ4w1YDKQKNoDp4; expires=Fri, 05-Nov-2021 14:34:27 GMT; path=/; domain=.google.com; HttpOnly"], "code"=>["200"], "http_version"=>["1.1"], "message"=>["OK"]}
    

    【讨论】:

      【解决方案2】:

      见http://ruby-doc.org/stdlib-2.0/libdoc/net/http/rdoc/Net/HTTP.html#label-Setting+Headers

      在 ruby​​ 2.0.0 中运行良好 - 但你是正确的,在 1.9.3 中的行为不同

      Ruby 2.0.0

      require 'net/http'
      uri = URI('http://github.com/ruby')
      
      http_request = Net::HTTP::Get.new(uri)
      http_request.each_header { |header| puts header }
      
      # => accept-encoding
      # => accept
      # => user-agent
      # => host    
      
      http_response = Net::HTTP.start(uri.hostname, uri.port) do |http|
        http.request(http_request)
      end
      

      Ruby 1.9.3

      require 'uri'
      require 'net/http'
      uri = URI.parse('http://github.com/ruby')
      
      http_request = Net::HTTP::Get.new(uri.path)
      http_request.each_header { |header| puts header }
      
      # => accept
      # => user-agent
      
      http_response = Net::HTTP.start(uri.hostname, uri.port) do |http|
        http.request(http_request)
      end
      
      http_request.each_header { |header| puts header }
      
      # => accept
      # => user-agent
      # => host
      

      【讨论】:

      • 有趣的作品在 ruby​​ 2.0.0 中效果很好 - 更新了答案,但可能没有帮助
      • 谢谢 :) 但不幸的是,正如你所推测的,我需要那个主机头预请求哈哈哈 :(
      【解决方案3】:

      Net::HTTP 类似乎都使用 Net::HTTPHeader 作为 mixin。您应该能够在请求对象上使用 to_hash() 一次获取所有标头,或使用 each_header() / each() 一次迭代一个标头。

      【讨论】:

      • 虽然以上内容应该可以获取明确设置的标头列表,但我不确定它是否会提前包含 Net::HTTP 在发送时可能添加的任何其他标头请求('Host' 是一个完美的例子......这个标头完全有可能只在最后一秒自动生成)。
      • 嗯.. 是的,这就是我所关心的。我已经找到了 each_header。我很高兴从 URI 字符串中假设“主机:”标头,但我担心可能会自动创建其他标头而我会错过。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      相关资源
      最近更新 更多