How to log an entire request (headers, body, etc) for a certain url?
12,840
Solution 1
It looks like request.headers
returns a hash, but in fact, it returns an instance of Http::Headers
that doesn't have a keys
method defined.
But a Http::Headers
responds to env
which returns the original env hash. Therefore the following works:
http_request_header_keys = request.headers.env.keys.select do |header_name|
header_name.match("^HTTP.*")
end
Or you can just iterate over all key-value-pairs and copy them into another hash:
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
To wrap this up:
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
Solution 2
I'm using this to get the full headers:
request.headers.env.select do |k, _|
k.downcase.start_with?('http') ||
k.in?(ActionDispatch::Http::Headers::CGI_VARIABLES)
end
Related videos on Youtube
Author by
Admin
Updated on September 28, 2022Comments
-
Admin over 1 year
I need to log all the requests including HTTP headers, bodies, etc to a certain url. I've tried this code:
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
But it said
request.headers
doesn't contain a method namedkeys
. Also I figure there should be an easier way or standard to do it. Preferably, not to use a gem. -
Admin about 9 yearsWell, that's a half of the solution. How about logging the body?
-
spickermann about 9 years@jawanam : I updated my answer with an example of an
around_action