app/controllers/link_router_controller.rb
# 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