spec/lib/http_log_spec.rb in httplog-1.1.1 vs spec/lib/http_log_spec.rb in httplog-1.2.0
- old
+ new
@@ -1,17 +1,60 @@
# frozen_string_literal: true
require 'spec_helper'
describe HttpLog do
- let(:host) { 'localhost' }
- let(:port) { 9292 }
- let(:path) { '/index.html' }
+ subject { log } # see spec_helper
+
+ let(:host) { 'localhost' }
+ let(:port) { 9292 }
+ let(:path) { '/index.html' }
let(:headers) { { 'accept' => '*/*', 'foo' => 'bar' } }
- let(:data) { 'foo=bar&bar=foo' }
- let(:params) { { 'foo' => 'bar:form-data', 'bar' => 'foo' } }
+ let(:data) { 'foo=bar&bar=foo' }
+ let(:params) { { 'foo' => 'bar:form-data', 'bar' => 'foo' } }
+ let(:html) { File.read('./spec/support/index.html') }
+ let(:json) { JSON.parse(log.match(/\[httplog\]\s(.*)/).captures.first) }
+ # Configuration
+ let(:enabled) { HttpLog.configuration.enabled }
+ let(:severity) { HttpLog.configuration.severity }
+ let(:log_headers) { HttpLog.configuration.log_headers }
+ let(:log_request) { HttpLog.configuration.log_request }
+ let(:log_response) { HttpLog.configuration.log_response }
+ let(:log_data) { HttpLog.configuration.log_data }
+ let(:log_connect) { HttpLog.configuration.log_connect }
+ let(:log_benchmark) { HttpLog.configuration.log_benchmark }
+ let(:color) { HttpLog.configuration.color }
+ let(:prefix) { HttpLog.configuration.prefix }
+ let(:prefix_response_lines) { HttpLog.configuration.prefix_response_lines }
+ let(:prefix_line_numbers) { HttpLog.configuration.prefix_line_numbers }
+ let(:json_log) { HttpLog.configuration.json_log }
+ let(:compact_log) { HttpLog.configuration.compact_log }
+ let(:url_blacklist_pattern) { HttpLog.configuration.url_blacklist_pattern }
+ let(:url_whitelist_pattern) { HttpLog.configuration.url_whitelist_pattern }
+
+ def configure
+ HttpLog.configure do |c|
+ c.enabled = enabled
+ c.severity = severity
+ c.log_headers = log_headers
+ c.log_request = log_request
+ c.log_response = log_response
+ c.log_data = log_data
+ c.log_connect = log_connect
+ c.log_benchmark = log_benchmark
+ c.color = color
+ c.prefix = prefix
+ c.prefix_response_lines = prefix_response_lines
+ c.prefix_line_numbers = prefix_line_numbers
+ c.json_log = json_log
+ c.compact_log = compact_log
+ c.url_blacklist_pattern = url_blacklist_pattern
+ c.url_whitelist_pattern = url_whitelist_pattern
+ end
+ end
+
ADAPTERS = [
NetHTTPAdapter,
OpenUriAdapter,
HTTPClientAdapter,
HTTPartyAdapter,
@@ -23,309 +66,245 @@
].freeze
ADAPTERS.each do |adapter_class|
context adapter_class, adapter: adapter_class.to_s do
let(:adapter) { adapter_class.new(host: host, port: port, path: path, headers: headers, data: data, params: params) }
+ before { configure }
context 'with default configuration' do
- connection_test_method = adapter_class.is_libcurl? ? :to_not : :to
+ describe 'GET requests' do
+ let!(:res) { adapter.send_get_request }
- if adapter_class.method_defined? :send_get_request
- it 'should log GET requests' do
- res = adapter.send_get_request
+ it_behaves_like 'logs request', 'GET'
+ it_behaves_like 'logs data'
+ it_behaves_like 'logs expected response'
+ it_behaves_like 'logs status', 200
+ it_behaves_like 'logs benchmark'
- expect(log).send(connection_test_method, include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}"))
+ it { is_expected.to_not include('Header:') }
+ it { is_expected.to_not include("\e[0") }
- expect(log).to include(HttpLog::LOG_PREFIX + "Sending: GET http://#{host}:#{port}#{path}")
- expect(log).to include(HttpLog::LOG_PREFIX + 'Data:')
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
- expect(log).to include(HttpLog::LOG_PREFIX + 'Status: 200')
- expect(log).to include(HttpLog::LOG_PREFIX + 'Benchmark: ')
- expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
-
- expect(log).to_not include("\e[0")
-
- expect(res).to be_a adapter.response if adapter.respond_to? :response
+ unless adapter_class.is_libcurl?
+ it { is_expected.to include("Connecting: #{host}:#{port}") }
end
+ it { expect(res).to be_a adapter.response if adapter.respond_to? :response }
+
context 'with gzip encoding' do
let(:path) { '/index.html.gz' }
let(:data) { nil }
- it 'decompresses gzipped response body' do
- adapter.send_get_request
- expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
- end
+ it_behaves_like 'logs expected response'
if adapter_class.method_defined? :send_head_request
it "doesn't try to decompress body for HEAD requests" do
- adapter.send_head_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
+ expect(log).to include('Response:')
end
end
end
context 'with UTF-8 response body' do
let(:path) { '/utf8.html' }
let(:data) { nil }
- it 'works' do
- adapter.send_get_request
- expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
- if adapter.logs_data?
- expect(log).to include(' <title>Блог Яндекса</title>')
- end
- end
+ it_behaves_like 'logs expected response'
+ it { is_expected.to include(' <title>Блог Яндекса</title>') if adapter.logs_data? }
end
context 'with binary response body' do
- let(:path) { '/test.bin' }
- let(:data) { nil }
+ %w[/test.bin /test.pdf].each do |response_file_name|
+ let(:path) { response_file_name }
+ let(:data) { nil }
- it "doesn't log response" do
- adapter.send_get_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response: (not showing binary data)')
+ it { is_expected.to include('Response: (not showing binary data)') }
+
+ context 'and JSON logging' do
+ let(:json_log) { true }
+ it { expect(json['response_body']).to eq '(not showing binary data)' }
+ end
end
end
end
- if adapter_class.method_defined? :send_post_request
- it 'logs POST requests' do
- res = adapter.send_post_request
+ describe 'POST requests' do
+ if adapter_class.method_defined? :send_post_request
+ let!(:res) { adapter.send_post_request }
- expect(log).send(connection_test_method, include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}"))
+ unless adapter_class.is_libcurl?
+ it { is_expected.to include("Connecting: #{host}:#{port}") }
+ end
- expect(log).to include(HttpLog::LOG_PREFIX + "Sending: POST http://#{host}:#{port}#{path}")
- expect(log).to include(HttpLog::LOG_PREFIX + 'Data: foo=bar&bar=foo')
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
- expect(log).to include(HttpLog::LOG_PREFIX + 'Status: 200')
- expect(log).to include(HttpLog::LOG_PREFIX + 'Benchmark: ')
- expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
+ it_behaves_like 'logs request', 'POST'
+ it_behaves_like 'logs expected response'
+ it_behaves_like 'logs data', 'foo=bar&bar=foo'
+ it_behaves_like 'logs status', 200
+ it_behaves_like 'logs benchmark'
- expect(res).to be_a adapter.response if adapter.respond_to? :response
- end
+ it { is_expected.to_not include('Header:') }
- context 'with non-UTF request data' do
- let(:data) { "a UTF-8 striñg with an 8BIT-ASCII character: \xC3" }
- it 'does not raise and error' do
- expect { adapter.send_post_request }.to_not raise_error
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
+ it { expect(res).to be_a adapter.response if adapter.respond_to? :response }
+
+ context 'with non-UTF request data' do
+ let(:data) { "a UTF-8 striñg with an 8BIT-ASCII character: \xC3" }
+ it_behaves_like 'logs expected response' # == doesn't throw exception
end
- end
- context 'with URI encoded non-UTF data' do
- let(:data) { 'a UTF-8 striñg with a URI encoded 8BIT-ASCII character: %c3' }
- it 'does not raise and error' do
- expect { adapter.send_post_request }.to_not raise_error
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
+ context 'with URI encoded non-UTF data' do
+ let(:data) { 'a UTF-8 striñg with a URI encoded 8BIT-ASCII character: %c3' }
+ it_behaves_like 'logs expected response' # == doesn't throw exception
end
end
end
end
context 'with custom configuration' do
context 'GET requests' do
- it 'should not log anything unless enabled is set' do
- HttpLog.configure { |c| c.enabled = false }
- adapter.send_get_request
- expect(log).to eq('')
- end
+ before { adapter.send_get_request }
- it 'should log at other levels' do
- HttpLog.configure { |c| c.severity = Logger::Severity::INFO }
- adapter.send_get_request
- expect(log).to include('INFO')
+ context 'when disabled' do
+ let(:enabled) { false }
+ it_behaves_like 'logs nothing'
end
- it 'should log headers if enabled' do
- HttpLog.configure { |c| c.log_headers = true }
- adapter.send_get_request
- # request header
- expect(log.downcase).to include(HttpLog::LOG_PREFIX + 'Header: accept: */*'.downcase)
- # response header
- expect(log.downcase).to include(HttpLog::LOG_PREFIX + 'Header: server: thin'.downcase)
+ context 'with different log level' do
+ let(:severity) { Logger::Severity::INFO }
+ it { is_expected.to include('INFO') }
end
- it 'should not log headers if disabled' do
- HttpLog.configure { |c| c.log_headers = false }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
+ context 'with headers logging' do
+ let(:log_headers) { true }
+ it { is_expected.to match(%r{Header: accept: */*}i) } # request
+ it { is_expected.to match(/Header: Server: thin/i) } # response
end
- it 'should log the request if url does not match blacklist pattern' do
- HttpLog.configure { |c| c.url_blacklist_pattern = /example.com/ }
- adapter.send_get_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Sending: GET')
+ context 'with blacklist hit' do
+ let(:url_blacklist_pattern) { /#{host}:#{port}/ }
+ it_behaves_like 'logs nothing'
end
- it 'should log the request if url matches whitelist pattern and not the blacklist pattern' do
- HttpLog.configure { |c| c.url_blacklist_pattern = /example.com/ }
- HttpLog.configure { |c| c.url_whitelist_pattern = /#{host}:#{port}/ }
- adapter.send_get_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Sending: GET')
+ context 'with blacklist miss' do
+ let(:url_blacklist_pattern) { /example.com/ }
+ it_behaves_like 'logs request', 'GET'
end
- it 'should not log the request if url matches blacklist pattern' do
- HttpLog.configure { |c| c.url_blacklist_pattern = /#{host}:#{port}/ }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
- end
+ context 'with whitelist hit' do
+ let(:url_whitelist_pattern) { /#{host}:#{port}/ }
+ it_behaves_like 'logs request', 'GET'
- it 'should not log the request if url does not match whitelist pattern' do
- HttpLog.configure { |c| c.url_whitelist_pattern = /example.com/ }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
+ context 'and blacklist hit' do
+ let(:url_blacklist_pattern) { /#{host}:#{port}/ }
+ it_behaves_like 'logs nothing'
+ end
end
- it 'should not log the request if url matches blacklist pattern and the whitelist pattern' do
- HttpLog.configure { |c| c.url_blacklist_pattern = /#{host}:#{port}/ }
- HttpLog.configure { |c| c.url_whitelist_pattern = /#{host}:#{port}/ }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
+ context 'with whitelist miss' do
+ let(:url_whitelist_pattern) { /example.com/ }
+ it_behaves_like 'logs nothing'
end
- it 'should not log the request if disabled' do
- HttpLog.configure { |c| c.log_request = false }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
- end
+ it_behaves_like 'with request logging disabled'
+ it_behaves_like 'with connection logging disabled'
+ it_behaves_like 'data logging disabled'
+ it_behaves_like 'response logging disabled'
+ it_behaves_like 'benchmark logging disabled'
- it 'should not log the connection if disabled' do
- HttpLog.configure { |c| c.log_connect = false }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}")
+ context 'with single color' do
+ let(:color) { :red }
+ it { is_expected.to include("\e[31m") }
end
- it 'should not log data if disabled' do
- HttpLog.configure { |c| c.log_data = false }
- adapter.send_get_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
+ context 'with color hash' do
+ let(:color) { { color: :black, background: :yellow } }
+ it { is_expected.to include("\e[30m\e[43m") }
end
- it 'should colorized output with single color' do
- HttpLog.configure { |c| c.color = :red }
- adapter.send_get_request
- expect(log).to include("\e[31m")
+ context 'with custom prefix' do
+ let(:prefix) { '[my logger]' }
+ it { is_expected.to include('[my logger]') }
+ it { is_expected.to_not include(HttpLog::LOG_PREFIX) }
end
- it 'should colorized output with color hash' do
- HttpLog.configure { |c| c.color = { color: :black, background: :yellow } }
- adapter.send_get_request
- expect(log).to include("\e[30m\e[43m")
+ context 'with custom lambda prefix' do
+ let(:prefix) { -> { '[custom prefix]' } }
+ it { is_expected.to include('[custom prefix]') }
+ it { is_expected.to_not include(HttpLog::LOG_PREFIX) }
end
- it 'should log with custom string prefix' do
- HttpLog.configure { |c| c.prefix = '[my logger]' }
- adapter.send_get_request
- expect(log).to include('[my logger]')
- expect(log).to_not include(HttpLog::LOG_PREFIX)
+ context 'with compact config' do
+ let(:compact_log) { true }
+ it { is_expected.to match(%r{\[httplog\] GET http://#{host}:#{port}#{path}(\?.*)? completed with status code \d{3} in (\d|\.)+}) }
+ it { is_expected.to_not include("Connecting: #{host}:#{port}") }
+ it { is_expected.to_not include('Response:') }
+ it { is_expected.to_not include('Data:') }
+ it { is_expected.to_not include('Benchmark: ') }
end
-
- it 'should log with custom lambda prefix' do
- HttpLog.configure { |c| c.prefix = -> { '[custom prefix]' } }
- adapter.send_get_request
- expect(log).to include('[custom prefix]')
- expect(log).to_not include(HttpLog::LOG_PREFIX)
- end
end
context 'POST requests' do
if adapter_class.method_defined? :send_post_request
- it 'should not log data if disabled' do
- HttpLog.configure { |c| c.log_data = false }
- adapter.send_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
- end
+ before { adapter.send_post_request }
- it 'should not log the response if disabled' do
- HttpLog.configure { |c| c.log_response = false }
- adapter.send_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
- end
-
- it 'should prefix all response lines' do
- HttpLog.configure { |c| c.prefix_response_lines = true }
-
- adapter.send_post_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
- expect(log).to include(HttpLog::LOG_PREFIX + '<html>')
- end
-
- it 'should prefix all response lines with line numbers' do
- HttpLog.configure { |c| c.prefix_response_lines = true }
- HttpLog.configure { |c| c.prefix_line_numbers = true }
-
- adapter.send_post_request
- expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
- expect(log).to include(HttpLog::LOG_PREFIX + '1: <html>')
- end
-
- it 'should not log the benchmark if disabled' do
- HttpLog.configure { |c| c.log_benchmark = false }
- adapter.send_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
- end
+ it_behaves_like 'data logging disabled'
+ it_behaves_like 'response logging disabled'
+ it_behaves_like 'benchmark logging disabled'
+ it_behaves_like 'with prefix response lines'
+ it_behaves_like 'with line numbers'
end
end
context 'POST form data requests' do
if adapter_class.method_defined? :send_post_form_request
- it 'should not log data if disabled' do
- HttpLog.configure { |c| c.log_data = false }
- adapter.send_post_form_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
- end
+ before { adapter.send_post_form_request }
- it 'should not log the response if disabled' do
- HttpLog.configure { |c| c.log_response = false }
- adapter.send_post_form_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
- end
-
- it 'should not log the benchmark if disabled' do
- HttpLog.configure { |c| c.log_benchmark = false }
- adapter.send_post_form_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
- end
+ it_behaves_like 'data logging disabled'
+ it_behaves_like 'response logging disabled'
+ it_behaves_like 'benchmark logging disabled'
+ it_behaves_like 'with prefix response lines'
+ it_behaves_like 'with line numbers'
end
end
context 'POST multi-part requests (file upload)' do
let(:upload) { Tempfile.new('http-log') }
let(:params) { { 'foo' => 'bar', 'file' => upload } }
if adapter_class.method_defined? :send_multipart_post_request
- it 'should not log data if disabled' do
- HttpLog.configure { |c| c.log_data = false }
- adapter.send_multipart_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
- end
+ before { adapter.send_multipart_post_request }
- it 'should not log the response if disabled' do
- HttpLog.configure { |c| c.log_response = false }
- adapter.send_multipart_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
- end
-
- it 'should not log the benchmark if disabled' do
- HttpLog.configure { |c| c.log_benchmark = false }
- adapter.send_multipart_post_request
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
- end
+ it_behaves_like 'data logging disabled'
+ it_behaves_like 'response logging disabled'
+ it_behaves_like 'benchmark logging disabled'
+ it_behaves_like 'with prefix response lines'
+ it_behaves_like 'with line numbers'
end
end
end
- context 'with compact config' do
- before(:each) { HttpLog.configure { |c| c.compact_log = true } }
+ context 'with JSON config' do
+ let(:json_log) { true }
- it 'should log a single line with status and benchmark' do
- adapter.send_get_request
- expect(log).to match(%r{\[httplog\] GET http://#{host}:#{port}#{path}(\?.*)? completed with status code \d{3} in (\d|\.)+})
- expect(log).to_not include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}")
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Response:')
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
- expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark: ')
+ if adapter_class.method_defined? :send_post_request
+ before { adapter.send_post_request }
+
+ it { expect(json['method']).to eq('POST') }
+ it { expect(json['request_body']).to eq(data) }
+ it { expect(json['request_headers']).to be_a(Hash) }
+ it { expect(json['response_headers']).to be_a(Hash) }
+ it { expect(json['response_code']).to eq(200) }
+ it { expect(json['response_body']).to eq(html) }
+ it { expect(json['benchmark']).to be_a(Numeric) }
+
+ context 'and compact config' do
+ let(:compact_log) { true }
+
+ it { expect(json['method']).to eq('POST') }
+ it { expect(json['request_body']).to be_nil }
+ it { expect(json['request_headers']).to be_nil }
+ it { expect(json['response_headers']).to be_nil }
+ it { expect(json['response_code']).to eq(200) }
+ it { expect(json['response_body']).to be_nil }
+ it { expect(json['benchmark']).to be_a(Numeric) }
+ end
end
end
end
end
end