如何记录某个网址的整个请求(标题,正文等)?

时间:2015-02-24 03:30:16

标签: ruby-on-rails ruby ruby-on-rails-4 logging

我需要将所有请求(包括HTTP标头,正文等)记录到某个URL。我试过这段代码:

def index
  global_request_logging
end

private

def global_request_logging 
    http_request_header_keys = request.headers.keys.select{|header_name| header_name.match("^HTTP.*")}
    http_request_headers = request.headers.select{|header_name, header_value| http_request_header_keys.index(header_name)}
    logger.info "Received #{request.method.inspect} to #{request.url.inspect} from #{request.remote_ip.inspect}.  Processing with headers #{http_request_headers.inspect} and params #{params.inspect}"
    begin 
      yield 
    ensure 
      logger.info "Responding with #{response.status.inspect} => #{response.body.inspect}"
    end 
  end 

但它说request.headers不包含名为keys的方法。我还认为应该有一个更简单的方法或标准来做到这一点。优选地,不使用宝石。

2 个答案:

答案 0 :(得分:14)

看起来request.headers返回一个哈希值,但事实上,它返回的Http::Headers实例没有定义keys方法。

但是Http::Headers响应env,它返回原始的env哈希值。因此,这样的事情可能有用:

http_request_header_keys = request.headers.env.keys.select do |header_name| 
  header_name.match("^HTTP.*")
end

或者您可以迭代所有键值对并将它们复制到另一个哈希:

http_envs = {}.tap do |envs|
  request.headers.each do |key, value|
    envs[key] = value if key.downcase.starts_with?('http')
  end
end

logger.info <<-LOG.squish
  Received     #{request.method.inspect} 
  to           #{request.url.inspect} 
  from         #{request.remote_ip.inspect}.  
  Processing 
  with headers #{http_envs.inspect} 
  and params   #{params.inspect}"
LOG

总结一下:

around_action :log_everything, only: :index

def index
  # ...
end

private
def log_everything
  log_headers
  yield
ensure
  log_response
end

def log_headers
  http_envs = {}.tap do |envs|
    request.headers.each do |key, value|
      envs[key] = value if key.downcase.starts_with?('http')
    end
  end

  logger.info "Received #{request.method.inspect} to #{request.url.inspect} from #{request.remote_ip.inspect}. Processing with headers #{http_envs.inspect} and params #{params.inspect}"
end

def log_response
  logger.info "Responding with #{response.status.inspect} => #{response.body.inspect}"
end

答案 1 :(得分:1)

我正在使用它来获取完整的标题:

swagger: "2.0"
...

definitions:
  ApiResult:
    type: object
    properties:
      result:
        type: boolean
      token:
        type: string
      errorCode:
        type: string
      errorMsg:
        type: string
    required:
      - result