If I send a remote: true
request to our subdomain controller, our layout renders (which it shouldn't)
Having tested the request.xhr?
method in the action, it's returning nil
(not the true / false) that you'd expect. This works for non-CORS ajax. It only stops working with CORS-ajax (for subdomain)
Here's the code:
#app/views/controller/view.html.haml
= link_to "test", new_user_session_url, remote: :true
#routes
new_user_session_path GET /login(.:format) admin/users/sessions#new {:subdomain=>"test"}
The response occurs & we get a layout
We want no layout, which works without CORS:
#app/controllers/application_controller.rb
layout :layout_select
def layout_select
if request.xhr?
false
else
devise_controller? ? "admin" : "application"
end
end
We have CORS policy set up & working. However, it seems our CORS-request is not being treated as xhr
. Any ideas?
In light of the comments from Mike Campbell
, I was able to determine that CORS requests are not treated as ajax
(xhr
) by default
The problem lies in the headers which are passed on an Ajax request. Standard ajax passes the following header:
#actionpack/lib/action_dispatch/http/request.rb
def xhr?
@env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/
end
This is passed with a "naked" Ajax request, which allows the xhr?
method to return either true or false. The issue is in a CORS ajax call, this header is not passed. I don't know why, but it just sends an ORIGIN
header instead
The proposed fix from Github suggested to include this:
uri.host != @env['HTTP_HOST'] || uri.scheme != @env['rack.url_scheme'] || uri.port != @env['HTTP_PORT'].to_i
This would basically return a boolean response based on whether the request was from the same domain as the script. Although this was prevented for being unsafe, it lead me to two fixes:
- Append a new
cors?
method to the Rails core- Send the
http_x_requested_with
header through a CORS request
Considering we are just trying to access a subdomain with the request, we felt that editing the Rails core was slightly overkill, although right. Instead, we found that using the inbuilt headers
argument in jquery would help:
$.ajaxSetup({ headers: {"X-Requested-With": "XMLHttpRequest"}});
Whilst this works, I am eager to hear about any security issues it may present. And plus, whether we can access json
and other formats with it