File: responder.rb

package info (click to toggle)
ruby-fakeweb 1.3.0%2Bgit20170806%2Bdfsg1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 452 kB
  • sloc: ruby: 2,057; sh: 24; makefile: 3
file content (127 lines) | stat: -rw-r--r-- 3,963 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module FakeWeb
  class Responder #:nodoc:

    attr_accessor :method, :uri, :options, :times
    KNOWN_OPTIONS = [:body, :exception, :response, :status].freeze

    def initialize(method, uri, options, times)
      self.method = method
      self.uri = uri
      self.options = options
      self.times = times ? times : 1

      if options.has_key?(:file) || options.has_key?(:string)
        print_file_string_options_deprecation_warning
        options[:body] = options.delete(:file) || options.delete(:string)
      end
    end

    def response(&block)
      if has_baked_response?
        response = baked_response
      else
        code, msg = meta_information
        response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
        response.instance_variable_set(:@body, body)
        headers_extracted_from_options.each do |name, value|
          if value.respond_to?(:each)
            value.each { |v| response.add_field(name, v) }
          else
            response[name] = value
          end
        end
      end

      response.instance_variable_set(:@read, true)
      response.extend FakeWeb::Response

      optionally_raise(response)

      yield response if block_given?

      response
    end

    private

    def headers_extracted_from_options
      options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value|
        [name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value]
      }
    end

    def body
      body = options[:body]
      return nil if body.to_s == ''

      body = body.to_s if defined?(Pathname) && body.is_a?(Pathname)

      if !body.include?("\0") && File.exist?(body) && !File.directory?(body)
        File.read(body)
      else
        body
      end
    end

    def baked_response
      response = options[:response]
      response = response.to_s if defined?(Pathname) && response.is_a?(Pathname)

      if response.is_a?(String) || response.is_a?(IO) || response.is_a?(StringIO)
        socket = Net::BufferedIO.new(response)
        r = Net::HTTPResponse.read_new(socket)

        # Store the original transfer-encoding
        saved_transfer_encoding = r.instance_eval {
          @header['transfer-encoding'] if @header.key?('transfer-encoding')
        }

        # Read the body of response
        r.instance_eval { @header['transfer-encoding'] = nil }
        r.reading_body(socket, true) {}

        # Delete the transfer-encoding key from r.@header if there wasn't one;
        # otherwise, restore the saved_transfer_encoding
        if saved_transfer_encoding.nil?
          r.instance_eval { @header.delete('transfer-encoding') }
        else
          r.instance_eval { @header['transfer-encoding'] = saved_transfer_encoding }
        end
        r
      elsif response.is_a?(Net::HTTPResponse)
        response
      else
        raise ArgumentError, "Handler not implemented for response #{response.inspect}"
      end
    end

    def has_baked_response?
      options.has_key?(:response)
    end

    def optionally_raise(response)
      return unless options.has_key?(:exception)

      case options[:exception].to_s
      when "Net::HTTPError", "OpenURI::HTTPError"
        raise options[:exception].new('Exception from FakeWeb', response)
      else
        raise options[:exception].new('Exception from FakeWeb')
      end
    end

    def meta_information
      options.has_key?(:status) ? options[:status] : [200, 'OK']
    end

    def print_file_string_options_deprecation_warning
      which = options.has_key?(:file) ? :file : :string
      first_external_caller = caller.detect { |line| !line.include?("/vendor_ruby/fake_web") }
      $stderr.puts
      $stderr.puts "Deprecation warning: FakeWeb's :#{which} option has been renamed to :body."
      $stderr.puts "Just replace :#{which} with :body in your FakeWeb.register_uri calls."
      $stderr.puts "Called at #{first_external_caller}"
    end

  end
end