Search code examples
pythonfastapihtmxstarlette

How to use HX-Redirect in HTMX frontend using FastAPI?


I'm trying to redirect on the frontend after a login. I make a request from my htmx frontend like this

<form hx-post="/authenticate" hx-target= "#success" id="login-form">

  <div id="success" class="mb-2"></div>

 </div>
.......input fields and submit button.....
</form>

My authenticate endpoint looks like this

@router.post("/authenticate", response_class=HTMLResponse)
async def authenticate(request: Request, response: Response, email: str = Form(), password: str = Form()):

    ..........
    #auth logic#
    ............
    response.headers["HX-Redirect"] = "http://127.0.0.1:8000/"
    data = {
        "success": "Logged in successfully"
    }
    return web_config.templates.TemplateResponse("auth_success.html", {"request": request, "data": data})

I know the code works because auth_success.html is successfully swapped on the frontend but what I expect to happen next is for the browser to redirect to the homepage(http://127.0.0.1:8000/), but it doesn't happen.

My CORS settings are all correct

        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
        expose_headers=["*"],

NOTE: Using RedirectResponse wouldn't work because of how HTMX(not HTML) works. It'll only call the endpoint and swap it's response into <div id="success"></div> which is not a redirect.


Solution

  • The reason for the redirection not taking place is due to the way you attempt adding the HX-Redirect header to the response. You are currently adding it to the Response object; however, since you are returning a TemplateResponse instead, the header is not added to the response you are actually returning. Hence, you should instead add the HX-Redirect header to the TemplateResponse, similar to the example below:

    @router.post('/authenticate', response_class=HTMLResponse)
    async def authenticate(request: Request, email: str = Form(), password: str = Form()):
        # ...
        
        data = {'msg': 'Logged in successfully'}
        response = templates.TemplateResponse('auth_success.html', {'request': request, 'data': data})
        response.headers['HX-Redirect'] = 'http://127.0.0.1:8000/'
        return response