I keep getting the 422 Unprocessable Entity
error with the follwoing missing fields:
{"detail":[{"type":"missing","loc":["body","username"],"msg":"Field required","input":null},{"type":"missing","loc":["body","password"],"msg":"Field required","input":null}]}
I tried everything possible, but the error persists.
This is my frontend code:
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleLogin = async (e) => {
e.preventDefault();
const formData = new URLSearchParams();
formData.append('username', email); // Assuming the backend expects 'username'
formData.append('password', password);
try {
const response = await fetch('http://localhost:8000/token', {
method: 'POST',
body: formData,
});
if (!response.ok) {
throw new Error('Login failed');
}
and this is the backend:
@fastapi_router.post("/token", response_model=Token)
async def login_for_access_token(
username: Annotated[str, Form()],
password: Annotated[str, Form()],
db: AsyncSession = Depends(database.get_db)
):
user = await auth.authenticate_user(db, username, password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=envs.access_token_expire_minutes)
access_token = auth.create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
logger.info(f"Access Token: {access_token}")
return {"access_token": access_token, "token_type": "bearer"}
Any help would be appreciated.
Here is a working example on how to submit Form
data to a FastAPI backend using JavaScript Fetch API in the frontend. Related answers where you can read more on the methods used below could be found here, as well as here and here.
Note that when expecting username
and password
fields as form data, one could alternatively use the OAuth2PasswordRequestForm
dependency class offered by FastAPI. Related answers on that class can be seen here, as well as here, here and here.
app.py
from fastapi import FastAPI, Form, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.post("/submit")
async def submit(username: str = Form(...), password: str = Form(...)):
return {"username": username, "password": password}
@app.get("/", response_class=HTMLResponse)
async def main(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
templates/index.html
<!DOCTYPE html>
<html>
<body>
<input type="button" value="Submit" onclick="send()">
<p id="resp"></p>
<script>
function send() {
var resp = document.getElementById("resp");
var formData = new FormData();
formData.append("username", "test");
formData.append("password", "pass");
fetch('/submit', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(data => {
resp.innerHTML = JSON.stringify(data); // data is a JSON object
})
.catch(error => {
console.error(error);
});
}
</script>
</body>
</html>