Cristian
Cristian

Reputation: 6077

Is there a way to know if a page request came from the same application?

In Rails3, is there a way to check if the page I'm rendering now was requested from the same application, without the use of the hardcoded domain name?

I currently have:

def back_link(car_id = '')
  # Check if search exists
  uri_obj = URI.parse(controller.request.env["HTTP_REFERER"]) if controller.request.env["HTTP_REFERER"].present?
  if uri_obj.present? && ["my_domain.com", "localhost"].include?(uri_obj.host) && uri_obj.query.present? && uri_obj.query.include?('search')
    link_to '◀ '.html_safe + t('back_to_search'), url_for(:back) + (car_id.present? ? '#' + car_id.to_s : ''), :class => 'button grey back'
  end
end

But this doesn't check for the "www." in front of the domain and all other possible situations.

It would also be nice if I could find out the specific controller and action that were used in the previous page (the referrer).

Upvotes: 7

Views: 10530

Answers (3)

Joshua Pinter
Joshua Pinter

Reputation: 47471

Create an internal_request? method utilizing request.referrer.

Compare the host and port of the request.referrer with your Application's host and port.

require 'uri' # Might be necesseary.

def internal_request?
  return false if request.referrer.blank?

  referrer = URI.parse( request.referrer )

  application_host = Rails.application.config.action_mailer.default_url_options[ :host ]
  application_port = Rails.application.config.action_mailer.default_url_options[ :port ]

  return true if referrer.host == application_host && referrer.port == application_port

  false
end

And then call it like this where you need it, most likely in application_controller.rb:

if internal_request?
  do_something
end

Some caveats:

  • This might need to be modified if you're using subdomains. Easy, though.
  • This will require you to be setting your host and port for ActionMailer in your configuration, which is common.
  • You might want to make it the reverse, like external_request? since you're likely handling those situations uniquely. This would allow you to do something like this:

    do_something_unique if external_request?
    

Upvotes: 0

Alex Peattie
Alex Peattie

Reputation: 27647

Try something like this:

ref = URI.parse(controller.request.env["HTTP_REFERER"])

if ref.host == ENV["HOSTNAME"]
  # do something

To try and get the controller/action from the referring page:

ActionController::Routing::Routes.recognize_path(url.path)
  #=> {:controller => "foo", :action => "bar"}

Upvotes: 2

Matthew Rudy
Matthew Rudy

Reputation: 16834

I think you're looking at this the wrong way.

If you look around the web, find a site with a search feature, and follow the link you'll see a param showing what was searched for.

That's a good way to do it.

Doing it by HTTP_REFERER seems a bit fragile, and won't work, for example, from a bookmark, or posted link.

eg.

/cars/12?from_search=sports+cars

then you can just look up the params[:from_search]

If you really need to do it by HTTP_REFERER then you probably dont have to worry about subdomains. Just;

def http_referer_uri
  request.env["HTTP_REFERER"] && URI.parse(request.env["HTTP_REFERER"])
end

def refered_from_our_site?
  if uri = http_referer_uri
    uri.host == request.host
  end
end

def refered_from_a_search?
  if refered_from_our_site?
    http_referer_uri.try(:query)['search']
  end
end

Upvotes: 15

Related Questions