(I did find the following question on SO, but it didn't help me: Is it possible to have an api call another api, having them both in same application?)
I am making an app using Fastapi with the following folder structure
main.py
is the entry point to the app
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1 import lines, upload
from app.core.config import settings
app = FastAPI(
title=settings.PROJECT_NAME,
version=0.1,
openapi_url=f'{settings.API_V1_STR}/openapi.json',
root_path=settings.ROOT_PATH
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.BACKEND_CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(upload.router, prefix=settings.API_V1_STR)
app.include_router(lines.router, prefix=settings.API_V1_STR)
In the lines.py
, I have 2 GET endpoints:
/one-random-line
--> returns a random line from a .txt
file/one-random-line-backwards
--> should return the output of the /one-random-line
Since the output of the second GET endpoint should be the reversed string of the output of the first GET endpoint, I tried doing the following steps mentioned here
The codes:
import random
from fastapi import APIRouter, Request
from starlette.responses import RedirectResponse
router = APIRouter(
prefix="/get-info",
tags=["Get Information"],
responses={
200: {'description': 'Success'},
400: {'description': 'Bad Request'},
403: {'description': 'Forbidden'},
500: {'description': 'Internal Server Error'}
}
)
@router.get('/one-random-line')
def get_one_random_line(request: Request):
lines = open('netflix_list.txt').read().splitlines()
if request.headers.get('accept') in ['application/json', 'application/xml']:
random_line = random.choice(lines)
else:
random_line = 'This is an example'
return {'line': random_line}
@router.get('/one-random-line-backwards')
def get_one_random_line_backwards():
url = router.url_path_for('get_one_random_line')
response = RedirectResponse(url=url)
return {'message': response[::-1]}
When I do this, I get the following error:
TypeError: 'RedirectResponse' object is not subscriptable
When I change the return
of the second GET endpoint to return {'message': response}
, I get the following output
What is the mistake I am doing?
Example:
If the output of /one-random-line
endpoint is 'Maverick', then the output of /one-random-line-backwards
should be 'kcirevam'
Refactor your code to have the common part as a function you call - you'd usually have this in a module external to your controller.
# this function could live as LineService.get_random_line for example
# its responsibility is to fetch a random line from a file
def get_random_line(path="netflix_list.txt"):
lines = open(path).read().splitlines()
return random.choice(lines)
# this function encodes the rule that "if the accepted response is json or xml
# we do the random value, otherwise we return a default value"
def get_random_or_default_line_for_accept_value(accept, path="netflix_list.txt", default_value="This is an example"):
if accept not in ("application/json", "application/xml"):
return default_value
return get_random_line(path=path)
@router.get('/one-random-line')
def get_one_random_line(request: Request):
return {
"line": get_random_or_default_line_for_accept_value(
accept=request.headers.get('accept'),
),
}
@router.get('/one-random-line-backwards')
def get_one_random_line_backwards(request: Request):
return {
"line": get_random_or_default_line_for_accept_value(
accept=request.headers.get('accept'),
)[::-1],
}