在前端,我有以下JS函数:
export const uploadFormData = async (
token: string,
email: string,
formInfo: Array<Object>,
): Promise<any> => {
const formData = new FormData();
formData.append('email', email);
formData.append('form_info', JSON.stringify({ formInfo }));
return fetch(
`${process.env.ENDPOINT}/upload_form_data/`,
{
method: 'POST',
headers: {
Authorization: `Token ${token}`,
},
body: formData,
},
).then((response) => {
console.log(response.body?.getReader());
if (response.status === 404) {
throw Error('Url not found');
}
if (response.status === 422) {
throw Error('Wrong request format');
}
if (response.status !== 200) {
throw Error('Something went wrong with uploading the form data.');
}
const data = response.json();
return {
succes: true,
data,
};
}).catch((error) => Promise.reject(error));
};
向 FastAPI 后端中的以下端点发送
POST
请求:
@app.post("/api/queue/upload_form_data/")
async def upload_form_data(
email: str = Body(...),
form_info: str = Body(...),
authorization: str = Header(...),
):
return 'form data processing'
然而,它不断抛出以下错误:
在前端:
POST http://localhost:8000/api/queue/upload_form_data/ 422 (Unprocessable Entity)
Uncaught (in promise) Error: Wrong request format
在后端:
POST /api/queue/upload_form_data/ HTTP/1.1" 400 Bad Request
在 Swagger UI(响应主体)中:
{
"detail": [
{
"loc": [
"header",
"authorization"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
导致这些错误的请求有什么问题?
在 Swagger/OpenAPI 规范中,
Authorization
是一个保留标头——与 Accept
和 Content-Type
标头一样——用于 Swagger 的内置 authentication/authorization 功能(参见 Swagger 文档)。因此,它们不允许被定义。
如果您使用的是 Swagger,则不能在端点中定义
Authorization
标头参数并期望它起作用,因为在通过 Swagger UI 提交请求时它会被忽略,并且您会收到 422 Unprocessable Entity
错误正文消息说 authorization
标头正在缩小(就像您问题中发布的错误一样)。
如果您 不需要 需要 Swagger UI 来测试您的应用程序,您可以保持原样并继续使用 JavaScript Fetch API,在标头中传递
Authorization
。例如:
from fastapi import Header
@app.post('/')
def main(authorization: str = Header(...)):
return authorization
此外,请注意,您实际上不必在端点中定义任何
Header
参数,因为您始终可以通过 Request
对象直接访问它们,例如:
from fastapi import Request
@app.post('/')
def main(request: Request):
authorization = request.headers.get('Authorzation')
return authorization
如果您确实也需要它与 Swagger UI 一起使用,一种解决方案是使用 FastAPI 的
HTTPBearer
,这将允许您在 Swagger 中单击屏幕右上角的Authorize
按钮UI autodocs(位于/docs
),您可以在其中的Value
字段中键入您的API 密钥。这将在请求标头中设置 Authorization
标头。例子:
from fastapi import FastAPI, Depends
from fastapi.security import HTTPBearer
app = FastAPI()
security = HTTPBearer()
@app.get('/')
def main(authorization: str = Depends(security)):
return authorization.credentials
APIKeyHeader
.
from fastapi import FastAPI, Security
from fastapi.security.api_key import APIKeyHeader
app = FastAPI()
api_key_header = APIKeyHeader(name='Authorization')
@app.get('/')
def main(api_key: str = Security(api_key_header)):
return api_key
另一种解决方案是将
authorization
Header
参数重命名为其他名称,例如 token
。然后,在您的端点内,检查 API 密钥是否在 token
或 request.headers.get('Authorization')
参数中——如果两者都返回 None
,则这意味着没有提供令牌。例子:
from fastapi import FastAPI, Request, Header
from typing import Optional
app = FastAPI()
@app.get('/')
def main(request: Request, token: Optional[str] = Header(None)):
authorization = request.headers.get('Authorization')
return token if token else authorization