我正在本地测试一组云函数,并根据需要设置了数据库、Firestore、宿主、PubSub和函数的模拟器。我正在尝试做以下事情:
- 在
functions/index.js
文件中,我正在导入用作不同端点的HTTP触发器的模块 - 我使用依赖项注入(DI(来允许模块访问
functions/index.js
文件中的所有常见依赖项
到目前为止我在代码中的方法:
functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const cors = require('cors');
const session = require('express-session');
const firestoreSession = require('connect-session-firebase')(session);
const cookieParser = require('cookie-parser');
const { validationResult } = require('express-validator');
const ref = admin.initializeApp({
databaseURL: 'http://localhost:8080',
credential: admin.credential.cert('path/to/credential.js')
});
// services
const UserService = require('./user/index')({
express, cookieParser, cors, ref,
session, firestoreSession, validationResult
});
exports.user = functions.https.onRequest(UserService);
HTTP请求触发器是express的实例。我正在注入依赖项(如在UserService中(,然后在URL BASE_URL/user下公开触发器。很少有其他类似的服务。在UserService内部,我有以下内容:
module.exports = function({
express, cors,
session, firestoreSession,
cookieParser, validationResult, ref
}) {
const Validators = require('./validators');
const userserv = express();
userserv.use(cors({ origin: true }));
userserv.use(session({
name: 'user_session',
resave: true,
saveUninitialized: true,
secret: 'TOKEN_SECRET_HERE',
store: new firestoreSession({
database: ref.database()
})
}));
userserv.post('/login', (req, res, nxt) => {
res.json({
status: 200,
message: 'Logged In'
});
});
// ... other route handlers
return userserv;
};
函数/user/index.js
现在,当我启动模拟器时,一切都开始得很好。当我使用curl发送POST请求时,函数会冻结,直到超时为止。以下是卷曲请求的示例:
curl -X POST -H 'Content-Type:application/json' -d '{}' http://localhost:5001/<App>/<region>/user/login
当超时发生时,或者当我手动停止模拟器时,我会看到预期的JSON响应。不确定是什么原因导致函数冻结。我的猜测可能与会话存储的数据库设置有关,这会导致函数进入请求的无限循环。一些建议将不胜感激。
注意:我使用DI是因为我想在一个文件中管理导入,并在服务之间共享会话存储。我看到的设置firebase会话存储的方式使用admin.initializeApp
中的app-ref,因此,将其作为参数传递给所有导入的服务模块是很容易的。
更新1
问题肯定出在会话中间件上。在functions/user/index.js
中注释掉会话设置代码不会导致服务器在发出请求并按预期及时发送响应时冻结。
更新2查看调试日志后,这似乎是database-debug.log
:的"问题">
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/zerocool/.cache/firebase/emulators/firebase-database-emulator-v4.3.1.jar) to field sun.nio.ch.SelectorImpl.selectedKeys
WARNING: Please consider reporting this to the maintainers of io.netty.util.internal.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
我没有足够的声誉发表评论。
你把钥匙装好了吗?
const ref = firebase.initializeApp({
credential: firebase.credential.cert('path/to/serviceAccountCredentials.json'),
databaseURL: 'https://databaseName.firebaseio.com'
});
此外,尝试传递标志:resave和saveUninitialized
express()
.use(session({
store: new FirebaseStore({
database: ref.database()
}),
secret: 'keyboard cat'
resave: true,
saveUninitialized: true,
cookie: {maxAge : 60000,
secure: false,
httpOnly: false }
}));
检查安全性:
{
"rules": {
".read": "false",
".write": "false",
"sessions": {
".read": "false",
".write": "false"
},
"some_public_data": {
".read": "true",
".write": "auth !== null"
}
}
}
使用以下标志启动CORS:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if(req.session){
res.header("mytoken",req.token);
}
next();
});
编辑1:发送cors 内部的帖子
const cors = require('cors')({origin: true});
userserv.post('/login', (req, res) => {
cors(req, res, () => {
console.log('Sending POST inside CORS')
res.status(200).send({message: 'Logged In'})
});
});
好的,我终于能够运行这些函数,并获得预期的结果。正如原始帖子的更新中所指出的,问题在于connect-session-firebase
存储设置。对于本地设置,我尝试了以下操作:
// ... other code unchanged
const ref = admin.initializeApp({
// remove the following line
// databaseURL: 'http://localhost:8080',
credential: admin.credential.cert('path/to/credential.js')
});
此外,根据connect-session-firebase
的文档,我需要设置一个包含以下内容的.env
文件:
FIREBASE_DATBASE_URL=http://localhost:9090
FIREBASE_SERVICE_ACCOUNT=./serviceAccount.json
数据库运行正常,对sessions.json
文件的查询产生了预期的条目。在部署后也测试了这一点(为此,我不需要.env文件,必须将数据库URL更改为项目的实际数据库URL(。感谢大家的时间和帮助。