Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log request bodies in logger middleware #277

Merged
merged 4 commits into from
Oct 5, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 26 additions & 1 deletion lib/faraday/response/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,56 @@ module Faraday
class Response::Logger < Response::Middleware
extend Forwardable

def initialize(app, logger = nil)
DEFAULT_OPTIONS = { :bodies => false }

def initialize(app, logger = nil, options = {})
super(app)
@logger = logger || begin
require 'logger'
::Logger.new(STDOUT)
end
@options = DEFAULT_OPTIONS.merge(options)
end

def_delegators :@logger, :debug, :info, :warn, :error, :fatal

def call(env)
info "#{env.method} #{env.url.to_s}"
debug('request') { dump_headers env.request_headers }
debug('request') { dump_body(env[:body]) } if env[:body] && log_body?(:request)
super
end

def on_complete(env)
info('Status') { env.status.to_s }
debug('response') { dump_headers env.response_headers }
debug('response') { dump_body env[:body] } if env[:body] && log_body?(:response)
end

private

def dump_headers(headers)
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
end

def dump_body(body)
if body.respond_to?(:to_str)
body.to_str
else
pretty_inspect(body)
end
end

def pretty_inspect(body)
require 'pp' unless body.respond_to?(:pretty_inspect)
body.pretty_inspect
end

def log_body?(type)
case @options[:bodies]
when Hash then @options[:bodies][type]
else @options[:bodies]
end
end
end
end
57 changes: 51 additions & 6 deletions test/adapters/logger_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@

module Adapters
class LoggerTest < Faraday::TestCase
def setup
@io = StringIO.new
@logger = Logger.new(@io)
@logger.level = Logger::DEBUG
def conn(logger, logger_options={})
rubbles = ['Barney', 'Betty', 'Bam Bam']

@conn = Faraday.new do |b|
b.response :logger, @logger
Faraday.new do |b|
b.response :logger, logger, logger_options
b.adapter :test do |stubs|
stubs.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'hello'] }
stubs.post('/ohai') { [200, {'Content-Type' => 'text/html'}, 'fred'] }
stubs.get('/ohno') { [200, {'Content-Type' => 'text/html'}, 'wilma'] }
stubs.post('/ohyes') { [200, {'Content-Type' => 'text/html'}, 'pebbles'] }
stubs.get('/rubbles') { [200, {'Content-Type' => 'application/json'}, rubbles] }
end
end
end

def setup
@io = StringIO.new
@logger = Logger.new(@io)
@logger.level = Logger::DEBUG

@conn = conn(@logger)
@resp = @conn.get '/hello', nil, :accept => 'text/html'
end

Expand All @@ -33,5 +43,40 @@ def test_logs_request_headers
def test_logs_response_headers
assert_match %(Content-Type: "text/html), @io.string
end

def test_does_not_log_request_body_by_default
@conn.post '/ohai', 'name=Unagi', :accept => 'text/html'
refute_match %(name=Unagi), @io.string
end

def test_does_not_log_response_body_by_default
@conn.post '/ohai', 'name=Toro', :accept => 'text/html'
refute_match %(fred), @io.string
end

def test_log_request_body
app = conn(@logger, :bodies => { :request => true })
app.post '/ohyes', 'name=Tamago', :accept => 'text/html'
assert_match %(name=Tamago), @io.string
end

def test_log_response_body
app = conn(@logger, :bodies => { :response => true })
app.get '/ohno', :accept => 'text/html'
assert_match %(wilma), @io.string
end

def test_log_request_and_response_body
app = conn(@logger, :bodies => true)
app.post '/ohyes', 'name=Ebi', :accept => 'text/html'
assert_match %(name=Ebi), @io.string
assert_match %(pebbles), @io.string
end

def test_log_response_body_object
app = conn(@logger, :bodies => true)
app.get '/rubbles', nil, :accept => 'text/html'
assert_match %([\"Barney\", \"Betty\", \"Bam Bam\"]\n), @io.string
end
end
end