FastAPI: как совместить хостинг приложения и статических файлов?
Вот я пишу "Hello world" с использованием FastAPI:
файл main.py, в котором написано
import uvicorn
from fastapi import FastAPI
app = FastAPI()
if __name__ == '__main__':
uvicorn.run("main:app", host='0.0.0.0', port=80, reload=True)
@app.get("/api")
async def root():
return {"message": "Hello World"}
Перед этим я установил зависимости
pip install fastapi
pip install uvicorn
Всё хорошо, я запускаю приложение python main.py
, и при заходе в браузер по url http://127.0.0.1/api
получаю заветный json {"message":"Hello World"}
Затем я добавляю хостинг статических файлов: создаю директорию static, кладу туда index.html с какой нибудь строчкой, и меняю свой python файл так:
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount('/', StaticFiles(directory='static',html=True))
if __name__ == '__main__':
uvicorn.run("main:app", host='0.0.0.0', port=80, reload=True)
@app.get("/api")
async def root():
return {"message": "Hello World"}
При этом у меня работает хостинг статического файла - по url http://127.0.0.1/
открывается index.html, но...
запрос по прежнему url http://127.0.0.1/api
работать перестаёт
Причем, если я поменяю строчку, задающую роутинг для статических файлов на
app.mount('/static/', StaticFiles(directory='static',html=True))
то оба запроса, и по http://127.0.0.1/static/
, и по http://127.0.0.1/api
- отработают правильно.
Кажется, что есть конфликт роутингов: роутинг по более короткому пути /
"перебивает" роутинг по пути /api
Как бы мне сделать, чтобы и index.html грузился, причем по "короткому" url http://127.0.0.1/
, и мой api по пути http://127.0.0.1/api
тоже работал?
Поясню: я хочу на основе FastAPI сделать такой "сайт для бедных": чтобы с него грузилась страница с JS-ом, который после загрузки начинает обращаться к api
Спасибо!
Ответы (1 шт):
Спасибо большое insolor и CrazyElf!
Вы указали что искать, и готовый ответ нашелся вот здесь: https://stackoverflow.com/questions/60716529/download-file-using-fastapi
Таким образом, вот первый работающий вариант того, что я хотел:
import uvicorn
from fastapi import FastAPI
from starlette.responses import FileResponse
app = FastAPI()
@app.get("/")
async def read_index():
return FileResponse('index.html')
@app.get("/api")
async def root():
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run("main:app", host='0.0.0.0', port=80, reload=True)
а вот - второй: (лично мне монтирование путей через mount нравится больше, чем через "магические атрибуты")
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
@app.get('/api')
def api_app():
return {"message": "Hello World"}
app.mount('/api', app)
app.mount('/', StaticFiles(directory='static',html=True))
if __name__ == '__main__':
uvicorn.run("main:app", host='0.0.0.0', port=80, reload=True)
Запуск: python main.py
Затем надо в браузере зайти на http://localhost/