W.P. McNeill
W.P. McNeill

Reputation: 17056

Minimal FastAPI Static File Server Script

I want to write a minimal FastAPI static file server launched from a script that allows you to specify the directory to share on the command line. Following the example in the FastAPI documentation, I wrote this.

import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

server = FastAPI()

if __name__ == "__main__":
    import sys

    directory = sys.argv[1]
    server.mount("/static", StaticFiles(directory=directory), name="static")
    uvicorn.run(app="my_package:server")

If I run this with the argument /my/directory where this directory contains file.txt I expect that I'd be able to download file.txt at the URL http://localhost:8000/static/file.txt, but this returns an HTTP 404.

How do I write this minimal static file server script?

Upvotes: 0

Views: 445

Answers (2)

M.O.
M.O.

Reputation: 2986

When you call uvicorn.run(app="my_package:server"), it actually starts a separate process where my_package is imported. Therefore, everything inside if __name__ == "__main__": will not be run in the uvicorn process, so your directory will never be mounted.

One possible solution would be getting the directory from an environment variable, which is set from a small bash script:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

server = FastAPI()

directory = os.getenv("DIRECTORY")
server.mount("/static", StaticFiles(directory=directory), name="static")

start.sh:

#!/usr/bin/env bash
DIRECTORY=$1 uvicorn mypackage:server

Upvotes: 0

MatsLindh
MatsLindh

Reputation: 52862

The assumption I made about sys.argv not being available when uvicorn loads your module is wrong, so it should work as you expect by moving your static setup outside of the __main__ guard:

import uvicorn
import sys
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

server = FastAPI()
directory = sys.argv[1]
server.mount("/static", StaticFiles(directory=directory), name="static")

if __name__ == "__main__":
    uvicorn.run(app="my_package:server")

Upvotes: 1

Related Questions