Alright, I am trying to serve an apk file using node.js upon successful authentication of a get request. For this purpose I am using an api call of the form:
GET /apk/?username=user&token=a_token_goes_here
Note that the actual authentication is performed by sending the credentials on the header of the request (say a username and password appear there). Authentication succeeds, and when I also verify that the personalized token of the user is correct it is time for me to actually serve the file back to the client. For the sake of simplicity the critical part of the code for the handler looks like this:
Peer.find({"username": request.credentials.peer.username}).exec(function (dbError, results) {
if (dbError) {
// handle error
}
if (results[0]._id.toString() === request.query.token) {
var absolutePath = THE_ACTUAL_PATH_TO_THE_APK_NOT_UNDER_PUBLIC;
var stat = fs.statSync(absolutePath);
response.writeHead(200, {
'Content-Type': 'application/vnd.android.package-archive',
'Content-Length': stat.size
});
var readStream = fs.createReadStream(absolutePath);
readStream.pipe(response);
return callback (null);
} else {
// error handling ...
}
}
I can see on the server console that the error code 200 is returned. However, on the client side, it feels as if the ajax call never ended. This is so because I disable the button for the ajax call right before the call, and I am going to activate the button again right after the end of the call. Moreover, I have print statements on the browser console that are not printed. Actually some of the statements are printed but perhaps 2 whole minutes later and then again, not everything. For the purposes of testing I have a text file with the contents
Here is your APK!
that I serve as the apk. Can someone point me what I am doing wrong? Most likely I should serve the file using a different function? How can we force the client to save the file that we ultimately want to serve from a url like the one above?
Here, there is a secondary issue (most likely naive): What happens if the client that is trying to download the file does so using a very crappy connection? Does this mean that the solution code on node.js is blocking all other incoming calls until the guy with the low bandwidth connection finishes his/her download of the apk? (I hope not and it is somehow returned as chunks or something)
Addition of the ajax call
$.ajax({
type: "GET",
url: theURL,
accepts: "application/vnd.android.package-archive",
beforeSend : function(xhr) {
xhr.withCredentials = true;
xhr.setRequestHeader("Authorization", "Basic " + mem.apk.username + ":" + mem.apk.password);
xhr.setRequestHeader("APP_KEY", mem.component.appKey);
xhr.setRequestHeader("APP_SECRET", mem.component.appSecret);
},
async: true,
contentType: "application/vnd.android.package-archive",
success: function(data, textStatus, jqXHR) {
var response = data;
console.log ("Data follows:");
console.log (data);
console.log ("Data ended");
},
error: function (data, textStatus, errorThrown) {
var response = JSON.parse(data.responseText);
console.log (JSON.stringify(response));
alert(response.message);
},
crossDomain: true,
username: mem.apk.username,
password: mem.apk.password
}).done(function() {}).fail(function() {}).always(function() {
$('#apkButton').prop("disabled",false);
});