team-umlaut/umlaut

View on GitHub
app/controllers/link_router_controller.rb

Summary

Maintainability
A
35 mins
Test Coverage
# All clicks on a ServiceResponse are actually sent through this controller,
# which redirects to actual destination. That allows statistic logging,
# as well as special behavior (like EZProxy redirection, or showing in a
# bannered frameset).
require 'cgi'
class LinkRouterController < UmlautController
  # Add resolve layout for handling errors.
  layout :resolve_layout

  def index
    # Capture mysterious exception for better error reporting.
    begin
      svc_response = ServiceResponse.find(params[:id])
    rescue ActiveRecord::RecordNotFound => exception
      # Usually this happens when it's a spider trying an old link. "go" links
      # don't stay good forever! Bad spider, ignoring our robots.txt.
      log_error_with_context(exception, :warn)
      raise exception# will be caught by top level rescue_from
    end
    @collection = self.create_collection
    clickthrough = Clickthrough.new
    clickthrough.request_id = svc_response.request_id
    clickthrough.service_response_id = svc_response.id
    clickthrough.save
    redirect_to calculate_url_for_response(svc_response)
  end

  protected

  # Used to calculate a destination/target url for an Umlaut response item.
  #
  # Pass in a ServiceType join object (not actually a ServiceResponse, sorry)
  # Calculates the URL for it, and then runs our link_out_filters on it,
  # returning the final calculated url.
  #
  # Also requires a rails 'params' object, since url calculation sometimes
  # depends on submitted HTTP params.
  #
  # Used from LinkController's index,
  def calculate_url_for_response(svc_response)
    svc = ServiceStore.instantiate_service!(svc_response.service_id, nil)
    destination =  svc.response_url(svc_response, params)

    raise_missing_url!(svc_response) if destination.blank?

    # if response_url returned a string, it's an external url and we're
    # done. If it's something else, usually a hash, then pass it to
    # url_for to generate a url.
    if destination.kind_of?(String)
      url = destination

      # Call link_out_filters, if neccesary.
      # These are services listed as  task: link_out_filter  in services.yml
      (1..9).each do |priority|
        @collection.link_out_service_level( priority ).each do |filter|
          filtered_url = filter.link_out_filter(url, svc_response)
          url = filtered_url if filtered_url
        end
      end
      return url
    else
      return url_for(params_preserve_xhr(destination))
    end
  end
  protected :calculate_url_for_response
end

def raise_missing_url!(service_response)
  svc_rsp_id  = service_response.try(:id)
  service_id  = service_response.try(:service_id)
  type        = service_response.try(:service_type_value_name)
  text        = service_response.try(:display_text)
  request_id  = service_response.try(:request).try(:id)
  request_url = service_response.try(:request).try(:http_env).try {|h| h["REQUEST_URI"] }

  raise ArgumentError.new("LinkRouterController#index missing URL to redirect to for ServiceResponse:#{svc_rsp_id} (#{service_id}/#{type}/#{text}) from original request url: #{request_url}")
end