rabid_zombie
rabid_zombie

Reputation: 992

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?

Upvotes: 1

Views: 4181

Answers (2)

Rajan Verma - Aarvy
Rajan Verma - Aarvy

Reputation: 2117

You should try giving relative url instead of absolute in ajax. I had the same problem, and worked by changing url

Upvotes: 0

Ashitaka
Ashitaka

Reputation: 19203

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' }
});

Upvotes: 1

Related Questions