Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 132 lines (109 sloc) 3.055 kb
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 128 129 130 131 132
#compatibility with Ruby 1.9.2 preview1 to allow reading raw responses
class StringIO
  alias_method :read_nonblock, :sysread
end

module WebMock

  class ResponseFactory
    def self.response_for(options)
      if options.respond_to?(:call)
        WebMock::DynamicResponse.new(options)
      else
        WebMock::Response.new(options)
      end
    end
  end
  
  class Response
    def initialize(options = {})
      if options.is_a?(IO) || options.is_a?(String)
        self.options = read_raw_response(options)
      else
        self.options = options
      end
    end

    def headers
      @headers
    end
    
    def headers=(headers)
      @headers = headers
      if @headers && !@headers.is_a?(Proc)
        @headers = Util::Headers.normalize_headers(@headers)
      end
    end

    def body
      @body || ''
    end
    
    def body=(body)
      @body = body
      stringify_body!
    end

    def status
      @status || [200, ""]
    end

    def status=(status)
      @status = status.is_a?(Integer) ? [status, ""] : status
    end

    def exception
      @exception
    end

    def raise_error_if_any
      raise @exception.new('Exception from WebMock') if @exception
    end

    def options=(options)
      self.headers = options[:headers]
      self.status = options[:status]
      self.body = options[:body]
      @exception = options[:exception]
    end

    def evaluate!(request_signature)
      self.body = @body.call(request_signature) if @body.is_a?(Proc)
      self.headers = @headers.call(request_signature) if @headers.is_a?(Proc)
      self.status = @status.call(request_signature) if @status.is_a?(Proc)
      self
    end

    def ==(other)
      self.body == other.body &&
      self.headers === other.headers &&
      self.status == other.status &&
      self.exception == other.exception
    end

    private

    def stringify_body!
      if @body.is_a?(IO)
        io = @body
        @body = io.read
        io.close
      end
    end

    def read_raw_response(raw_response)
      if raw_response.is_a?(IO)
        string = raw_response.read
        raw_response.close
        raw_response = string
      end
      socket = Net::BufferedIO.new(raw_response)
      response = Net::HTTPResponse.read_new(socket)
      transfer_encoding = response.delete('transfer-encoding') #chunks were already read by curl
      response.reading_body(socket, true) {}

      options = {}
      options[:headers] = {}
      response.each_header {|name, value| options[:headers][name] = value}
      options[:headers]['transfer-encoding'] = transfer_encoding if transfer_encoding
      options[:body] = response.read_body
      options[:status] = [response.code.to_i, response.message]
      options
    end

  end

  class DynamicResponse < Response
    attr_accessor :responder

    def initialize(responder)
      @responder = responder
    end

    def dup
      self.class.new(@responder)
    end

    def evaluate!(request_signature)
      self.options = @responder.call(request_signature)
      self
    end
  end
end
Something went wrong with that request. Please try again.