Angular调用FastAPI POST接口遇422错误:请求参数无法被后端识别
Angular调用FastAPI POST接口返回422错误的解决方法
在使用Angular的HttpClient.post调用FastAPI的POST登录接口时,后端无法接收请求参数,返回422 (Unprocessable Entity)错误,但Postman调用该接口完全正常。
后端FastAPI代码
from typing import Optional from pydantic import BaseModel class UsersLoginRequest(BaseModel): username: str password: str @users_router.post("/login") def login(body: UsersLoginRequest): pass
Postman正常调用示例(cURL)
curl --location --request POST 'http://127.0.0.1:3101/users/login' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --data-raw '{ "username": "admin", "password": "admin" }'
Postman调用后后端返回200 OK,说明接口本身逻辑正常。
错误的Angular写法及对应问题
写法一:将HttpParams作为请求体传递
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; constructor(private http: HttpClient) {} signIn(): void { const headers = new HttpHeaders(); headers.append('Content-Type', 'application/json'); let params = new HttpParams() .append('username', "admin") .append('password', "admin") this.http.post('http://127.0.0.1:3101/users/login', params, { headers: headers }) .subscribe({ error: (response: any) => {}, next: (response: any) => {} }) }
后端日志:
INFO: 127.0.0.1:62969 - "POST /users/login HTTP/1.1" 422 Unprocessable Entity
写法二:将参数放在params选项中
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; constructor(private http: HttpClient) {} signIn(): void { const headers = new HttpHeaders(); headers.append('Content-Type', 'application/json'); let params = new HttpParams() .append('username', "admin") .append('password', "admin") this.http.post('http://127.0.0.1:3101/users/login', null, { headers: headers, params: params }) .subscribe({ error: (response: any) => {}, next: (response: any) => {} }) }
后端日志同样返回422 Unprocessable Entity。
问题根源及正确写法
问题根源
- HttpHeaders的不可变性:
headers.append()不会修改原对象,而是返回新的Headers对象,原headers变量仍为空,导致请求没有正确携带Content-Type: application/json头。 - 参数传递方式错误:FastAPI的接口通过
BaseModel接收JSON请求体,但两种错误写法都没有传递正确的JSON请求体:- 写法一把
HttpParams(本质是URL查询参数格式)作为请求体发送,不符合JSON格式 - 写法二把参数放在
params选项中,这会将参数拼接在URL后面作为查询参数,而FastAPI接口是从请求体读取数据
- 写法一把
正确的Angular写法
import { HttpClient, HttpHeaders } from '@angular/common/http'; constructor(private http: HttpClient) {} signIn(): void { // 正确设置HttpHeaders:append后重新赋值 const headers = new HttpHeaders().append('Content-Type', 'application/json'); // 直接构造JSON格式的请求体 const body = { username: "admin", password: "admin" }; this.http.post('http://127.0.0.1:3101/users/login', body, { headers: headers }) .subscribe({ error: (response: any) => {}, next: (response: any) => {} }) }
简化写法(Angular默认会为JSON请求体添加Content-Type)
Angular的HttpClient.post在传递普通JavaScript对象作为请求体时,会自动设置Content-Type: application/json头,所以可以省略手动设置headers:
import { HttpClient } from '@angular/common/http'; constructor(private http: HttpClient) {} signIn(): void { const body = { username: "admin", password: "admin" }; this.http.post('http://127.0.0.1:3101/users/login', body) .subscribe({ error: (response: any) => {}, next: (response: any) => {} }) }
内容的提问来源于stack exchange,提问作者Abdulwahabdev
相关产品推荐
相关产品推荐

