Class: OpenID::StandardFetcher

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

Constant Summary collapse

USER_AGENT =
"ruby-openid/#{OpenID::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.



126
127
128
129
130
131
# 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

Instance Attribute Details

#ca_fileObject

Returns the value of attribute ca_file.



122
123
124
# File 'lib/openid/fetchers.rb', line 122

def ca_file
  @ca_file
end

#timeoutObject

Returns the value of attribute timeout.



123
124
125
# File 'lib/openid/fetchers.rb', line 123

def timeout
  @timeout
end

Instance Method Details

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



181
182
183
184
185
186
187
188
189
190
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
# 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) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# 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) ⇒ Object



137
138
139
140
141
142
# 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) ⇒ Object



144
145
146
147
148
149
150
# 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) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/openid/fetchers.rb', line 133

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