[英]How to call an API from a different API in the same app in FastAPI?
(我确实在 SO 上找到了以下问题,但它对我没有帮助: 是否可以让 api 调用另一个 api,让它们都在同一个应用程序中? )
我正在使用具有以下文件夹结构的 Fastapi 制作应用程序
main.py
是应用程序的入口点
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)
在lines.py
中,我有 2 个 GET 端点:
/one-random-line
--> 从.txt
文件中返回随机行/one-random-line-backwards
--> 应该返回/one-random-line
的 output由于第二个 GET 端点的 output 应该是第一个 GET 端点的 output 的反转字符串,因此我尝试执行此处提到的以下步骤
代码:
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]}
当我这样做时,我收到以下错误:
TypeError: 'RedirectResponse' object is not subscriptable
当我将第二个 GET 端点的return
更改为return {'message': response}
时,我得到以下 output
我在做什么错误?
例子:
如果/one-random-line
端点的 output 是 'Maverick',那么/one-random-line-backwards
的 output 应该是 'kcirevam'
重构您的代码以将公共部分作为您调用的 function - 您通常将其放在 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],
}
您可以直接从代码中调用任何端点作为 function 调用,您不必处理RedirectResponse()
或任何东西。 下面是一个示例,说明它的外观并将按原样运行:
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/one-random-line")
async def get_one_random_line(request: Request):
# implement your own logic here, this will only return a static line
return {"line": "This is an example"}
@app.get("/one-random-line-backwards")
async def get_one_random_line_backwards(request: Request):
# You don't have to do fancy http stuff, just call your endpoint:
one_line = await get_one_random_line(request)
return {"line": one_line["line"][::-1]}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
使用curl
我们得到以下结果:
% curl localhost:8000/one-random-line
{"line":"This is an example"}%
% curl localhost:8000/one-random-line-backwards
{"line":"elpmaxe na si sihT"}%
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.