FastAPI中flask.request.url的等效写法——Google OAuth2迁移疑问
我正把Python Flask版的Google OAuth2示例迁移到FastAPI。原Flask代码里用flask.request.url获取完整的授权响应URL(示例:http://localhost:8080/oauth2callback?state=79aCVleeoxdA4bYgo5YnzuK8vsvM22&code=4%2F0AWtgzh611Sc3dhUo_pqQSa4RVTEZOgX9rJHc328XCJ4UmLvHdg5zz3t1k8VS3ihZwKMEA&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.labels+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=none),但在FastAPI里用request.url.path只能拿到路径/oauth2callback,有时甚至返回None,需要找到FastAPI中对应flask.request.url的写法。
原Flask代码片段:
def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. print("this is the flask request url -----------", flask.request.url) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials flask.session['credentials'] = credentials_to_dict(credentials) creds = google.oauth2.credentials.Credentials( **flask.session['credentials']) return flask.redirect(flask.url_for('test_api_request'))
在FastAPI中,要获取包含协议、域名、路径和查询参数的完整请求URL,直接将request.url转为字符串即可——str(request.url),这和Flask里的flask.request.url功能完全一致。
额外注意点:
- 不要使用
request.url.path,它仅返回URL的路径部分; - 确保路由函数已正确注入
Request对象(从fastapi导入); - 若需要反向生成外部URL(对应Flask的
url_for(_external=True)),FastAPI 0.100+版本可直接用url_for("oauth2callback", external=True),低版本可以通过str(request.base_url) + url_for("oauth2callback").path构建。
修改后的FastAPI代码示例:
from fastapi import FastAPI, Request from fastapi.responses import RedirectResponse import google_auth_oauthlib.flow from google.oauth2.credentials import Credentials from starlette.middleware.sessions import SessionMiddleware app = FastAPI() # 配置SessionMiddleware用于存储state和credentials,生产环境请更换为安全的密钥 app.add_middleware(SessionMiddleware, secret_key="your-secure-secret-key") CLIENT_SECRETS_FILE = "client_secret.json" SCOPES = [ "email", "profile", "openid", "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.modify", "https://www.googleapis.com/auth/gmail.labels" ] def credentials_to_dict(credentials): return { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes } @app.get("/oauth2callback") async def oauth2callback(request: Request): state = request.session.get('state') if not state: return RedirectResponse(url="/") flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) # 生成外部重定向URI flow.redirect_uri = url_for("oauth2callback", external=True) # 获取完整授权响应URL,对应flask.request.url authorization_response = str(request.url) print("this is the fastapi request url -----------", authorization_response) flow.fetch_token(authorization_response=authorization_response) credentials = flow.credentials request.session['credentials'] = credentials_to_dict(credentials) creds = Credentials(**request.session['credentials']) return RedirectResponse(url="/test_api_request")
内容的提问来源于stack exchange,提问作者ElayA

