class OpenID::StandardFetcher

Constants

REDIRECT_LIMIT
TIMEOUT
USER_AGENT

Attributes

ca_file[RW]
timeout[RW]

Public Class Methods

new(proxy_addr=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil) click to toggle source

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

# File lib/openid/fetchers.rb, line 126
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
end

Public Instance Methods

fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT) click to toggle source
# File lib/openid/fetchers.rb, line 181
def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT)
  unparsed_url = url.dup
  url = URI::parse(url)
  if url.nil?
    raise FetchingError, "Invalid URL: #{unparsed_url}"
  end

  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
        if whole_body.length > MAX_RESPONSE_KB
          raise FetchingError.new("Response Too Large")
        end
      end
      whole_body
    end
    response = conn.start {
      # Check the certificate against the URL's hostname
      if supports_ssl?(conn) and conn.use_ssl?
        conn.post_connection_check(url.host)
      end

      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
    }
  rescue Timeout::Error => why
    raise FetchingError, "Error fetching #{url}: #{why}"
  rescue RuntimeError => why
    raise why
  rescue OpenSSL::SSL::SSLError => why
    raise SSLFetchingError, "Error connecting to SSL URL #{url}: #{why}"
  rescue FetchingError => why
    raise why
  rescue Exception => why
    raise FetchingError, "Error fetching #{url}: #{why}"
  end

  case response
  when Net::HTTPRedirection
    if redirect_limit <= 0
      raise HTTPRedirectLimitReached.new(
        "Too many redirects, not fetching #{response['location']}")
    end
    begin
      return fetch(response['location'], body, headers, redirect_limit - 1)
    rescue HTTPRedirectLimitReached => e
      raise e
    rescue FetchingError => why
      raise FetchingError, "Error encountered in redirect from #{url}: #{why}"
    end
  else
    response = HTTPResponse._from_net_response(response, unparsed_url)
    response.body = whole_body
    setup_encoding(response)
    return response
  end
end
make_connection(uri) click to toggle source
# File lib/openid/fetchers.rb, line 152
def make_connection(uri)
  conn = make_http(uri)

  if !conn.is_a?(Net::HTTP)
    raise RuntimeError, sprintf("Expected Net::HTTP object from make_http; got %s",
                                conn.class)
  end

  if uri.scheme == 'https'
    if supports_ssl?(conn)

      conn.use_ssl = true

      if @ca_file
        set_verified(conn, true)
        conn.ca_file = @ca_file
      else
        Util.log("WARNING: making https request to #{uri} without verifying " +
                 "server certificate; no CA path was specified.")
        set_verified(conn, false)
      end
    else
      raise RuntimeError, "SSL support not found; cannot fetch #{uri}"
    end
  end

  return conn
end
make_http(uri) click to toggle source
# File lib/openid/fetchers.rb, line 137
def make_http(uri)
  http = @proxy.new(uri.host, uri.port)
  http.read_timeout = @timeout
  http.open_timeout = @timeout
  return http
end
set_verified(conn, verify) click to toggle source
# File lib/openid/fetchers.rb, line 144
def set_verified(conn, verify)
  if verify
    conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
  else
    conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
end
supports_ssl?(conn) click to toggle source
# File lib/openid/fetchers.rb, line 133
def supports_ssl?(conn)
  return conn.respond_to?(:use_ssl=)
end

Private Instance Methods

setup_encoding(response) click to toggle source
# File lib/openid/fetchers.rb, line 252
def setup_encoding(response)
  return unless defined?(Encoding.default_external)
  return unless charset = response.type_params["charset"]

  begin
    encoding = Encoding.find(charset)
  rescue ArgumentError
  end
  encoding ||= Encoding.default_external

  body = response.body
  if body.respond_to?(:force_encoding)
    body.force_encoding(encoding)
  else
    body.set_encoding(encoding)
  end
end