Firebase https 函数可以从客户端调用,因为函数调用是由客户端 SDK 提供的。
但是可以从服务器端调用它们吗?我找不到任何相关文档或问题/答案。具体来说,我使用的是 Next.js,我想在服务器端渲染期间调用 https 函数,并通过 props 将结果传递到客户端。
const token = await admin.credential.applicationDefault().getAccessToken();
const appCheckToken = await admin.appCheck().createToken(admin.app()?.options?.projectId as string);
const selfPolizeEmissionResponse = await axios.post(
'https://us-central1-{yourProjectId}.cloudfunctions.net/{yourCallableName}',
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
'X-Firebase-AppCheck': appCheckToken,
},
body: JSON.stringify({
data: {
// Your Data to be use by callable!
},
}),
}
);
axios。
previous threads,您最好构建一个可以使用 HTTP 客户端从后端调用的 HTTP 函数。这是由于从后端实现 HTTPS 可调用函数所需的身份验证时出现问题。这就是 Maciek Sawicki 提到的。
还值得一提的是,对于其他操作(例如使用 Firestore 或其他 Firebase 服务),可以使用Firebase Admin SDK。 Admin SDK 旨在从后端使用,并且具有不同的身份验证要求。如果您想查看可以使用哪些服务,请参考以下参考。
serverApp.ts
// enforces that this code can only be called on the server
// https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment
import "server-only";
import { headers } from "next/headers";
import { FirebaseServerApp, initializeServerApp } from "firebase/app";
import { firebaseConfig } from "./config";
import { connectAuthEmulator, getAuth as getAuthFirebase} from "firebase/auth";
import { connectFirestoreEmulator, getFirestore as getFirestoreFirebase} from "firebase/firestore";
import { connectFunctionsEmulator, getFunctions as getFunctionsFirebase } from "firebase/functions";
let firestoreEmulatorConnected = false;
let authEmulatorConnected = false;
let functionsEmulatorConnected = false;
export function getServerApp() {
const idToken = headers().get("Authorization")?.split("Bearer ")[1];
const firebaseServerApp = initializeServerApp(
firebaseConfig,
idToken
? {
authIdToken: idToken,
}
: {}
);
return firebaseServerApp;
}
export function getAuth(firebaseServerApp?: FirebaseServerApp) {
if (!firebaseServerApp) {
firebaseServerApp = getServerApp();
}
const auth = getAuthFirebase(firebaseServerApp);
if (process.env.NODE_ENV === 'development' && !authEmulatorConnected) {
console.log('Connecting to Auth emulator!');
connectAuthEmulator(auth, "http://localhost:9099");
authEmulatorConnected = true;
}
return auth;
}
export async function getCurrentUser(firebaseServerApp?: FirebaseServerApp) {
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return auth.currentUser;
}
export function getFirestore(firebaseServerApp?: FirebaseServerApp) {
if (!firebaseServerApp) {
firebaseServerApp = getServerApp();
}
const db = getFirestoreFirebase(firebaseServerApp);
if (process.env.NODE_ENV === 'development' && !firestoreEmulatorConnected) {
console.log('Connecting to Firestore emulator!');
connectFirestoreEmulator(db, '127.0.0.1', 8080);
firestoreEmulatorConnected = true;
}
return db;
}
export function getFunctions(firebaseServerApp?: FirebaseServerApp) {
if (!firebaseServerApp) {
firebaseServerApp = getServerApp();
}
const functions = getFunctionsFirebase(firebaseServerApp);
if (process.env.NODE_ENV === 'development' && !functionsEmulatorConnected) {
console.log('Connecting to Functions emulator!');
connectFunctionsEmulator(functions, '127.0.0.1', 5001);
functionsEmulatorConnected = true;
}
return functions;
}
然后在调用函数时使用 Functions 实例
import { Functions, httpsCallable } from "firebase/functions";
export async function testFunction(functions: Functions, input: string) {
const testFunction = httpsCallable<string, RetType>(functions, 'testFunction');
const response = await testFunction(input);
return response.data;
}
import { getFunctions } from "@/lib/firebase/serverApp";
const functions = getFunctions();
const result = await testFunction(code);
按照这种模式,我们可以在服务器端访问 Firebase 服务。