Firebase托管应用调用Python云函数:on_call失败及认证方案咨询
Firebase云函数调用问题:on_call报错与on_request认证实现
问题背景
从Firebase托管应用调用Python编写的Firebase云函数时,@https_fn.on_request()装饰的函数可通过fetch正常调用,但@https_fn.on_call()装饰的函数调用报错,同时需要为on_request函数实现认证功能。
代码示例
Python云函数(函数名:function-hw,入口:say_hello)
import functions_framework from firebase_functions import https_fn, options from firebase_admin import auth, initialize_app from datetime import datetime # 需初始化Firebase Admin initialize_app() @https_fn.on_call( cors=options.CorsOptions( cors_origins=[r"https://jr\.mysite\.app$"], cors_methods=["get", "post"], ) ) def say_hello(req: https_fn.Request) -> https_fn.Response: print(req.__dict__) return { "Hello": "World!", "Time": "CORS!", "Now": datetime.now() }
JS调用代码
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.8.0/firebase-app.js"; import { getAuth } from "https://www.gstatic.com/firebasejs/10.8.0/firebase-auth.js"; import { getFunctions, httpsCallable } from "https://www.gstatic.com/firebasejs/10.8.0/firebase-functions.js"; const firebaseConfig = { apiKey: "...", authDomain: "...", projectId: "...", storageBucket: "...", messagingSenderId: "...", appId: "...", measurementId: "..." }; const firebaseApp = initializeApp(firebaseConfig); const auth = getAuth(firebaseApp); const functions = getFunctions(firebaseApp); var callFunction = httpsCallable('function-hw'); // 此处存在错误 callFunction() .then(function(result) { console.log(result.data); }) .catch(function(error) { console.error('Error:', error); }); async function requestFunction() { const fcnUrl = "url for firebase function with on_request decorator"; const response = await fetch(fcnUrl); const data = await response.json(); console.log(data); } requestFunction()
报错信息
on_call调用时报错:
service.ts:185 Uncaught TypeError: e._url is not a function at call (service.ts:185:59) at service.ts:215:3 at index.js:37:1
问题解答
1. on_call云函数的使用错误
存在两处关键错误:
- JS调用参数缺失:
httpsCallable方法必须传入functions实例作为第一个参数,正确写法为:const callFunction = httpsCallable(functions, 'function-hw'); - Python函数参数类型错误:
@https_fn.on_call装饰的函数,接收的参数应为https_fn.CallableRequest而非https_fn.Request,且直接返回字典即可(无需https_fn.Response)。修正后的Python函数:@https_fn.on_call( cors=options.CorsOptions( cors_origins=[r"https://jr\.mysite\.app$"], cors_methods=["get", "post"], ) ) def say_hello(req: https_fn.CallableRequest) -> dict: # 可直接通过req.auth获取认证用户信息 if req.auth: print(f"Authenticated user: {req.auth.uid}") return { "Hello": "World!", "Time": "CORS!", "Now": datetime.now().isoformat() }
2. on_request中实现认证
通过以下步骤实现Bearer Token认证:
前端修改:传递ID Token
在fetch请求中添加Authorization头,携带用户的ID Token:
async function requestFunction() { const fcnUrl = "url for firebase function with on_request decorator"; const user = auth.currentUser; if (user) { const idToken = await user.getIdToken(); const response = await fetch(fcnUrl, { headers: { 'Authorization': `Bearer ${idToken}` } }); const data = await response.json(); console.log(data); } else { console.log("No user logged in"); } }
后端修改:验证Token
在on_request函数中提取并验证Token,获取用户信息:
@https_fn.on_request( cors=options.CorsOptions( cors_origins=[r"https://jr\.mysite\.app$"], cors_methods=["get", "post"], ) ) def say_hello(req: https_fn.Request) -> https_fn.Response: # 提取Authorization头 auth_header = req.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return https_fn.Response("Unauthorized", status=401) id_token = auth_header.split('Bearer ')[1] try: # 验证ID Token decoded_token = auth.verify_id_token(id_token) uid = decoded_token['uid'] print(f"Authenticated user UID: {uid}") return https_fn.Response({ "Hello": "Authenticated World!", "UserUID": uid, "Now": datetime.now().isoformat() }, status=200) except auth.InvalidIdTokenError: return https_fn.Response("Invalid token", status=401) except Exception as e: return https_fn.Response(f"Error: {str(e)}", status=500)
内容的提问来源于stack exchange,提问作者John Robinson
相关产品推荐
相关产品推荐

