mirror of
https://github.com/rest-client/rest-client.git
synced 2022-11-09 13:49:40 -05:00
First try(cherry picked from commit eece9eda0487969e582ef97e6a41f86780a53d08)
This commit is contained in:
parent
5cee63c615
commit
16a4dbf9dd
4 changed files with 129 additions and 92 deletions
|
@ -88,16 +88,14 @@ module RestClient
|
|||
attr_accessor :proxy
|
||||
end
|
||||
|
||||
# Print log of RestClient calls. Value can be stdout, stderr, or a filename.
|
||||
# Setup the log for RestClient calls.
|
||||
# Value should be a logger but can can be stdout, stderr, or a filename.
|
||||
# You can also configure logging by the environment variable RESTCLIENT_LOG.
|
||||
def self.log=(log)
|
||||
@@log = log
|
||||
end
|
||||
|
||||
def self.log # :nodoc:
|
||||
return ENV['RESTCLIENT_LOG'] if ENV['RESTCLIENT_LOG']
|
||||
return @@log if defined? @@log
|
||||
nil
|
||||
def self.log= log
|
||||
if log.is_a? String
|
||||
warn "[warning] You should set the log with a logger"
|
||||
end
|
||||
@@log = create_log log
|
||||
end
|
||||
|
||||
def self.version
|
||||
|
@ -105,4 +103,49 @@ module RestClient
|
|||
return File.read(version_path).chomp if File.file?(version_path)
|
||||
"0.0.0"
|
||||
end
|
||||
|
||||
# Create a log that respond to << like a logger
|
||||
# param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
|
||||
def self.create_log param
|
||||
if param
|
||||
if param.is_a? String
|
||||
if param == 'stdout'
|
||||
stdout_logger = Class.new do
|
||||
def << obj
|
||||
STDOUT.puts obj
|
||||
end
|
||||
end
|
||||
stdout_logger.new
|
||||
elsif param == 'stderr'
|
||||
stderr_logger = Class.new do
|
||||
def << obj
|
||||
STDERR.puts obj
|
||||
end
|
||||
end
|
||||
stderr_logger.new
|
||||
else
|
||||
file_logger = Class.new do
|
||||
attr_writer :target_file
|
||||
def << obj
|
||||
File.open(@target_file, 'a') { |f| f.puts obj }
|
||||
end
|
||||
end
|
||||
logger = file_logger.new
|
||||
logger.target_file = param
|
||||
logger
|
||||
end
|
||||
else
|
||||
param
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@env_log = create_log ENV['RESTCLIENT_LOG']
|
||||
|
||||
@@log = nil
|
||||
|
||||
def self.log # :nodoc:
|
||||
@@env_log || @@log
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -73,13 +73,13 @@ module RestClient
|
|||
target_value = value.to_s
|
||||
final[target_key] = MIME::Types.type_for_extension target_value
|
||||
elsif 'ACCEPT' == target_key.upcase
|
||||
# Accept can be composed of several comma-separated values
|
||||
if value.is_a? Array
|
||||
target_values = value
|
||||
else
|
||||
target_values = value.to_s.split ','
|
||||
end
|
||||
final[target_key] = target_values.map{ |ext| MIME::Types.type_for_extension(ext.to_s.strip)}.join(', ')
|
||||
# Accept can be composed of several comma-separated values
|
||||
if value.is_a? Array
|
||||
target_values = value
|
||||
else
|
||||
target_values = value.to_s.split ','
|
||||
end
|
||||
final[target_key] = target_values.map{ |ext| MIME::Types.type_for_extension(ext.to_s.strip)}.join(', ')
|
||||
else
|
||||
final[target_key] = value.to_s
|
||||
end
|
||||
|
@ -148,12 +148,12 @@ module RestClient
|
|||
net.read_timeout = @timeout if @timeout
|
||||
net.open_timeout = @open_timeout if @open_timeout
|
||||
|
||||
display_log request_log
|
||||
log_request
|
||||
|
||||
net.start do |http|
|
||||
res = http.request(req, payload) { |http_response| fetch_body(http_response) }
|
||||
result = process_result(res)
|
||||
display_log response_log(res)
|
||||
log_response res
|
||||
|
||||
if result.kind_of?(String) or @method == :head
|
||||
Response.new(result, res)
|
||||
|
@ -183,12 +183,14 @@ module RestClient
|
|||
http_response.read_body do |chunk|
|
||||
@tf.write(chunk)
|
||||
size += chunk.size
|
||||
if size == 0
|
||||
display_log("#{@method} #{@url} done (0 length file)")
|
||||
elsif total == 0
|
||||
display_log("#{@method} #{@url} (zero content length)")
|
||||
else
|
||||
display_log("#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total])
|
||||
if RestClient.log
|
||||
if size == 0
|
||||
RestClient.log << "#{@method} #{@url} done (0 length file)"
|
||||
elsif total == 0
|
||||
RestClient.log << "#{@method} #{@url} (zero content length)"
|
||||
else
|
||||
RestClient.log << "#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total]
|
||||
end
|
||||
end
|
||||
end
|
||||
@tf.close
|
||||
|
@ -236,30 +238,20 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
def request_log
|
||||
def log_request
|
||||
if RestClient.log
|
||||
out = []
|
||||
out << "RestClient.#{method} #{url.inspect}"
|
||||
out << "headers: #{processed_headers.inspect}"
|
||||
out << "payload: #{payload.short_inspect}" if payload
|
||||
out.join(', ')
|
||||
out << payload.short_inspect if payload
|
||||
out << processed_headers.inspect.gsub(/^\{/, '').gsub(/\}$/, '')
|
||||
RestClient.log << out.join(', ')
|
||||
end
|
||||
end
|
||||
|
||||
def response_log(res)
|
||||
size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
|
||||
"# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
|
||||
end
|
||||
|
||||
def display_log(msg)
|
||||
return unless log_to = RestClient.log
|
||||
|
||||
if log_to == 'stdout'
|
||||
STDOUT.puts msg
|
||||
elsif log_to == 'stderr'
|
||||
STDERR.puts msg
|
||||
else
|
||||
File.open(log_to, 'a') { |f| f.puts msg }
|
||||
def log_response res
|
||||
if RestClient.log
|
||||
size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
|
||||
RestClient.log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -274,7 +266,7 @@ module MIME
|
|||
|
||||
# Return the first found content-type for a value considered as an extension or the value itself
|
||||
def type_for_extension ext
|
||||
candidates = @extension_index[ext]
|
||||
candidates = @extension_index[ext]
|
||||
candidates.empty? ? ext : candidates[0].content_type
|
||||
end
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ describe RestClient::Request do
|
|||
@net.stub!(:start).and_yield(@http)
|
||||
@net.stub!(:use_ssl=)
|
||||
@net.stub!(:verify_mode=)
|
||||
RestClient.log = 'test.log'
|
||||
RestClient.log = nil
|
||||
end
|
||||
|
||||
it "accept */* mimetype, preferring xml" do
|
||||
|
@ -150,7 +150,7 @@ describe RestClient::Request do
|
|||
it "transmits the request with Net::HTTP" do
|
||||
@http.should_receive(:request).with('req', 'payload')
|
||||
@request.should_receive(:process_result)
|
||||
@request.should_receive(:response_log)
|
||||
@request.should_receive(:log_response)
|
||||
@request.transmit(@uri, 'req', 'payload')
|
||||
end
|
||||
|
||||
|
@ -289,71 +289,63 @@ describe RestClient::Request do
|
|||
end
|
||||
|
||||
it "logs a get request" do
|
||||
['RestClient.get "http://url", headers: {"Accept-encoding"=>"gzip, deflate", "Accept"=>"*/*; q=0.5, application/xml"}',
|
||||
'RestClient.get "http://url", headers: {"Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate}'].should include
|
||||
RestClient::Request.new(:method => :get, :url => 'http://url').request_log
|
||||
log = RestClient.log = []
|
||||
RestClient::Request.new(:method => :get, :url => 'http://url').log_request
|
||||
['RestClient.get "http://url", "Accept-encoding"=>"gzip, deflate", "Accept"=>"*/*; q=0.5, application/xml"',
|
||||
'RestClient.get "http://url", "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate"'].should include(log[0])
|
||||
end
|
||||
|
||||
it "logs a post request with a small payload" do
|
||||
['RestClient.post "http://url", headers: {"Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3", "Accept"=>"*/*; q=0.5, application/xml"}, paylod: "foo"',
|
||||
'RestClient.post "http://url", headers: {"Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3"}, paylod: "foo"'].should include
|
||||
RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo').request_log
|
||||
log = RestClient.log = []
|
||||
RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo').log_request
|
||||
['RestClient.post "http://url", "foo", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3", "Accept"=>"*/*; q=0.5, application/xml"',
|
||||
'RestClient.post "http://url", "foo", "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3"'].should include(log[0])
|
||||
end
|
||||
|
||||
it "logs a post request with a large payload" do
|
||||
['RestClient.post "http://url", headers: {"Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000", "Accept"=>"*/*; q=0.5, application/xml"}, paylod: 1000 byte length',
|
||||
'RestClient.post "http://url", headers: {"Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000"}, paylod: 1000 byte length'].should include
|
||||
RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).request_log
|
||||
log = RestClient.log = []
|
||||
RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).log_request
|
||||
['RestClient.post "http://url", 1000 byte length, "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000", "Accept"=>"*/*; q=0.5, application/xml"',
|
||||
'RestClient.post "http://url", 1000 byte length, "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000"'].should include(log[0])
|
||||
end
|
||||
|
||||
it "logs input headers as a hash" do
|
||||
['RestClient.get "http://url", headers: {"Accept-encoding"=>"gzip, deflate", "Accept"=>"text/plain"}',
|
||||
'RestClient.get "http://url", headers: {"Accept"=>"text/plain", "Accept-encoding"=>"gzip, deflate"}'].should include
|
||||
RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain' })
|
||||
log = RestClient.log = []
|
||||
RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain' }).log_request
|
||||
['RestClient.get "http://url", "Accept-encoding"=>"gzip, deflate", "Accept"=>"text/plain"',
|
||||
'RestClient.get "http://url", "Accept"=>"text/plain", "Accept-encoding"=>"gzip, deflate"'].should include(log[0])
|
||||
end
|
||||
|
||||
it "logs a response including the status code, content type, and result body size in bytes" do
|
||||
log = RestClient.log = []
|
||||
res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
|
||||
res.stub!(:[]).with('Content-type').and_return('text/html')
|
||||
@request.response_log(res).should == "# => 200 OK | text/html 4 bytes"
|
||||
@request.log_response res
|
||||
log[0].should == "# => 200 OK | text/html 4 bytes"
|
||||
end
|
||||
|
||||
it "logs a response with a nil Content-type" do
|
||||
log = RestClient.log = []
|
||||
res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
|
||||
res.stub!(:[]).with('Content-type').and_return(nil)
|
||||
@request.response_log(res).should == "# => 200 OK | 4 bytes"
|
||||
@request.log_response res
|
||||
log[0].should == "# => 200 OK | 4 bytes"
|
||||
end
|
||||
|
||||
it "logs a response with a nil body" do
|
||||
log = RestClient.log = []
|
||||
res = mock('result', :code => '200', :class => Net::HTTPOK, :body => nil)
|
||||
res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
|
||||
@request.response_log(res).should == "# => 200 OK | text/html 0 bytes"
|
||||
@request.log_response res
|
||||
log[0].should == "# => 200 OK | text/html 0 bytes"
|
||||
end
|
||||
|
||||
it "strips the charset from the response content type" do
|
||||
log = RestClient.log = []
|
||||
res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
|
||||
res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
|
||||
@request.response_log(res).should == "# => 200 OK | text/html 4 bytes"
|
||||
end
|
||||
|
||||
it "displays the log to stdout" do
|
||||
RestClient.stub!(:log).and_return('stdout')
|
||||
STDOUT.should_receive(:puts).with('xyz')
|
||||
@request.display_log('xyz')
|
||||
end
|
||||
|
||||
it "displays the log to stderr" do
|
||||
RestClient.stub!(:log).and_return('stderr')
|
||||
STDERR.should_receive(:puts).with('xyz')
|
||||
@request.display_log('xyz')
|
||||
end
|
||||
|
||||
it "append the log to the requested filename" do
|
||||
RestClient.stub!(:log).and_return('/tmp/restclient.log')
|
||||
f = mock('file handle')
|
||||
File.should_receive(:open).with('/tmp/restclient.log', 'a').and_yield(f)
|
||||
f.should_receive(:puts).with('xyz')
|
||||
@request.display_log('xyz')
|
||||
@request.log_response res
|
||||
log[0].should == "# => 200 OK | text/html 4 bytes"
|
||||
end
|
||||
|
||||
it "set read_timeout" do
|
||||
|
|
|
@ -33,21 +33,31 @@ describe RestClient do
|
|||
RestClient.log = nil
|
||||
end
|
||||
|
||||
it "gets the log source from the RESTCLIENT_LOG environment variable" do
|
||||
ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return('from env')
|
||||
RestClient.log = 'from class method'
|
||||
RestClient.log.should == 'from env'
|
||||
it "uses << if the log is not a string" do
|
||||
log = RestClient.log = []
|
||||
log.should_receive(:<<).with('xyz')
|
||||
RestClient.log << 'xyz'
|
||||
end
|
||||
|
||||
it "sets a destination for log output, used if no environment variable is set" do
|
||||
ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return(nil)
|
||||
RestClient.log = 'from class method'
|
||||
RestClient.log.should == 'from class method'
|
||||
it "displays the log to stdout" do
|
||||
RestClient.log = 'stdout'
|
||||
STDOUT.should_receive(:puts).with('xyz')
|
||||
RestClient.log << 'xyz'
|
||||
end
|
||||
|
||||
it "returns nil (no logging) if neither are set (default)" do
|
||||
ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return(nil)
|
||||
RestClient.log.should == nil
|
||||
it "displays the log to stderr" do
|
||||
RestClient.log = 'stderr'
|
||||
STDERR.should_receive(:puts).with('xyz')
|
||||
RestClient.log << 'xyz'
|
||||
end
|
||||
|
||||
it "append the log to the requested filename" do
|
||||
RestClient.log = '/tmp/restclient.log'
|
||||
f = mock('file handle')
|
||||
File.should_receive(:open).with('/tmp/restclient.log', 'a').and_yield(f)
|
||||
f.should_receive(:puts).with('xyz')
|
||||
RestClient.log << 'xyz'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue