Amazon Lambda для Firebase
Я получаю "Не могу найти модуль" firebase ", когда я пытаюсь запустить это в Lambda (Node.js 4.3)
var Firebase = require('firebase');
То же самое происходит, когда я пытаюсь загрузить ZIP-пакет, содержащий node_modules/firebase
Есть ли у кого-нибудь работающая запись из лямбда-в firebase?
Ответы
Ответ 1
Чтобы безопасно использовать пакет firebase npm (версия 3.3.0) в AWS Lambda (Nodejs 4.3), выполните следующие действия:
'use strict';
var firebase = require("firebase");
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false; //<---Important
var config = {
apiKey: "<<apikey>>",
authDomain: "<<app_id>>.firebaseapp.com",
databaseURL: "https://<<app_id>>.firebaseio.com",
storageBucket: "<<app_id>>.appspot.com",
};
if(firebase.apps.length == 0) { // <---Important!!! In lambda, it will cause double initialization.
firebase.initializeApp(config);
}
...
<Your Logic here...>
...
};
Ответ 2
Я решил свою проблему, используя firebase REST api
var https = require('https');
exports.handler = function(event, context, callback) {
var body = JSON.stringify({
foo: "bar"
})
var https = require('https');
var options = {
host: 'project-XXXXX.firebaseio.com',
port: 443,
path: '/.json',
method: 'POST'
};
var req = https.request(options, function(res) {
console.log(res.statusCode);
res.on('data', function(d) {
process.stdout.write(d);
});
});
req.end(body);
req.on('error', function(e) {
console.error(e);
});
callback(null, "some success message");
}
Ответ 3
Это уже поздно, но в случае, если кто-то ищет:
Замена папки проекта, а не содержимого папки проекта, может привести к этому. Закрепленная папка при извлечении не должна содержать папку с файлами лямбда в ней, но должна иметь файл index.js и папку node_modules на корневом уровне.
Рабочим примером лямбда-функции является (с использованием новейших блестящих вещей в виде бамбы * вздох *):
var firebase = require('firebase');
// Your service account details
var credentials = {
"type": "service_account",
"project_id": "project-123451234512345123",
"private_key_id": "my1private2key3id",
"private_key": "-----BEGIN PRIVATE KEY-----InsertKeyHere-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "1111222223333344444",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/projectname%40project-123451234512345123.iam.gserviceaccount.com"
};
firebase.initializeApp({
serviceAccount: credentials,
databaseURL: "https://project-123451234512345123.firebaseio.com"
});
exports.handler = function (event, context, callback) {
// I use some data passed in from AWS API Gateway:
if (!event.firebaseUid) {
callback('Missing param for id');
}
firebase.database().ref().child('users').child(firebaseUid).child('at').set(newTokens.access_token).then(function (data) {
console.log('Firebase data: ', data);
firebase.database().goOffline();
callback(null, 'Firebase data: ', data);
}).catch(function (error) {
callback('Database set error ' + error);
});
};
Теперь для оговорки. Я испытал это, заставив лямбда-функцию на время ожидания даже после того, как произошел обратный вызов firebase, т.е. функция набора, похоже, создает слушатель, который удерживает функцию лямбда открытой, несмотря на возвращение правильных данных.
Обновление: вызов firebase.database(). goOffline() исправляет ошибку тайм-аута функции лямбда, которую я испытывал.
Обычные предостережения о безопасности, которые не проверяются или не подходят, а также возможности остановки пространства и времени с помощью этого использования.
Ответ 4
Другой вариант, если вы используете установку разработки node, - это использовать пакет node-lambda
из здесь. По сути, он предоставляет обертки для настройки, тестирования и развертывания в лямбда. node-lambda deploy
упакует все установленные вами модули (например, с помощью npm i --save firebase
) и убедитесь, что они доступны на самой Lambda. Я нашел, что это действительно полезно для управления внешними модулями.
Ответ 5
2017-03-22 edit: google только что объявила firebase cloud functions, что намного лучший способ сделать это. Облачные функции работают так же, как лямбда, и могут запускаться из событий firebase.
Здесь мое решение с помощью REST api (так что вам не нужно ничего require
):
var https = require('https');
var firebaseHost = "yourapp.firebaseio.com";
function fbGet(key){
return new Promise((resolve, reject) => {
var options = {
hostname: firebaseHost,
port: 443,
path: key + ".json",
method: 'GET'
};
var req = https.request(options, function (res) {
res.setEncoding('utf8');
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve(JSON.parse(body))
});
});
req.end();
req.on('error', reject);
});
}
function fbPut(key, value){
return new Promise((resolve, reject) => {
var options = {
hostname: firebaseHost,
port: 443,
path: key + ".json",
method: 'PUT'
};
var req = https.request(options, function (res) {
console.log("request made")
res.setEncoding('utf8');
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve(body)
});
});
req.end(JSON.stringify(value));
req.on('error', reject);
});
}
Вы можете использовать его следующим образом:
fbPut("/foo/bar", "lol").then(res => {
console.log("wrote data")
})
И затем:
fbGet("/foo/bar").then(data => {
console.log(data); // prints "lol"
}).catch(e => {
console.log("error saving to firebase: ");
console.log(e);
})
Ответ 6
Для меня firebase-admin должен сделать трюк.
https://firebase.google.com/docs/admin/setup
Спасибо за Josiah Choi за предложение context.callbackWaitsForEmptyEventLoop. Поэтому lambda не нужно инициализировать Firebase каждый раз. Мой первый запуск был очень медленным.
var firebase = require('firebase-admin');
module.exports.Test = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false; //<---Important
if(firebase.apps.length == 0) { // <---Important!!! In lambda, it will cause double initialization.
firebase.initializeApp({
credential: firebase.credential.cert("serviceAccount.json"),
databaseURL: <YOUR FIREBASE URL>
});
}
firebase.database().ref('conversation').once('value').then(function(snapshot) {
console.log (snapshot.val()) ;
var bodyReturn = {
input: snapshot.val()
} ;
callback(null,bodyReturn);
context.succeed() ;
});
};
Ответ 7
Попробовав несколько вещей, это работает для меня (v 3.10.8):
for(var i=0;i<5;i++)
{
var firebase = require('firebase');
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
storageBucket: "",
messagingSenderId: ""
};
if(firebase.apps)
if(firebase.apps.length==0)
firebase.initializeApp(config)
firebase.database().ref().child("test").once('value').
then(function(snapshot) {
console.log(snapshot.val());
});
}