Starlette代码仅支持GET请求,需改为POST请求的技术咨询
解决方案:无需重写,仅需简单修改即可支持POST请求
你只需要对现有代码做两处关键修改,就能适配POST请求场景,完全不需要重写:
1. 给路由指定允许的HTTP方法
Starlette的Route默认仅接受GET请求,必须显式声明支持POST方法:
routes = [ Route("/testpath", endpoint=homepage, methods=["POST"]) ]
2. 修复响应构造的错误
原代码中JSONResponse的参数顺序错误,你把请求体body放在了第二个参数位置(该位置应为状态码等可选参数),需要调整响应数据的构造方式:
async def homepage(request): if request.user.is_authenticated: body = await request.json() # 将请求体整合到响应数据中,或根据业务需求处理 return JSONResponse({ "user": my_user, "password": my_pass, "header": request.headers.get('client_id'), "request_body": body }) return PlainTextResponse('Hello, you')
额外优化建议:避免使用全局变量
原代码用my_user和my_pass全局变量存储用户信息是线程不安全的,并发请求下会出现数据混乱。建议将用户信息存入request.state:
# 在BasicAuthBackend的authenticate方法中修改 async def authenticate(self, conn): # ... 原有代码 ... username, _, password = decoded.partition(":") # 存入request.state而非全局变量 conn.state.username = username conn.state.password = password return AuthCredentials(["authenticated"]), SimpleUser(username)
然后在视图函数中从request.state读取:
async def homepage(request): if request.user.is_authenticated: body = await request.json() return JSONResponse({ "user": request.state.username, "password": request.state.password, "header": request.headers.get('client_id'), "request_body": body }) return PlainTextResponse('Hello, you')
修改后的完整代码
from starlette.applications import Starlette from starlette.authentication import ( AuthCredentials, AuthenticationBackend, AuthenticationError, SimpleUser ) from starlette.middleware import Middleware from starlette.middleware.authentication import AuthenticationMiddleware from starlette.responses import (PlainTextResponse, JSONResponse) from starlette.routing import Route import base64 import binascii class BasicAuthBackend(AuthenticationBackend): async def authenticate(self, conn): if "Authorization" not in conn.headers: return auth = conn.headers["Authorization"] try: scheme, credentials = auth.split() if scheme.lower() != 'basic': return decoded = base64.b64decode(credentials).decode("ascii") except (ValueError, UnicodeDecodeError, binascii.Error) as exc: raise AuthenticationError('Invalid basic auth credentials') username, _, password = decoded.partition(":") conn.state.username = username conn.state.password = password # TODO: 此处需添加用户名密码的实际验证逻辑 return AuthCredentials(["authenticated"]), SimpleUser(username) async def homepage(request): if request.user.is_authenticated: body = await request.json() return JSONResponse({ "user": request.state.username, "password": request.state.password, "header": request.headers.get('client_id'), "request_body": body }) return PlainTextResponse('Hello, you') routes = [ Route("/testpath", endpoint=homepage, methods=["POST"]) ] middleware = [ Middleware(AuthenticationMiddleware, backend=BasicAuthBackend()) ] app = Starlette(debug=True, routes=routes, middleware=middleware)
内容的提问来源于stack exchange,提问作者Nick Ellson
相关产品推荐
相关产品推荐

