我正在努力将我的一些 Google Cloud Run 函数迁移到无服务器 Google Cloud Functions。
我一整天都在尝试调试这个问题,但感觉没有取得任何进展。
我在日志中看到的错误是:
request_body = request.body()
^^^^^^^^^^^^
AttributeError: 'Request' object has no attribute 'body'
这些函数最初被编写为异步函数,但 Google Cloud Functions 似乎不适用于异步函数。 我已将函数更新为同步,但出现上面的错误。
import functions_framework
from fastapi import FastAPI, Request, HTTPException, APIRouter, Response, Body
from fastapi.middleware.cors import CORSMiddleware
from firebase_admin import credentials, auth, exceptions
from firebase_admin import storage
from firebase_admin import firestore
from google.cloud.firestore import FieldFilter
from pydantic import BaseModel
import json
app = FastAPI()
origins = [
"http://localhost",
"http://localhost:3000",
"http://localhost:3001",
"http://localhost:8000",
"http://fir-integrationyay.web.app",
"http://fir-integrationyay.firebaseapp.com"
"https://localhost",
"https://localhost:3000",
"https://localhost:3001",
"https://localhost:8000",
"https://fir-integrationyay.web.app",
"https://fir-integrationyay.firebaseapp.com"
# Add any other allowed origins if needed
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class SessionLoginRequest(BaseModel):
idToken: str
@app.post('/')
def session_login(request: Request):
print('test', request)
try:
request_body = request.body()
request_data = json.loads(request_body)
id_token = request_data.get('idToken')
if not id_token:
raise HTTPException(status_code=400, detail='idToken is required')
decoded_claims = auth.verify_id_token(id_token)
if time.time() - decoded_claims['exp'] < 5 * 60:
expires_in = timedelta(days=10)
session_cookie = auth.create_session_cookie(id_token, expires_in=expires_in)
email = decoded_claims['email']
uid = decoded_claims['uid']
# Get a reference to the Firestore database
db = firestore.client()
# Query the user document by user_id
user_ref = db.collection("customers").where(filter=FieldFilter("user_id", "==", uid))
user_docs = user_ref.get()
if user_docs:
user_doc = user_docs[0]
user_data = user_doc.to_dict()
else:
# If user document doesn't exist, create it with initial credits
new_user_data = {
'email': email,
'user_id': uid,
'credits': 50,
'current_subscription_tier': 'Free'
}
db.collection("customers").add(new_user_data)
user_data = new_user_data
response = JSONResponse({'status': 'success', 'user_data': user_data})
response.set_cookie(
'session', session_cookie, expires=expires_in, max_age=10*24*60*60, path="/", samesite='None', secure=True, httponly=True)
return json.dumps(response)
else:
raise HTTPException(status_code=401, detail='Recent sign in required')
except auth.InvalidIdTokenError:
raise HTTPException(status_code=401, detail='Invalid ID token')
except exceptions.FirebaseError:
raise HTTPException(status_code=401, detail='Failed to create a session cookie')
我的顶部打印语句记录“测试”,然后什么都没有,所以看起来我实际上没有收到请求。
在前端,我像往常一样发送请求:
const handleAuthStateChange = async (user) => {
if (user) {
const initial = user.displayName?.charAt(0)?.toUpperCase() || "";
setIsAuthenticated(true);
const newUserData = {
...user,
displayName: user.displayName,
initial: initial,
};
setUserData(newUserData);
localStorage.setItem("userData", JSON.stringify(newUserData));
try {
const idToken = await user.getIdToken(true);
console.log("idToken", idToken);
const response = await axios.post(
`${process.env.REACT_APP_API_URL}/session-login`,
{ idToken },
{
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
withCredentials: true,
}
);
我正在添加一条语句
print(dict(request.headers))
,其中记录:
{'Host': 'us-central1-fir-integrationyay.cloudfunctions.net', 'Accept': '*/*', 'Access-Control-Request-Method': 'POST', 'Access-Control-Request-Headers': 'content-type', 'Origin': 'http://localhost:3000', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'cross-site', 'Sec-Fetch-Dest': 'empty', 'Referer': 'http://localhost:3000/', 'Accept-Language': 'en-US,en;q=0.9', 'Priority': 'u=1, i', 'X-Cloud-Trace-Context': '6dc6c37b8477dde3848d3d22c6989694/10885890348088290753;o=1', 'Early-Data': '1', 'Traceparent': '00-6dc6c37b8477dde3848d3d22c6989694-971273987da7edc1-01', 'X-Forwarded-For': '69.180.179.235', 'X-Forwarded-Proto': 'https', 'Forwarded': 'for="69.180.179.235";proto=https', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Content-Length': '0', 'Function-Execution-Id': 'WB6pFXqImVPD'}
你忘了这个
from functions_framework import create_app
# Wrap the FastAPI app with the Functions Framework app
ff_app = create_app(app)
# The entry point for GCP Functions Framework
def http(request):
return ff_app(request)