2015-02-24 27 views
8

我需要記錄所有的請求,包括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方法。此外,我認爲應該有一個更簡單的方法或標準來做到這一點。最好不要使用寶石。

+0

標題註釋沒有鍵方法。 http://api.rubyonrails.org/classes/ActionDispatch/Http/Headers.html 有一個名爲'env'的實例變量,它是一個包含值的散列。所以你應該可以做'request.headers.env.keys'。要理解標題類的工作方式,請查看源代碼,它非常小:https://github.com/rails/rails/blob/e7b0947afdc8c9f4119d06628070667b9e7875d1/actionpack/lib/action_dispatch/http/headers.rb – Brennan 2015-02-24 03:44:06

回答

11

它看起來像request.headers返回一個散列,但事實上,它返回的Http::Headers的實例沒有定義keys方法。

但是Http::Headersenv作出響應,它返回原始的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 
+0

嗯,這是一半的解決方案。記錄身體如何? – 2015-02-24 03:59:44

+0

@jawanam:我用'around_action' – spickermann 2015-02-24 06:07:02

+0

超酷的例子更新了我的答案,謝謝! – 2017-03-16 10:54:07

1

我用它來獲取完整標題:

request.headers.env.select do |k, _| 
    k.downcase.start_with?('http') || 
    k.in?(ActionDispatch::Http::Headers::CGI_VARIABLES) 
end 
相關問題