Class: OpenID::StandardFetcher

Inherits:
Object
  • Object
show all
Defined in:
lib/openid/fetchers.rb

Constant Summary collapse

USER_AGENT =
"ruby-openid/#{OpenID::Version::VERSION} (#{RUBY_PLATFORM})"
REDIRECT_LIMIT =
5
TIMEOUT =
ENV["RUBY_OPENID_FETCHER_TIMEOUT"] || 60

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(proxy_addr = nil, proxy_port = nil, proxy_user = nil, proxy_pass = nil) ⇒ StandardFetcher

I can fetch through a HTTP proxy; arguments are as for Net::HTTP::Proxy.



133
134
135
136
137
138
139
# File 'lib/openid/fetchers.rb', line 133

def initialize(proxy_addr = nil, proxy_port = nil,
  proxy_user = nil, proxy_pass = nil)
  @ca_file = nil
  @proxy = Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user, proxy_pass)
  @timeout = TIMEOUT
  @ssl_verify_peer = nil
end

Instance Attribute Details

#ca_fileObject

Returns the value of attribute ca_file.



130
131
132
# File 'lib/openid/fetchers.rb', line 130

def ca_file
  @ca_file
end

#ssl_verify_peerObject

Returns the value of attribute ssl_verify_peer.



130
131
132
# File 'lib/openid/fetchers.rb', line 130

def ssl_verify_peer
  @ssl_verify_peer
end

#timeoutObject

Returns the value of attribute timeout.



130
131
132
# File 'lib/openid/fetchers.rb', line 130

def timeout
  @timeout
end

Instance Method Details

#fetch(url, body = nil, headers = nil, redirect_limit = REDIRECT_LIMIT) ⇒ Object

Raises:



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/openid/fetchers.rb', line 191

def fetch(url, body = nil, headers = nil, redirect_limit = REDIRECT_LIMIT)
  unparsed_url = url.dup
  url = URI.parse(url)
  raise FetchingError, "Invalid URL: #{unparsed_url}" if url.nil?

  headers ||= {}
  headers["User-agent"] ||= USER_AGENT

  begin
    conn = make_connection(url)
    response = nil

    whole_body = ""
    body_size_limitter = lambda do |r|
      r.read_body do |partial| # read body now
        whole_body << partial
        raise FetchingError.new("Response Too Large") if whole_body.length > MAX_RESPONSE_KB
      end
      whole_body
    end
    response = conn.start do
      # Check the certificate against the URL's hostname
      conn.post_connection_check(url.host) if supports_ssl?(conn) and conn.use_ssl?

      if body.nil?
        conn.request_get(url.request_uri, headers, &body_size_limitter)
      else
        headers["Content-type"] ||= "application/x-www-form-urlencoded"
        conn.request_post(url.request_uri, body, headers, &body_size_limitter)
      end
    end
  rescue Timeout::Error => e
    raise FetchingError, "Error fetching #{url}: #{e}"
  rescue RuntimeError => e
    raise e
  rescue OpenSSL::SSL::SSLError => e
    raise SSLFetchingError, "Error connecting to SSL URL #{url}: #{e}"
  rescue FetchingError => e
    raise e
  rescue Exception => e
    raise FetchingError, "Error fetching #{url}: #{e}"
  end

  case response
  when Net::HTTPRedirection
    if redirect_limit <= 0
      raise HTTPRedirectLimitReached.new(
        "Too many redirects, not fetching #{response["location"]}",
      )
    end
    begin
      fetch(response["location"], body, headers, redirect_limit - 1)
    rescue HTTPRedirectLimitReached => e
      raise e
    rescue FetchingError => e
      raise FetchingError, "Error encountered in redirect from #{url}: #{e}"
    end
  else
    response = HTTPResponse._from_net_response(response, unparsed_url)
    response.body = whole_body
    setup_encoding(response)
    response
  end
end

#make_connection(uri) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/openid/fetchers.rb', line 160

def make_connection(uri)
  conn = make_http(uri)

  unless conn.is_a?(Net::HTTP)
    raise format(
      "Expected Net::HTTP object from make_http; got %s",
      conn.class,
    ).to_s
  end

  if uri.scheme == "https"
    raise "SSL support not found; cannot fetch #{uri}" unless supports_ssl?(conn)

    conn.use_ssl = true

    if @ca_file
      set_verified(conn, true)
      conn.ca_file = @ca_file
    elsif @ssl_verify_peer
      set_verified(conn, true)
    else
      Util.log("WARNING: making https request to #{uri} without verifying " +
               "server certificate; no CA path was specified.")
      set_verified(conn, false)
    end

  end

  conn
end

#make_http(uri) ⇒ Object



145
146
147
148
149
150
# File 'lib/openid/fetchers.rb', line 145

def make_http(uri)
  http = @proxy.new(uri.host, uri.port)
  http.read_timeout = @timeout
  http.open_timeout = @timeout
  http
end

#set_verified(conn, verify) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/openid/fetchers.rb', line 152

def set_verified(conn, verify)
  conn.verify_mode = if verify
    OpenSSL::SSL::VERIFY_PEER
  else
    OpenSSL::SSL::VERIFY_NONE
  end
end

#supports_ssl?(conn) ⇒ Boolean

Returns:

  • (Boolean)


141
142
143
# File 'lib/openid/fetchers.rb', line 141

def supports_ssl?(conn)
  conn.respond_to?(:use_ssl=)
end