1

I have a FastAPI server running at localhost:8000 and a react dev server running at localhost:3000. I have an endpoint set up as follows:

@router.post(
    name="Create User",
    tags=[Tags.Authentication],
    path='/create_user',
    status_code=200,
    response_model=SuccessfulUserAuthenticate
)
def create_user(
        user: UserInCreate = Body(
            title="User",
            description="User that will be created",
            default=Required,
            embed=True
        )
):
    pwd_context = CryptContext(schemes=['bcrypt'], deprecated="auto")
    new_user_object = User(
        user.first_name,
        user.last_name,
        user.email,
        pwd_context.hash(user.password),
        user.dob)
    with Session() as s:
        user_already_exists = True if s.query(User).where(User.email == user.email).first() else False
        if user_already_exists:
            raise EmailAlreadyExistsException()
        else:
            new_user_object.datetime_joined = datetime.utcnow()
            s.add(new_user_object)
            s.commit()
            return_user = SuccessfulUserAuthenticate(
                user.email,
                create_access_token(
                    data={
                        'user': user.email
                    }
                )
            )
            return return_user

Long story short, this function simply checks whether the email exists on the database. If it does, it raises an error which is handled by an exception handler which looks as such:

@app.exception_handler(EmailAlreadyExistsException)
def email_exists_exception_handler(request: Request, exc: EmailAlreadyExistsException):
    print('here')
    return JSONResponse(
        status_code=exc.status_code,
        content=jsonable_encoder({'detail': exc.description})
    )

If the email does not exist, it creates an account in the database. As you can see, I have a little debug statement which shows up in my terminal. The react frontend fetch function looks as such:

    const createUserSignUpSubmit = async () => {
        const response = await fetch('http://localhost:8000/authentication/create_user', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                "user": {
                "email": "user@example.com",
                "password": "string",
                "first_name": "string",
                "last_name": "string",
                "dob": "2019-08-24"
                }
                })
        })
        console.log(response.status)
        console.log(response.body)
        setFirstName('')
        setLastName('')
        setEmail('')
        setPassword('')
        setDate(new Date())
    }

When I submit this fetch request, I know that it reaches the endpoint because I can see the sql statements print out to the terminal and they look as follows:

2022-09-22 18:22:12,178 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-09-22 18:22:12,184 INFO sqlalchemy.engine.Engine SELECT user.id AS user_id, user.first_name AS user_first_name, user.last_name AS user_last_name, user.email AS user_email, user.password AS user_password, user.datetime_joined AS user_datetime_joined, user.date_of_birth AS user_date_of_birth 
FROM user 
WHERE user.email = %s 
 LIMIT %s
2022-09-22 18:22:12,184 INFO sqlalchemy.engine.Engine [generated in 0.00023s] ('user4@example.com', 1)
2022-09-22 18:22:12,191 INFO sqlalchemy.engine.Engine ROLLBACK
here

The "here" is printed from the exception handler. So everything flows as you would expect but it just wont return a response to my frontend. It does properly return a response to postman however. After much searching, I can't seem to figure out the issue. I've concluded that it isn't a CORS issue because I have the appropriate middleware set up as well as follows:

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

It seems as if the code is flowing just as I want it to, all the way until the final step where it actually has to send a response back to React. Any help would be greatly appreciated!

KrabbyPatty
  • 312
  • 1
  • 2
  • 9
  • The truth is, even if `return_user` is None, the body would simply be empty but I would at least receive a response status code. – KrabbyPatty Sep 23 '22 at 12:54
  • 1
    Please have a look at related answers [here](https://stackoverflow.com/a/71741617/17865804), [here](https://stackoverflow.com/a/73761724/17865804) and [here](https://stackoverflow.com/a/71805329/17865804). – Chris Sep 23 '22 at 12:57
  • 1
    Hey @Chris, I've realized what the problem was and have answered it below. Thank you so much for your help though :) – KrabbyPatty Sep 23 '22 at 13:10

1 Answers1

1

So after some debugging, I've realized that my mistake was that I forgot to call e.preventDefault() in the method that performs the fetch request. As a result of that, the page would reload and my API wouldn't have anywhere to send the response back to. It's working as intended now.

Chris
  • 18,724
  • 6
  • 46
  • 80
KrabbyPatty
  • 312
  • 1
  • 2
  • 9
  • 1
    To future readers: To add some context as to what OP is referring to, please have a look at [this answer](https://stackoverflow.com/a/73358937/17865804) and [this answer](https://stackoverflow.com/a/73359311/17865804). – Chris Sep 23 '22 at 14:05