rabid_zombie rabid_zombie - 1 year ago 70
Ajax Question

Routing error: No route matches [OPTIONS]

When I try to set my request header token, I receive an error:

ActionController::RoutingError (No route matches [OPTIONS] "/data"):


Here is the ajax call:

$.ajax({
url: this.hostName + url,
type: 'POST',
data: data,
dataType: 'json',
beforeSend: function( xhr ) {
xhr.setRequestHeader( 'X-CSRF-Token', $( 'meta[name="csrf-token"]' ).attr( 'content' ) );
},
success: function(response) {
console.log('success');
console.log(response);
},
error: function(response) {
console.log('error');
console.log(response);
}
});


If I leave the request header out:

Started POST "/data" for 127.0.0.1 at 2012-07-24 18:37:22 -0700


but I get a warning stating:

WARNING: Can't verify CSRF token authenticity


Any ideas as to why this is happening?

Answer Source

Have you tried

$.ajax({
    url: this.hostName + url,
    type: 'POST',
    headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') }
    data: { param : 'something' },
    dataType: 'json'
});

And then in your controller params[:param] will give you 'something'.

If you are interested to know why you need all that X-CSRF-Token stuff, this is a good read. Basically, Rails automatically includes that token in your page to keep your application safe. If you inspect any page of your site, you'll see in the head of your HTML document something like this:

<meta content="guma1QdmO9Tn9SB4yV4DonkY4xf4Sy6lIvrFyHIaR1U=" name="csrf-token">

This is created by the line <%= csrf_meta_tags %> included in your application.html.erb file.

Rails automatically includes this token in regular non-GET requests to keep them safe. But with javascript and ajax, you have to do this manually by searching the DOM for the token with the jQuery function $('meta[name="csrf-token"]'.

Now, this isn't very efficient because you are searching for that token every time you are making a request. So what you should do, is use ajaxSetup, like this:

$.ajaxSetup({
    type: 'POST',
    headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') }
    dataType: 'json'
});

And now, whenever you want to send a request, all you need is this:

$.ajax({
    url: this.hostName + url,
    data: { param : 'something' }
});

EDIT: Ah, I see. What do you get when you do alert(this.hostName + url)? And how are you declaring your routes? Because if I remember correctly, you can use relative urls instead of absolute urls, you don't need the root part. Here's an example:

# routes.rb
post "relative_url" => 'controller#action'

# file.js
$.ajax({
    url: "relative_url",
    data: { param : 'something' }
});
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download