0

I have created a custom endpoint that returns select user meta data. I am trying to access this endpoint with Backbone. It works as expected in Postman and from my Backbone/javascript script If I have my access check dummied out.

var app2 ={};

app2.Pilot = Backbone.Model.extend({    
    url: POST_SUBMITTER.root + 'pilotdata/v1/pilot/'
 });

 app2.pilot = new app2.Pilot();

 app2.pilot.fetch(
   {data: ({ id: 1 })}
 ).then(function(){
    console.log(app2.pilot)
})      

Of course can't have the data hanging out naked. So I implement my access check and I get a status Unauthorized returned as expected. As the nonce is not being returned. But how to set the nonce? from theAverageDev I can up with:

    var app2 ={};

    app2.Pilot = Backbone.Model.extend({    
    url: POST_SUBMITTER.root + 'pilotdata/v1/pilot/',
    sync: function(){
        Backbone.sync('create', this,{
            beforeSend: function (xhr) {
                xhr.setRequestHeader('X-WP-NONCE', POST_SUBMITTER.nonce );
            },
        });
    },
 });

 app2.pilot = new app2.Pilot();

 app2.pilot.fetch(
   {data: ({ id: 1 })}
 ).then(function(){
    console.log(app2.pilot)
})      

And I admit I do not fully understand what that is doing. Overriding sync? However when I do that I get

TypeError: undefined is not an object (evaluating 'app2.pilot.fetch( {data: ({ id: 1 })}

It appears that overriding sync undefined fetch? What is the best way to use Backbone to pass the nonce?

I think I got it:

var app2 ={};

app2.Pilot = Backbone.Model.extend({    
    url: POST_SUBMITTER.root + 'pilotdata/v1/pilot/',
 });

 app2.pilot = new app2.Pilot();
 app2.pilot.fetch(
  { 
   beforeSend : function(xhr) {
     xhr.setRequestHeader('X-WP-NONCE', POST_SUBMITTER.nonce);
   },  
   data: ({id: 1})
   }
 ).then(function(){
    console.log(app2.pilot)
})    
  • I think I have found a partial solution if I change the code such – dsj Feb 8 at 2:04
  • Yes, but do try your original code with the modification as in my answer. It should work, unless your REST endpoint doesn't return a valid data.. :) Let me know! – Sally CJ Feb 8 at 3:06
1

From the documentation:

  1. Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server. By default, it uses jQuery.ajax to make a RESTful JSON request and returns a jqXHR.

  2. The sync function may be overridden globally as Backbone.sync, or at a finer-grained level, by adding a sync function to a Backbone collection or to an individual model.

So the code you initially have is actually good, but you should return the Backbone.sync() result like so:

app2.Pilot = Backbone.Model.extend({
  url: POST_SUBMITTER.root + 'pilotdata/v1/pilot/',
  sync: function( method, model, options ){
    return Backbone.sync(method, this, jQuery.extend( options, {
      beforeSend: function (xhr) {
        xhr.setRequestHeader( 'X-WP-NONCE', POST_SUBMITTER.nonce );
      },
    } ));
  },
});

Secondly, you should just pass the same method that Backbone passes to your model's custom sync() function, just as you can see above. And although you don't have to, I also use jQuery.extend() to extend the options object that's passed to that sync() function.

And with your other approach where you pass the header when you call your model's fetch() function, it does work, but extending the sync() function is much better since you don't need to specify the header for each request. :)

| improve this answer | |
  • 1
    Thank You, works great. So, JQuery.extend is merging the nonce header with 'other' options and then passing it to .sync? I tried not using $.extend and I can't get it to work. Nonce is passed, but I get a null object back. – dsj Feb 8 at 14:32
  • You're welcome, and yes, jQuery.extend() merges the options and they're passed to Backbone.sync(). And yes, sorry, the options need to be merged before they're passed to Backbone.sync(). But you don't have to use jQuery.extend() - you can use a native JS method like { ...options, new_item: 'value' } to extend the options object .. – Sally CJ Feb 8 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.