Class: RestClient::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/restclient/request.rb,
lib/restclient/exceptions.rb

Overview

backwards compatibility

Constant Summary collapse

Redirect =
RestClient::Redirect
Unauthorized =
RestClient::Unauthorized
RequestFailed =
RestClient::RequestFailed

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ Request

Returns a new instance of Request.



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/restclient/request.rb', line 15

def initialize(args)
  @method = args[:method] or raise ArgumentError, "must pass :method"
  @url = args[:url] or raise ArgumentError, "must pass :url"
  @headers = args[:headers] || {}
    @cookies = @headers.delete(:cookies) || args[:cookies] || {}
  @payload = process_payload(args[:payload])
  @user = args[:user]
  @password = args[:password]
  @timeout = args[:timeout]
  @open_timeout = args[:open_timeout]
end

Instance Attribute Details

#cookiesObject (readonly)

Returns the value of attribute cookies.



9
10
11
# File 'lib/restclient/request.rb', line 9

def cookies
  @cookies
end

#headersObject (readonly)

Returns the value of attribute headers.



9
10
11
# File 'lib/restclient/request.rb', line 9

def headers
  @headers
end

#methodObject (readonly)

Returns the value of attribute method.



9
10
11
# File 'lib/restclient/request.rb', line 9

def method
  @method
end

#open_timeoutObject (readonly)

Returns the value of attribute open_timeout.



9
10
11
# File 'lib/restclient/request.rb', line 9

def open_timeout
  @open_timeout
end

#passwordObject (readonly)

Returns the value of attribute password.



9
10
11
# File 'lib/restclient/request.rb', line 9

def password
  @password
end

#payloadObject (readonly)

Returns the value of attribute payload.



9
10
11
# File 'lib/restclient/request.rb', line 9

def payload
  @payload
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



9
10
11
# File 'lib/restclient/request.rb', line 9

def timeout
  @timeout
end

#urlObject (readonly)

Returns the value of attribute url.



9
10
11
# File 'lib/restclient/request.rb', line 9

def url
  @url
end

#userObject (readonly)

Returns the value of attribute user.



9
10
11
# File 'lib/restclient/request.rb', line 9

def user
  @user
end

Class Method Details

.execute(args) ⇒ Object



11
12
13
# File 'lib/restclient/request.rb', line 11

def self.execute(args)
  new(args).execute
end

Instance Method Details

#decode(content_encoding, body) ⇒ Object



148
149
150
151
152
153
154
155
156
# File 'lib/restclient/request.rb', line 148

def decode(content_encoding, body)
  if content_encoding == 'gzip' and not body.empty?
    Zlib::GzipReader.new(StringIO.new(body)).read
  elsif content_encoding == 'deflate'
    Zlib::Inflate.new.inflate(body)
  else
    body
  end
end

#default_headersObject



182
183
184
# File 'lib/restclient/request.rb', line 182

def default_headers
  { :accept => 'application/xml', :accept_encoding => 'gzip, deflate' }
end

#display_log(msg) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
# File 'lib/restclient/request.rb', line 170

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 }
  end
end

#executeObject



27
28
29
30
31
32
# File 'lib/restclient/request.rb', line 27

def execute
  execute_inner
rescue Redirect => e
  @url = e.url
  execute
end

#execute_innerObject



34
35
36
37
# File 'lib/restclient/request.rb', line 34

def execute_inner
  uri = parse_url_with_auth(url)
  transmit uri, net_http_request_class(method).new(uri.request_uri, make_headers(headers)), payload
end

#make_headers(user_headers) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/restclient/request.rb', line 39

def make_headers(user_headers)
    unless @cookies.empty?
      user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
    end

  default_headers.merge(user_headers).inject({}) do |final, (key, value)|
    final[key.to_s.gsub(/_/, '-').capitalize] = value.to_s
    final
  end
end

#net_http_classObject



50
51
52
53
54
55
56
57
# File 'lib/restclient/request.rb', line 50

def net_http_class
  if RestClient.proxy
    proxy_uri = URI.parse(RestClient.proxy)
    Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
  else
    Net::HTTP
  end
end

#net_http_request_class(method) ⇒ Object



59
60
61
# File 'lib/restclient/request.rb', line 59

def net_http_request_class(method)
  Net::HTTP.const_get(method.to_s.capitalize)
end

#parse_url(url) ⇒ Object



63
64
65
66
# File 'lib/restclient/request.rb', line 63

def parse_url(url)
  url = "http://#{url}" unless url.match(/^http/)
  URI.parse(url)
end

#parse_url_with_auth(url) ⇒ Object



68
69
70
71
72
73
# File 'lib/restclient/request.rb', line 68

def parse_url_with_auth(url)
  uri = parse_url(url)
  @user = uri.user if uri.user
  @password = uri.password if uri.password
  uri
end

#process_payload(p = nil, parent_key = nil) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/restclient/request.rb', line 75

def process_payload(p=nil, parent_key=nil)
  unless p.is_a?(Hash)
    p
  else
    @headers[:content_type] ||= 'application/x-www-form-urlencoded'
    p.keys.map do |k|
      key = parent_key ? "#{parent_key}[#{k}]" : k
      if p[k].is_a? Hash
        process_payload(p[k], key)
      else
        value = URI.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
        "#{key}=#{value}"
      end
    end.join("&")
  end
end

#process_result(res) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/restclient/request.rb', line 124

def process_result(res)
  if res.code =~ /\A2\d{2}\z/
    decode res['content-encoding'], res.body if res.body
  elsif %w(301 302 303).include? res.code
    url = res.header['Location']

    if url !~ /^http/
      uri = URI.parse(@url)
      uri.path = "/#{url}".squeeze('/')
      url = uri.to_s
    end

    raise Redirect, url
  elsif res.code == "304"
    raise NotModified, res
  elsif res.code == "401"
    raise Unauthorized, res
  elsif res.code == "404"
    raise ResourceNotFound, res
  else
    raise RequestFailed, res
  end
end

#request_logObject



158
159
160
161
162
163
164
# File 'lib/restclient/request.rb', line 158

def request_log
  out = []
  out << "RestClient.#{method} #{url.inspect}"
  out << (payload.size > 100 ? "(#{payload.size} byte payload)".inspect : payload.inspect) if payload
  out << headers.inspect.gsub(/^\{/, '').gsub(/\}$/, '') unless headers.empty?
  out.join(', ')
end

#response_log(res) ⇒ Object



166
167
168
# File 'lib/restclient/request.rb', line 166

def response_log(res)
  "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{(res.body) ? res.body.size : nil} bytes"
end

#setup_credentials(req) ⇒ Object



120
121
122
# File 'lib/restclient/request.rb', line 120

def setup_credentials(req)
  req.basic_auth(user, password) if user
end

#transmit(uri, req, payload) ⇒ Object



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
# File 'lib/restclient/request.rb', line 92

def transmit(uri, req, payload)
  setup_credentials(req)

  net = net_http_class.new(uri.host, uri.port)
  net.use_ssl = uri.is_a?(URI::HTTPS)
  net.verify_mode = OpenSSL::SSL::VERIFY_NONE
  net.read_timeout = @timeout if @timeout
  net.open_timeout = @open_timeout if @open_timeout

  display_log request_log

  net.start do |http|
    res = http.request(req, payload)
    display_log response_log(res)
    string = process_result(res)

    if string or @method == :head
      Response.new(string, res)
    else
      nil
    end
  end
rescue EOFError
  raise RestClient::ServerBrokeConnection
rescue Timeout::Error
  raise RestClient::RequestTimeout
end