1

I can make the following request using curl and receive a 200 OK, I'm not able to get a 200 OK with an ajax request. I've tried this below without luck

can't get this to work

$.ajax({
    beforeSend: function (xhr) { xhr.setRequestHeader ('Authorization', 'Token 6ff1fed470ec2ddaf8b3af958461990G') },
    type: "GET",
    url: "http://testurl.abc.com/api/v1/category/",
    dataType: "json"
}).done(function( msg ) {
    console.log( msg );
}).fail(function(jqXHR, textStatus, errorThrown) {
    console.log( "Request failed: " + textStatus );
    console.log( errorThrown );
});

The good request

curl http://testurl.abc.com/api/v1/category -I -H 'Authorization: Token token='6ff1fed470ec2ddaf8b3af958461990G''

HTTP/1.1 200 OK 
Cache-Control: max-age=0, private, must-revalidate
Content-length: 0
Content-Type: application/json; charset=utf-8
Date: Sat, 01 Mar 2014 05:05:45 GMT
Etag: "c676e7d052ef40b8ff298c158f8bd7af"
Server: WEBrick/1.3.1 (Ruby/2.0.0/2014-02-24)
Set-Cookie: request_method=HEAD; path=/   
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 7ba9b354-e3d0-4408-81df-8d5e991875e7
X-Runtime: 0.006036
X-Ua-Compatible: chrome=1
X-Xss-Protection: 1; mode=block
Connection: keep-alive

any clues appreciated.

cheers!

Update: It doesn't look like the Authorization: Token token={token} isn't being set correctly. If I edit a failed request in charles proxy to include this then it works as expected. Just a question now of figuring out why my call to setRequestHeader is being ignored.

module Api                                                                                                                                                                                                  
       module V1                                                                                                                                                                                           
         class CategoryController < ApplicationController                                                                                                                                                                                                                                                                              
        before_filter :restrict_access                                                                                                                                                                  
        def index                                                                                                                                                                                       
            @categories = Category.all                                                                                                                                                                  

            render :json => @categories, :callback => params[:callback]                                                                                                                                                                                                                                                                                                                                                                                                                                    
        end                                                                                                                                                                                             

        def restrict_access                                                                                                                                                                                                                                                                                                                                                                                         
                authenticate_or_request_with_http_token do |token, options|                                                                                                                             
                  ApiKey.exists?(access_token: token)                                                                                                                                                   
                end                                                                                                                                                                                                                                                                                                                                       
        end                                                                                                                                                                                                                                                                                                                                                                                                        
      end                                                                                                                                                                                                                                                                                                                                                                                                        
    end                                                                                                                                                                                                 
end                                                                                                                                                                                                         



class ApplicationController < ActionController::Base                                                                                                                                                        

  protect_from_forgery with: :exception                                                                                                                                                                     
  before_filter :cors_preflight_check                                                                                                                                                                       
  after_filter :cors_set_access_control_headers                                                                                                                                                             


    def cors_set_access_control_headers                                                                                                                                                                       
     headers['Access-Control-Allow-Origin'] = '*'                                                                                                                                                         
     headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'                                                                                                                          
     headers['Access-Control-Request-Method'] = '*'                                                                                                                                                       
     headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'                                                                                            
    end                                                                                                                                                                                                       

    def cors_preflight_check                                                                                                                                                                                  
       if request.method == "OPTIONS"                                                                                                                                                                         
         headers['Access-Control-Allow-Origin'] = '*'                                                                                                                                                        
         headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'                                                                                                                         
         headers['Access-Control-Request-Method'] = '*'                                                                                                                                                      
         headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'                                                                                           
         render :text => '', :content_type => 'text/plain'                                                                                                                                                   
       end                                                                                                                                                                                                    
     end                                                                                                                                                                                                      
  end                                                                                                                                                                                                         
MikeW
  • 4,599
  • 9
  • 38
  • 76

1 Answers1

1

This is some working code we use:

(function(token) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST","******",true);
    xmlhttp.setRequestHeader("Authorization", "Token " + token);
    xmlhttp.send();
})(tracker);

I figured your problem would be your beforeSend call, but it seems that's the recommended way to create an authentication token with $.ajax


Rack-CORS

You may have an issue with your CORS policy in your app

If you're not receiving the request in production, but are locally, then it's likely a CORS issue. By using the Rack-CORS gem, you'll be able to allow different request types to endpoints you specify

Here's the code we use:

config.middleware.use Rack::Cors do
  allow do
    origins '*'
    resource '/data*', :headers => :any, :methods => :post
  end
end
Community
  • 1
  • 1
Richard Peck
  • 73,250
  • 8
  • 84
  • 139
  • Hi Rich - thanks for the reply. I'll give your suggestion a try. So far I have tried to setup CORS as permissive as possible. Testing locally I get a 200 OK, but remotely is still 401. I used rails cast #352 to secure the controller - Let me know if there's anymore info you would like. I added the controller api code above. Cheers! – MikeW Mar 01 '14 at 12:50
  • Are you using rack-cors? – Richard Peck Mar 01 '14 at 12:52
  • I haven't heard of this one before - I'll read up on this gem – MikeW Mar 01 '14 at 12:55
  • 1
    Finally got it working thanks to your suggestion for Rack-cors (awesome gem). It appears that JSONP is only required x-domain if the server isn't configured to handle CORS properly.Thanks again! – MikeW Mar 01 '14 at 22:29