2

Cannot understand even if i delete all inside function and just print something still got this error, but when i use fastapi docs, and try signing with that, it work.

@auth_router.post('/signin')
async def sign_in(username: str = Form(...), password: str = Form(...)) -> dict:
    user = await authenticate_user(username, password)

    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, 
            detail='Invalid username or password',
        )

    user_obj = await User_Pydantic.from_tortoise_orm(user)
    user_token = await generate_token(user_obj)

    return {
        'access_token': user_token,
        'token_type': 'bearer',
    }

Before i use OAuth2PasswordRequestForm, when got 422 error, try another way.

my model is tortoise orm, and when need i convert it to pydantic model, in docs all is work.

JS

handleEvent(signinform, 'submit', e => {
    e.preventDefault();
    if(!isEmpty(signinform)){

        signInUsername = getElement('input[name="username"]', signinform).value;
        signInPassword = getElement('input[name="password"]', signinform).value;
        recaptchaV3 = getElement('[name="g-recaptcha-response"]').value;

        if(recaptchaV3){
            signInData = new FormData();
            signInData.append('username', signInUsername);
            signInData.append('password', signInPassword);

            isLogened = request('POST', '/signin', signInData);
            if(isLogened){
                log(isLogened);
            }
            
        } else{
            alert('Reload Page');
        }

    }

})

authenticate_user func

async def authenticate_user(username: str, password: str):
    user = await User.get(username=username)

    if not user or not user.verify_password(password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, 
            detail='Invalid username or password',
        )
    return user

My request function

const request = (method, url, data = null) => {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open(method, url, true)
        xhr.setRequestHeader('Content-Type', 'application/json')
        xhr.onerror = function () {
            console.log(xhr.response);
        };
        xhr.onload = () => {
        if (xhr.status === 200) {
            return resolve(JSON.parse(xhr.responseText || '{}'))
            } else {
                return reject(new Error(`Request failed with status ${xhr.status}`))
            }
        } 
        if (data) {
            xhr.send(JSON.stringify(data))
        } else {
            xhr.send()
        }


    })
}
  • The 422 error will have a body that explains which expected information is missing. 422 indicates that one of the required parameters to the FastAPI endpoint is missing (i.e. it doesn't match the expected input format). The message will tell you which field(s) is missing / in the wrong location. As possible explanation is that you're including a recaptcha value that your endpoint doesn't expect (and which wouldn't be expected if you used the docs). Not sure if that would result in a 422 error, though. – MatsLindh May 10 '21 at 11:13
  • @MatsLindh No, i try recaptcha is not raise error, and my body is empty, i update my question, add func how i send request – WhyIsThatHappening May 10 '21 at 11:26
  • You're sending your data as JSON, but you use `Form(...)` as the parameter - which implies regular urlencoded post params. – MatsLindh May 10 '21 at 12:00
  • Please have a look at [this answer](https://stackoverflow.com/a/70636163/17865804) – Chris Mar 14 '23 at 12:39

3 Answers3

5

Although you did not publish the error, who's purpose is to tell you the problem, I'm fairly sure the problem lies in the way you perform the request.

The line

xhr.setRequestHeader('Content-Type', 'application/json')

means that you are sending json data, which is not accepted by the authentication form of openapi. Also, you are stringifying the data into json which, again, is not an accepted format.

Thus, changing the content type to www-form-urlencoded and adding a FormData object to your request's body, will make it work.

You can see it in the github discussions below

https://github.com/tiangolo/fastapi/issues/2740 https://github.com/tiangolo/fastapi/issues/1431

lsabi
  • 3,641
  • 1
  • 14
  • 26
  • yeah problem was in it, sorry just blind copy js code, from one thing to another one, i remove that line and it work, i try set request header to what you suggest me, and also try use multipart/form-data and not work, but deleting that line is working idea! TNX A LOT SIR. – WhyIsThatHappening May 10 '21 at 13:01
0

Ensure that you have provided content type in your request,

xhr.setRequestHeader('Content-Type', 'application/json')

If it's there then verify the format of your input. Here, you have declared two varibales - signInUsername and signInPassword.

Important: You might provided a default value for these files in FastAPI. In that case, if you provided an empty content or null as the attribute values then the fastapi will throw the above error.

Ensure that the data that you are sending to the server is correct.

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
0

Try changing the content-type to:

content_type: application/x-www-form-urlencoded
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83