mirror of
				https://github.com/rest-client/rest-client.git
				synced 2022-11-09 13:49:40 -05:00 
			
		
		
		
	Merge pull request #538 from kaiuhl/per-resource-logging
Optional Resource and Request logging
This commit is contained in:
		
						commit
						18332b4461
					
				
					 7 changed files with 70 additions and 25 deletions
				
			
		
							
								
								
									
										11
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -528,7 +528,7 @@ $ restclient put http://example.com/resource < input_body
 | 
			
		|||
 | 
			
		||||
## Logging
 | 
			
		||||
 | 
			
		||||
To enable logging you can:
 | 
			
		||||
To enable logging globally you can:
 | 
			
		||||
 | 
			
		||||
- set RestClient.log with a Ruby Logger, or
 | 
			
		||||
- set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
 | 
			
		||||
| 
						 | 
				
			
			@ -536,7 +536,14 @@ To enable logging you can:
 | 
			
		|||
```ruby
 | 
			
		||||
$ RESTCLIENT_LOG=stdout path/to/my/program
 | 
			
		||||
```
 | 
			
		||||
Either produces logs like this:
 | 
			
		||||
 | 
			
		||||
You can also set individual loggers when instantiating a Resource:
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
resource = RestClient::Resource.new 'http://example.com/resource', log: Logger.new(STDOUT)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
All options produce logs like this:
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
RestClient.get "http://some/resource"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,7 @@ module RestClient
 | 
			
		|||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @log = args[:log]
 | 
			
		||||
      @tf = nil # If you are a raw request, this is your tempfile
 | 
			
		||||
      @max_redirects = args[:max_redirects] || 10
 | 
			
		||||
      @processed_headers = make_headers headers
 | 
			
		||||
| 
						 | 
				
			
			@ -531,19 +532,24 @@ module RestClient
 | 
			
		|||
      redacted_uri.to_s
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Default to the global logger if there's not a request-specific one
 | 
			
		||||
    def log
 | 
			
		||||
      @log || RestClient.log
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def log_request
 | 
			
		||||
      return unless RestClient.log
 | 
			
		||||
      return unless log
 | 
			
		||||
 | 
			
		||||
      out = []
 | 
			
		||||
 | 
			
		||||
      out << "RestClient.#{method} #{redacted_url.inspect}"
 | 
			
		||||
      out << payload.short_inspect if payload
 | 
			
		||||
      out << processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ")
 | 
			
		||||
      RestClient.log << out.join(', ') + "\n"
 | 
			
		||||
      log << out.join(', ') + "\n"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def log_response res
 | 
			
		||||
      return unless RestClient.log
 | 
			
		||||
      return unless log
 | 
			
		||||
 | 
			
		||||
      size = if @raw_response
 | 
			
		||||
               File.size(@tf.path)
 | 
			
		||||
| 
						 | 
				
			
			@ -551,7 +557,7 @@ module RestClient
 | 
			
		|||
               res.body.nil? ? 0 : res.body.size
 | 
			
		||||
             end
 | 
			
		||||
 | 
			
		||||
      RestClient.log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n"
 | 
			
		||||
      log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return a hash of headers whose keys are capitalized strings
 | 
			
		||||
| 
						 | 
				
			
			@ -782,13 +788,13 @@ module RestClient
 | 
			
		|||
        http_response.read_body do |chunk|
 | 
			
		||||
          @tf.write chunk
 | 
			
		||||
          size += chunk.size
 | 
			
		||||
          if RestClient.log
 | 
			
		||||
          if log
 | 
			
		||||
            if size == 0
 | 
			
		||||
              RestClient.log << "%s %s done (0 length file)\n" % [@method, @url]
 | 
			
		||||
              log << "%s %s done (0 length file)\n" % [@method, @url]
 | 
			
		||||
            elsif total == 0
 | 
			
		||||
              RestClient.log << "%s %s (zero content length)\n" % [@method, @url]
 | 
			
		||||
              log << "%s %s (zero content length)\n" % [@method, @url]
 | 
			
		||||
            else
 | 
			
		||||
              RestClient.log << "%s %s %d%% done (%d of %d)\n" % [@method, @url, (size * 100) / total, size, total]
 | 
			
		||||
              log << "%s %s %d%% done (%d of %d)\n" % [@method, @url, (size * 100) / total, size, total]
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,7 +51,8 @@ module RestClient
 | 
			
		|||
      Request.execute(options.merge(
 | 
			
		||||
              :method => :get,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def head(additional_headers={}, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +60,8 @@ module RestClient
 | 
			
		|||
      Request.execute(options.merge(
 | 
			
		||||
              :method => :head,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def post(payload, additional_headers={}, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +70,8 @@ module RestClient
 | 
			
		|||
              :method => :post,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :payload => payload,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def put(payload, additional_headers={}, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +80,8 @@ module RestClient
 | 
			
		|||
              :method => :put,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :payload => payload,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def patch(payload, additional_headers={}, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +90,8 @@ module RestClient
 | 
			
		|||
              :method => :patch,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :payload => payload,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def delete(additional_headers={}, &block)
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +99,8 @@ module RestClient
 | 
			
		|||
      Request.execute(options.merge(
 | 
			
		||||
              :method => :delete,
 | 
			
		||||
              :url => url,
 | 
			
		||||
              :headers => headers), &(block || @block))
 | 
			
		||||
              :headers => headers,
 | 
			
		||||
              :log => log), &(block || @block))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +127,10 @@ module RestClient
 | 
			
		|||
      options[:open_timeout]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def log
 | 
			
		||||
      options[:log] || RestClient.log
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Construct a subresource, preserving authentication.
 | 
			
		||||
    #
 | 
			
		||||
    # Example:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,10 @@ module RestClient
 | 
			
		|||
      "<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def log
 | 
			
		||||
      request.log
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.create(body, net_http_res, request)
 | 
			
		||||
      result = self.new(body || '')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +58,8 @@ module RestClient
 | 
			
		|||
      begin
 | 
			
		||||
        encoding = Encoding.find(charset) if charset
 | 
			
		||||
      rescue ArgumentError
 | 
			
		||||
        if RestClient.log
 | 
			
		||||
          RestClient.log << "No such encoding: #{charset.inspect}"
 | 
			
		||||
        if response.log
 | 
			
		||||
          response.log << "No such encoding: #{charset.inspect}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -694,6 +694,12 @@ describe RestClient::Request, :include_helpers do
 | 
			
		|||
      RestClient::Request.new(:method => :get, :url => 'http://user:password@url', :headers => {:user_agent => 'rest-client'}).log_request
 | 
			
		||||
      expect(log[0]).to eq %Q{RestClient.get "http://user:REDACTED@url", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "User-Agent"=>"rest-client"\n}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'logs to a passed logger, if provided' do
 | 
			
		||||
      logger = double('logger', '<<' => true)
 | 
			
		||||
      expect(logger).to receive(:<<)
 | 
			
		||||
      RestClient::Request.new(:method => :get, :url => 'http://user:password@url', log: logger).log_request
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "strips the charset from the response content type" do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,37 +7,37 @@ describe RestClient::Resource do
 | 
			
		|||
 | 
			
		||||
  context "Resource delegation" do
 | 
			
		||||
    it "GET" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.get
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "HEAD" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :head, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :head, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.head
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "POST" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.post 'abc', :content_type => 'image/jpg'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "PUT" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.put 'abc', :content_type => 'image/jpg'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "PATCH" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :patch, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :patch, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.patch 'abc', :content_type => 'image/jpg'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "DELETE" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.delete
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "overrides resource headers" do
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '2'}, :user => 'jane', :password => 'mypass')
 | 
			
		||||
      expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '2'}, :user => 'jane', :password => 'mypass', :log => nil)
 | 
			
		||||
      @resource.get 'X-Something' => '2'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -238,4 +238,16 @@ describe RestClient::Response, :include_helpers do
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "logging" do
 | 
			
		||||
    it "uses the request's logger" do
 | 
			
		||||
      stub_request(:get, 'http://some/resource').to_return(body: 'potato', status: 200)
 | 
			
		||||
 | 
			
		||||
      logger = double('logger', '<<' => true)
 | 
			
		||||
      request = RestClient::Request.new(url: 'http://some/resource', method: :get, log: logger)
 | 
			
		||||
 | 
			
		||||
      expect(logger).to receive(:<<)
 | 
			
		||||
 | 
			
		||||
      request.execute
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue