-1

Environment:

  • I am using typeahead/bloodhound for a search field in my mobile app (steroids/cordova)
  • Every request from my app to the API needs to be signed and the signature added to auth headers

Obviously setting the headers in the ajax settings won't work as each request bloodhound sends will be different and require different signatures.

In my first implementation, I was using the beforeSend ajax setting to achieve this. Simply calculate the signature in that function and add it to the request headers.

However, this was not very secure so I have decided to place the secret used and the signature calculation into a Cordova custom plugin's native code to be compiled. Not bullet proof but a reasonable amount of security.

As Cordova plugins are asynchronous, beforeSend became useless in this case. The function will complete before the signing and setting of the headers are done.

So, in summary, the question is: How can I asynchronously calculate and set those headers with typeahead/bloodhound?

Ozgur Susoy
  • 111
  • 9
  • [this is sort of a similar question](http://stackoverflow.com/questions/20453862/jquery-deferred-method-and-ajax-beforesend). although nothing useful offered by anyone there either. in my case, i am not particularly concerned about where a solution would be possible (ajax or bloodhound), just something that works would do. this would be so simple if beforeSend could just return a promise :/ – Ozgur Susoy Apr 27 '14 at 07:27
  • [another](http://stackoverflow.com/questions/13943196/how-to-properly-utilize-jquery-deferred-promise-on-auto-invoked-function-such-as). there is an accepted answer there but its about as hacky as it gets. i think i'd rather fork and hack bloodhound then put that workaround in my code :/ it also seems like this is impossible to do within ajax options so if typeahead support has no answers other than down voting, looks like this has to be a bloodhound hack. seriously regretting my decision to use typeahead/bloodhound. – Ozgur Susoy Apr 27 '14 at 08:11

1 Answers1

1

ok, the solution seems to be fork and hack. First modify _getFromRemote to remove the need for beforeSend by adding a remote.headers option similar to the remote.replace except that it returns a deferred object

if (this.remote.headers) {
    $.when(
        this.remote.headers(url, query, this.remote.ajax)
    ).done(function(headers) {
        that.remote.ajax.headers = headers;
        deferred.resolve(that.transport.get(url, that.remote.ajax, handleRemoteResponse));
     });
} else {
    deferred.resolve(this.transport.get(url, this.remote.ajax, handleRemoteResponse));
}

and then modify the get function that uses this to handle the deferred

if (matches.length < this.limit && this.transport) {
    cacheHitPromise = this._getFromRemote(query, returnRemoteMatches);
    cacheHitPromise.done(function(hit) {
        if (!hit) {
            (matches.length > 0 || !this.transport) && cb && cb(matches);
        }
     });
}

now I'm free to use asynchronous native code to sign and set request auth headers :)

Ozgur Susoy
  • 111
  • 9