2

Okay i have been fighting with this for a few hours.

I manually return different status codes... if status is 200 it is successfull and completes.

but i have tried a lot of the 400 codes example: 400, 401, 403, 404 to get the error to trigger and never get it to work

when i pass anything besides status of 200 it will just reload page... but if status is 200 it will log in and alert complete too...

(function( $ ) {
  var Core = Core || {};
  Core = {
    init: function (){
    },
    api: {
      submit: function( ajax_url, ajax_data, callback ){
        var auth_token = '';
        if( Core.auth.isAuthenticated() ) {
          auth_token = Core.auth.authToken.get();
        }
        $.ajax({
          type: "GET",
          dataType: "jsonp",
          // test
          url: "http://192.168.1.65:3000/" + ajax_url,
          // live
          //url: "http://www.customsite.com/" + ajax_url,
          cache: false,
          //data: ajax_data,
          data: 'auth_token='+ auth_token + '&' + ajax_data,
          success: function(data) {
            if(typeof callback.onSuccess == 'function'){
              callback.onSuccess.call(this, data);
            }
          },
          error: function(data){
            if(typeof callback.onError == 'function'){
              callback.onError.call(this, data);
            }
          },
          complete: function(data){
            if(typeof callback.onComplete == 'function'){
              callback.onComplete.call(this, data);
            }
          }
        });
      }
    }
  };

  $( Core.init );
  window.Core = Core;
})(jQuery);

Form submit

authenticate: {
  onSubmit: function(form_obj) {
    var ajax_url = form_obj.attr('action'),
        ajax_data = form_obj.serialize();
    Core.api.submit( ajax_url, ajax_data,
      {
        onSuccess: Core.login.authenticate.onSuccess,
        onError: Core.login.authenticate.onError,
        onComplete: Core.login.authenticate.onComplete
      }
    );
  },

  onSuccess: function(data) {
    Core.auth.authToken.set(data.access_token, 30);
    window.location = 'index.html';
  },

  onError: function(data) {
      alert('ERROR');
  },


  onComplete: function(data) {
      alert('Complete');
  }
}

rails Application:

  def create
    resource = User.find_for_database_authentication(:email => params[:user][:email])
    if resource.valid_password?(params[:user][:password])
      resource.reset_authentication_token!
      render :json => {:access_token => resource.authentication_token, :token_type => "persistant"}, :callback => params[:callback], :status => 200
    else
      render :json => {:error => "invalid_grant"}, :callback => params[:callback], :status => 404
    end
  end
Big Al Ruby Newbie
  • 834
  • 1
  • 10
  • 30

1 Answers1

1

You are making a JSONP request, which is a form of cross domain "Ajax". Read What is JSONP all about? here on StackOverflow for how it works.

The short description: JSONP uses a <script src="your URL here"></script> tag to trigger the download of a JavaScript file. Since it is a regular SCRIPT element, any non 200 HTTP response triggers the "onerror" callback on that element in the browser. Your REST-like response from your Rails application is breaking the error handling on the browser. JSONP requests in jQuery have very limited error handling. If making a JSONP request, you always need to render a 200 OK response.

If you want REST-like responses, I would recommend wrapping your actual HTTP response with some additional JSON:

{
    "response": {
        "status": 401,
        "data": {
            ...
        }
    }
}

Then your success handler will have to intelligently parse out the response:

success: function(data) {
    if (data.response.status === 200 && callback.onSuccess) {
        callback.onSuccess.call(this, data.response.data);
    }
    else if (data.response.status >= 400 && callback.onError) {
        callback.onError.call(this, data.response.data.error);
    }

    if (callback.onComplete) {
        callback.onComplete.call(this, data.response.data);
    }
}


authenticate: {
  onSubmit: function(form_obj) {
    var ajax_url = form_obj.attr('action'),
        ajax_data = form_obj.serialize();
    Core.api.submit( ajax_url, ajax_data,
      {
        onSuccess: Core.login.authenticate.onSuccess,
        onError: Core.login.authenticate.onError,
        onComplete: Core.login.authenticate.onComplete
      }
    );
  },

  onSuccess: function(data) {
    Core.auth.authToken.set(data.access_token, 30);
    window.location = 'index.html';
  },

  onError: function(data) {
      alert(data);
  },

  onComplete: function(data) {
  }
}

Changes to your Rails controller:

def create
  resource = User.find_for_database_authentication(:email => params[:user][:email])

  if resource.valid_password?(params[:user][:password])
    resource.reset_authentication_token!

    render :json => {
      :response => {
        :status => 200,
        :data => {:access_token => resource.authentication_token, :token_type => "persistant"}
        }
      } 
    }, :callback => params[:callback]


  else
    render :json => {
      :response => {
        :status => 401,
        :data => {
          :error => "invalid_grant"
        }
      }
    }, :callback => params[:callback]
  end
end
Community
  • 1
  • 1
Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
  • I have changed the info as instructed and still can not get the alerts.. alert('ERROR'); – Big Al Ruby Newbie Dec 19 '14 at 15:10
  • in that documentation i found this in the error... so is it possible to alert the user that login creditials are incorrect... Note: This handler is not called for cross-domain script and cross-domain JSONP requests. – Big Al Ruby Newbie Dec 19 '14 at 15:15
  • Can you post your updated code, and which version of jQuery you are using? Are you getting a JavaScript error? – Greg Burghardt Dec 19 '14 at 15:46
  • No javascript errors showing. I am using PhoneGap and no errors... i can see the successuful call to server and when incorrect login it returns the 401 Unauthorized in the server log... but on the app i login it just stays on same page... no alert... if a successful login is attempted it logs in and does everything correctly – Big Al Ruby Newbie Dec 19 '14 at 15:48
  • Left everything the same except for changing the complete and error to what you suggested... get same results. using /*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ – Big Al Ruby Newbie Dec 19 '14 at 15:50
  • You'll need to start debugging this with the JavaScript debugger that comes with the browser you are using. If you have to use IE8, then you might be better off using Firefox or Chrome, because their dev tools are really good. – Greg Burghardt Dec 19 '14 at 15:53
  • Oh! I just realized this is a JSONP request!! – Greg Burghardt Dec 19 '14 at 15:54
  • Yeah it is JSONP Cross Domain. Building a mobile app. – Big Al Ruby Newbie Dec 19 '14 at 16:00
  • I completely rewrote my answer. – Greg Burghardt Dec 19 '14 at 16:02
  • Ok so how would you code he json response. I currently have render :json => {:error => "invalid_grant"}, :callback => params[:callback], :status => 401 – Big Al Ruby Newbie Dec 19 '14 at 16:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67340/discussion-between-greg-burghardt-and-big-al-ruby-newbie). – Greg Burghardt Dec 19 '14 at 16:10
  • callback inside JSON or not? you have it both ways – Big Al Ruby Newbie Dec 19 '14 at 16:18