How to add body content in FastAPI's RedirectResponse?
Asked Answered
G

1

1

I would like to use an audio file inside the /check_base endpoint. However, I can't send the file in the body of FastAPI's RedirectResponse. The /check endpoint returns a RedirectResponse, which only accepts a URL parameter. Please help me on this.

Here is my code:

@router.post("/check")
async def check(
    request: Request
):
   file = StarletteUploadFile(filename="/home/hello.wav")
   redirect_url = app.url_path_for("check_base", **{'audio':file)

   response = RedirectResponse(url=redirect_url)
   return response


@router.post("/check_base")
async def check_base(
    request: Request,
    audio: UploadFile = File(...)
):
Glucinum answered 2/11, 2022 at 14:23 Comment(1)
Be aware that 307 redirect should retry the request on the new URL, i.e. it's meant to tell the client to do the exact thing again. A 307 redirect response effectively says "Look here instead" - including a relevant body with the actual content in that case might confuse clients and be hard to reason about in the future (it's unexpected behavior). What is the case for not returning a 200 OK response to indicate that the content is actually what the client asked for?Firecure
W
0

URL redirection in the HTTP protocol is basically a header, i.e., the Location response header, indicating the URL to redirect a page to (see here and here for more details). That being said, it does not prevent one to provide a body in the redirect response as well. Since FastAPI/Starlette's RedirectResponse does not provide the relevant content parameter, which would allow you to define the response body, you could instead return a custom Response directly with a 3xx (redirection) status code and the Location header holding the URL to redirect to. If you want the redirected request to reuse the method (e.g., POST) and the body of the original request, then you could use 307 Temporary Redirect status response code (the relevant Starlette implementation of all status codes can be found here).

Working Example:

app.py

from fastapi import FastAPI, Request, Response, Form, status
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory='templates')
 
@app.post('/submitFinal')
def final(msg: str = Form(...)):
    return f'You reached your destination. The msg is {msg}'
    
@app.post('/submit')
def redirect(msg: str = Form(...)):
    headers = {'Location': '/submitFinal'}
    return Response(content=msg, headers=headers, status_code=status.HTTP_307_TEMPORARY_REDIRECT)

@app.get('/')
def index(request: Request):
    return templates.TemplateResponse('index.html', {'request': request})

templates/index.html

<!DOCTYPE html>
<html>
   <head>
      <script>
         document.addEventListener('DOMContentLoaded', (event) => {
            document.getElementById("myForm").addEventListener("submit", function (e) {
              e.preventDefault() // Cancel the default action
              var formElement = document.getElementById('myForm');
              var data = new FormData(formElement);
              fetch('/submit', {
                    method: 'POST',
                    body: data
                 })
                 .then(resp => resp.text()) // or, resp.json(), etc.
                 .then(data => {
                    document.getElementById("responseArea").innerHTML = data;
                 })
                 .catch(error => {
                    console.error(error);
                 });
            });
         });
      </script>
   </head>
   <body>
      <h1>Send a message</h1>
      <form id="myForm">
         Message : <input type="text" name="msg" value="foo">
         <input class="submit" type="submit" value="Submit">
      </form>
      <div id="responseArea"></div>
   </body>
</html>
Wallin answered 2/11, 2022 at 16:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.