I am using Firebase
database for my android application. I am using cloud functions feature of it. I have coded functions and trying to test it on local machine.
I am running this command to test it, cloud functions works well on firebase server not on localhost. Below commands sends an error
firebase serve --only functions
> firebase serve --only functions
=== Serving from 'D:\Firebase'...
i functions: Preparing to emulate HTTPS functions. Support for other event types coming soon.
Warning: You're using Node.js v7.10.0 but Google Cloud Functions only supports v6.11.1.
Server#addProtoService is deprecated. Use addService instead
+ functions: getUsers: http://localhost:5002/xyz/us-central1/getUsers
info: User function triggered, starting execution
info: Execution took 60022 ms, finished with status: 'timeout'
info: Execution took 60022 ms, finished with status: 'crash'
Error: Can't set headers after they are sent.
at ServerResponse.setHeader (_http_outgoing.js:371:11)
at ServerResponse.header (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:730:10)
at ServerResponse.send (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:256:15)
at ProxyServer.Supervisor._proxy.on (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\@google-cloud\functions-emulator\src\supervisor\supervisor.js:97:12)
at ProxyServer.emit (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\eventemitter3\index.js:144:27)
at ClientRequest.proxyError (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\http-proxy\lib\http-proxy\passes\web-incoming.js:156:18)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:191:7)
at Socket.socketErrorListener (_http_client.js:358:9)
info: Execution took 60054 ms, finished with status: 'crash'
Error: Can't set headers after they are sent.
at ServerResponse.setHeader (_http_outgoing.js:371:11)
at ServerResponse.header (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:730:10)
at ServerResponse.send (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\response.js:256:15)
at ProxyServer.Supervisor._proxy.on (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\@google-cloud\functions-emulator\src\supervisor\supervisor.js:97:12)
at ProxyServer.emit (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\eventemitter3\index.js:144:27)
at ClientRequest.proxyError (C:\Users\williams\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\http-proxy\lib\http-proxy\passes\web-incoming.js:156:18)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:191:7)
at Socket.socketCloseListener (_http_client.js:334:9)
Code:
exports.getUsers = functions.https.onRequest((request, response) => {
var x = [],
similarityCount;
db
.ref("/users/" + request.query.userId)
.once("value")
.then(function(snapshot) {
var jsonObject = snapshot.val();
var basicProfileJsonObject = jsonObject.basicProfile;
for (var key in basicProfileJsonObject) {
if (utils.isNumber(basicProfileJsonObject[key])) {
x.push(basicProfileJsonObject[key]);
}
}
db.ref("/users/").once("value").then(function(snapshot) {
var y = [];
var jsonResponse = [];
snapshot.forEach(function(item) {
var user = item.val();
let userId = user.basicProfile.userId;
if (userId !== request.query.userId) {
var basicProfileJsonObject = user.basicProfile;
for (var key in basicProfileJsonObject) {
if (utils.isNumber(basicProfileJsonObject[key])) {
y.push(basicProfileJsonObject[key]);
}
}
if (request.query.algo === "cosine") {
// compute cosine value
similarityCount = cosineUtils.cosineSimilarity(x, y);
} else if (request.query.algo == "euclidean") {
// compute euclidean distance value
similarityCount = 1 / (1 + euclidean(x, y));
} else if (request.query.algo === "pearson-correlation") {
// compute pearson correlation coefficents
similarityCount = pcorr.pearsonCorrelation(x, y);
}
console.log("------------------------------------");
console.log(x);
console.log("------------------------------------");
console.log("------------------------------------");
console.log(y);
console.log("------------------------------------");
console.log("------------------------------------");
console.log(similarityCount);
console.log("------------------------------------");
jsonResponse.push(item.val());
y = [];
}
});
response.send(jsonResponse);
});
});
});
Can anyone help me what is going wrong ?
The error "Error: Can't set headers after they are sent." means that you're already in the Body or Finished state, but some function tried to set a header or statusCode. When you see this error, try to look for anything that tries to send a header after some of the body has already been written.
You can connect an HTTP function to Firebase Hosting. Requests on your Firebase Hosting site can be proxied to specific HTTP functions. This also allows you to use your own custom domain with an HTTP function.
This is definitely a tricky case. I think there's a complicated error case happening here and the error message is sub-par. Notice that there are two lines that say "Execution took 60022 ms, finished with status: X". My wild guess here is that the Cloud Function timed out (which then sends a response) but your code continued to run in the background. Eventually it tried to send the real response, but the response had already been sent and Express.js threw an exception.
As an aside, this Cloud Function is trying to load every single user in your application during the limit of an HTTP request. No matter how fast Cloud Functions or the Firebase Realtime Database gets, you're going to hit a limit if you try to fit a O(N) operation in a constant timeout. Is it possible to make your HTTP function calculate the similarity between two users? Or to proactively calculate and invalidate users' similarities in the background and return cached values in your HTTP function?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With