Class: ResourceController

Inherits:
UmlautController show all
Defined in:
app/controllers/resource_controller.rb

Overview

We proxy cover images from foreign sources through Umlaut sometimes, in order to switch their access from http to https to avoid browser warnings on an https page. This controller does that.

It does NOT take URL in request parameters, but instead takes a response ID. it will only proxy urls already stored in umlaut responses, so this is not an open proxy with the security problems that would cause.

Constant Summary collapse

HttpTimeout =

seconds to wait for thing were proxying. Yeah, fairly big num seems neccesary for Amazon at least.

4

Instance Method Summary collapse

Methods included from Umlaut::ControllerBehavior

#default_url_options, #set_locale

Methods included from UmlautConfigurable

set_default_configuration!

Instance Method Details

#proxyObject

We really ought to stream the remote response to our client, but I couldn't get that to work how I wanted in Rails2. Even using render :text=>proc, problem is we needed to know the content-type before we read any of the response, which we didn't. This implementation holds the whole image in memory for a second while it delivers it, oh well. doesn't seem to effect speed much, even though it's not optimal.


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
# File 'app/controllers/resource_controller.rb', line 22

def proxy
  svc_resp = ServiceResponse.find(params[:id])
  url_str =  svc_resp.view_data[:url]
  uri = nil
  begin
    uri = URI(url_str)
  rescue
    raise Exception.new("resource#proxy can only handle String urls, not '#{url.inspect}'")
  end

  proxied_headers = proxy_headers( request, uri.host )

  # open-uri :read_timeout is not behaving reliably, resort to Timeout.timeout
  # should we just be using raw Net::Http and give up on open-uri? remember
  # to update timeout exceptions in rescue below if you change.
  remote_response = Timeout.timeout(HttpTimeout) {  open(uri, 'rb', proxied_headers) }

  # copy certain headers to our proxied response
  ["Content-Type", "Cache-Control", "Expires", "Content-Length", "Last-Modified", "Etag", "Date"].each do |key|
    value = remote_response.meta[key.downcase] # for some reason open-uri lowercases em
    # rack doens't like it if we set a nil value here.
    response.headers[key] = value unless value.blank?
  end

  response.headers["X-Original-Url"] = url_str

  # And send the actual result out
  render(:text => remote_response.read)
rescue Timeout::Error, Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
  msg                = "#{e.inspect}: waiting for image proxy from `#{url_str}`; timeout is currently set to #{HttpTimeout}s; returning broken image"
  backtrace          = Umlaut::Util.clean_backtrace(e)

  logger.warn("#{msg}\n  #{backtrace.join("\n  ")}")

  response.headers['X-Original-Url'] = url_str
  render :text => msg, :status => 504
end