Google Cloud Function 无法识别请求正文

问题描述 投票:0回答:1

我正在努力将我的一些 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'}
google-cloud-platform google-cloud-functions
1个回答
0
投票

你忘了这个

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)
© www.soinside.com 2019 - 2024. All rights reserved.